<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skodak</id>
	<title>MoodleDocs - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://docs.moodle.org/dev/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Skodak"/>
	<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/Special:Contributions/Skodak"/>
	<updated>2026-07-30T23:24:17Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=48464</id>
		<title>Setting up PhpStorm</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=48464"/>
		<updated>2015-08-26T03:12:59Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* OS X */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.jetbrains.com/phpstorm/ PhpStorm] is a commercial IDE, it is arguably the best IDE for PHP developers with features such as code completion, code inspection, phpunit support, Behat support, database editor, debugger, etc.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===OS X===&lt;br /&gt;
&lt;br /&gt;
Do not install Java manually, download a PhpStorm package with bundled java instead.&lt;br /&gt;
&lt;br /&gt;
==General settings==&lt;br /&gt;
&lt;br /&gt;
* Disable missing @throws tag warning in &amp;quot;Preferences / Project Settings / Inspections / PHP / PHPDoc&amp;quot;&lt;br /&gt;
* Strip trailing whitespace from &amp;quot;Modified Lines&amp;quot; in &amp;quot;Preferences / IDE Settings / Editor&amp;quot;&lt;br /&gt;
* Show line numbers in &amp;quot;Preferences / IDE Settings / Editor / Appearance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Bug tracker integration==&lt;br /&gt;
&lt;br /&gt;
* Add tracker linking in &amp;quot;Preferences / Version control / Issue Navigation&amp;quot;&lt;br /&gt;
* Set Issue ID to &amp;quot;MDL-\d+&amp;quot; and Issue link to &amp;quot;https://tracker.moodle.org/browse/$0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Code formatting==&lt;br /&gt;
&lt;br /&gt;
* Setup coding style to use all rules from [[Coding style]] in &amp;quot;Preferences / Project Settings / Code Style / PHP&amp;quot;  - this will allow you to use automatic code formatting and it does nice code formatting on copy/paste.&lt;br /&gt;
* Set line separator to Unix in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
* Set right margin to 132 or 180 in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Moodle code checker==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PHPUnit integration==&lt;br /&gt;
# Install [[PHPUnit]] via Composer &lt;br /&gt;
# Tell PHPStorm where is composer - go to &amp;quot;Preferences / PHP / Composer&amp;quot;, fill in &amp;quot;Path to PHP executable&amp;quot;, &amp;quot;Path to composer.phar&amp;quot;, &amp;quot;Path to composer.json&amp;quot; and make sure the option &amp;quot;Add packages as libraries&amp;quot; is enabled.&lt;br /&gt;
# Go to &amp;quot;Run / Edit configurations&amp;quot;&lt;br /&gt;
# Add PHPUnit configuration by clicking on &amp;quot;+&amp;quot;&lt;br /&gt;
# Click &amp;quot;Use alternative configuration file&amp;quot; and select your phpunit.xml file&lt;br /&gt;
# Go to &amp;quot;Run / Run ...&amp;quot; and select your new PHPUnit configuration to run&lt;br /&gt;
&lt;br /&gt;
==Database editor==&lt;br /&gt;
# Click on the &amp;quot;Database&amp;quot; tab to see the database window&lt;br /&gt;
# Click &amp;quot;+&amp;quot; in the top left and add &amp;quot;Database source&amp;quot; for your database&lt;br /&gt;
# Note: click on the link to download the necessary drivers directly from IDE&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48310</id>
		<title>Server clustering improvements proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48310"/>
		<updated>2015-07-21T02:07:26Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* $CFG-&amp;gt;tempdir */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.6}}&lt;br /&gt;
&lt;br /&gt;
Author: [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 4 July 2013 (WST) and others&lt;br /&gt;
&lt;br /&gt;
MDL-40979 was raised to group together this issues that are raised out of this document and the discussion.  All issues should be linked to that EPIC.&lt;br /&gt;
&lt;br /&gt;
==Cluster configuration requirements==&lt;br /&gt;
&lt;br /&gt;
# Cluster node clocks must be synchronised with difference &amp;lt;1s.&lt;br /&gt;
# Database setup must be ACID compliant.&lt;br /&gt;
# $CFG-&amp;gt;dataroot must be a shared directory.&lt;br /&gt;
# $CFG-&amp;gt;cachedir must be a shared directory.&lt;br /&gt;
&lt;br /&gt;
Note that these last two often cause confusion.  These directories must be shared because Moodle code relies on that, all cluster nodes must see the same data there.  Cluster headaches do occur when there is a lot of data in here, so our aim is to REDUCE dependence on shared caches as much as possible, technically it is not possible to have only local caches.&lt;br /&gt;
&lt;br /&gt;
==config.php settings==&lt;br /&gt;
Each node in cluster may use local set of php files including config.php, these may be synchronised via git for example, rsync, etc.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;wwwroot===&lt;br /&gt;
It must be the same on all nodes, it must be the public facing URL. It cannot be dynamic.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;sslproxy===&lt;br /&gt;
Enable if you have https:// wwwroot but the SSL is not done by Apache.&lt;br /&gt;
&lt;br /&gt;
Do not forget to enable &#039;&#039;Secure cookies only&#039;&#039; to make your site really secure, without it cookie stealing is still trivial.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;reverseproxy===&lt;br /&gt;
Enable if your nodes are accessed via different URL. Please note that it is not compatible with $CFG-&amp;gt;loginhttps.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dirroot===&lt;br /&gt;
It is strongly recommended that $CFG-&amp;gt;dirroot (which is automatically set via realpath(config.php)) contains the same path on all nodes. It does not need to point to the same shared directory though. The reason is that some some low level code may use the dirroot value for cache invalidation.&lt;br /&gt;
&lt;br /&gt;
The simplest solution is to have the same directory structure on each cluster node and synchronise these during each upgrade.&lt;br /&gt;
&lt;br /&gt;
The dirroot should be always read only for apache process because otherwise built in add-on installation and plugin uninstallation would get the nodes out of sync.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dataroot===&lt;br /&gt;
&lt;br /&gt;
This &#039;&#039;&#039;MUST&#039;&#039;&#039; be a shared directory where each cluster node is accessing the files directly. It must be very reliable, administrators cannot manipulate files directly there.&lt;br /&gt;
&lt;br /&gt;
Locking support is not required, if any code tries to use file locks in dataroot outside of cachedir or muc directory it is a bug.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;tempdir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;tempdir is a directory that must be shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The contents of this directory may be deleted if there is no pending HTTP request.&lt;br /&gt;
&lt;br /&gt;
In 2.9 and later use new request directory instead where possible.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;cachedir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;cachedir is a directory shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Cache invalidation is done by deleting or overriding of existing files, this needs to be automatically replicated to all cluster nodes, otherwise the cache may return stale or invalid data which often leads to fatal errors or data loss.&lt;br /&gt;
&lt;br /&gt;
The existing documentation clearly states that this directory must be shared, all existing code including add-ons may expect this, it is therefore not possible to change this requirement without breaking backwards compatibility.&lt;br /&gt;
&lt;br /&gt;
Please note that MUC caches have similar problem, the current design expects that each node is contacting the same caches. It should be possible to create new MUC backends that do not require shared cache backends in a way similar to the proposed $CFG-&amp;gt;localcachedir .&lt;br /&gt;
&lt;br /&gt;
You can safely purge cachedir when restarting the whole cluster, you may get some notices or temporary errors if you purge this directory while other requests are active.&lt;br /&gt;
&lt;br /&gt;
Netspot admins came up with a hypothesis that &amp;quot;cachedir does not have to be shared&amp;quot;, it is easy to disapprove it - we need to find a single case where the sharing is required. Let&#039;s look at the caching of data from config table in $CFG global variable. If one node modifies CFG value others would not be notified about the change and would continue using stale value. Workaround seems to be to create a new revision number that is incremented after any change in $CFG and share it with all nodes. The question is where to put it so that it is shared by all nodes? Storing it in database would require one extra read on each page and one extra write on each update, that is not acceptable. We cannot put the revision into a shared filesystem because we would not have it. We cannot rely on presence of memcache or any shared data storage in default installation either. In most other cases we store the revision flags in CFG itself, it is clearly not possible in this case because it would not be shared by nodes. Somebody said &amp;quot;but it works without sharing for all our clients for at least a year&amp;quot; - that does not prove anything, you would have to make sure it works also for everybody else with all add-ons, custom modifications and minimal number of PHP extensions required by Moodle.&lt;br /&gt;
&lt;br /&gt;
In any case cachedir is shared by definition since the beginning of its existence, it is a fact that developers writing code may depend on. If you do not like it then use local cache dir.&lt;br /&gt;
&lt;br /&gt;
== New $CFG-&amp;gt;localcachedir==&lt;br /&gt;
&lt;br /&gt;
The difference from normal $CFG-&amp;gt;cachedir is that the directory does not have to be shared by all cluster nodes, the files stored in $CFG-&amp;gt;localcachedir MUST NOT change! Default directory is &amp;quot;$CFG-&amp;gt;dataroot/localcache&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All files there must use unique revision numbers or hashes because the cached data cannot be invalidated by other mechanism - it will support only adding of new files, but no file deletes or overrides. The $CFG-&amp;gt;localcachedir will be growing over time, all local cache files will be deleted during purge_all_caches() (automatically during upgrades).&lt;br /&gt;
&lt;br /&gt;
When using hashes please make sure the number of files in one directory is kept to some reasonable number because some filesystems might have problems with large number of files in one directory.&lt;br /&gt;
&lt;br /&gt;
Note that some caches cannot be easily moved to localcachedir because you need a reliable revision number here, but sometimes it is either not possible or very slow because you need to store the revision number somewhere and you need to bump up the revision number after any change and you would need to store it in database. Caching is not free, each usage must be carefully evaluated.&lt;br /&gt;
&lt;br /&gt;
Design requirements:&lt;br /&gt;
* Everything must be automatic without extra administrative overhead.&lt;br /&gt;
* purge_all_caches() on any node triggers local cache purging on all other nodes before adding any new files there.&lt;br /&gt;
* Performance on standalone servers must not be worse.&lt;br /&gt;
&lt;br /&gt;
Usage restrictions:&lt;br /&gt;
* No file deletes&lt;br /&gt;
* No file modifications&lt;br /&gt;
* No file overwriting&lt;br /&gt;
* Soft limit on maximum number of files in one directory (few thousands)&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* Clustered servers may use fast local filesystem such as tempfs.&lt;br /&gt;
* No opcache cache invalidation problems if php files included from localcachedir (because the files must not change).&lt;br /&gt;
&lt;br /&gt;
Candidates for migration from $CFG-&amp;gt;cachedir:&lt;br /&gt;
* JS cache MDL-40546 &lt;br /&gt;
* Theme caches MDL-40563&lt;br /&gt;
* HTMLPurifier cache MDL-41017&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40545.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Component cache==&lt;br /&gt;
&lt;br /&gt;
Class core_component is using a $CFG-&amp;gt;cachedir/core_component.php cache that contains a complete list of all plugins and all classes present in $CFG-&amp;gt;dirroot. The implementation must be as fast as possible and the results must be extremely reliable.&lt;br /&gt;
&lt;br /&gt;
The cache is automatically invalidated on admin/index.php page and during installation and every upgrade. It is also cleared during purge_all_caches(), but that is only a side effect of storing it in cachedir and it is not required.&lt;br /&gt;
&lt;br /&gt;
core_component class cannot depend on database, MUC or any core libraries - that is the reason why there cannot be any revision flag, there is nowhere to store it, the sha1() of that file content would be the revision. But we would have to go through all plugin directories to find out if it was changed or what revision to use. There are only two options - either we store this file in shared cache or admin invalidates this cache manually, the second option it clearly not acceptable for standard installations.&lt;br /&gt;
&lt;br /&gt;
===Alternative component cache location===&lt;br /&gt;
&lt;br /&gt;
This is useful for clustered installations only. Typically the $CFG-&amp;gt;alternative_component_cache = &#039;/local/cache/dir/core_component.php&#039; would point to local node cache directory. Before upgrade the administrator would have to manually execute following on each node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ php admin/cli/alternative_component_cache.php --rebuild&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively you could put the cache file directly into dirroot and distribute it together with new PHP source files. Yet another possibility would be to purge all local caches on all nodes before upgrade or simply change the script name in config.php on all nodes before upgrade.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40475.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==MUC and clustering==&lt;br /&gt;
&lt;br /&gt;
At present administrators are free to create new stores and assign them to existing definitions of each cache. Unfortunately the documentation or admin UI does not mention that by default all those definitions require cache stores to be shared by all cluster nodes! Some cache keys may include revision numbers and all settings which makes them compatible with local caches, we need to document it somewhere.&lt;br /&gt;
&lt;br /&gt;
I would like to propose a new flag in cache definition &#039;&#039;&#039;localcache&#039;&#039;&#039; which would indicate that it is safe to use local cache stores on cluster nodes. For now we can at least document it in db/caches.php as inline comments. This information should be clearly visible on the cache store/definition settings page. Maybe we could add setting to cache stores which indicates if it is a shared or local cache. The only potential problem is that it might confuse admins that know little about clustering or cache invalidation.&lt;br /&gt;
&lt;br /&gt;
In theory the installation could create two file stores by default - one using current $CFG-&amp;gt;cachedir and second using $CFG-&amp;gt;localcachedir and assign them to definitions based on localcache flag. This could help new admins when setting up clusters, all they would have to do would be to move localcachedir to cluster node ram disks.&lt;br /&gt;
&lt;br /&gt;
Note that MODE_REQUEST are local by definition and MODE_SESSION are always shared (because session is shared), this means we need to consider only MODE_APPLICATION definitions here.&lt;br /&gt;
&lt;br /&gt;
List of caches/definitions that are compatible with local caching on cluster nodes:&lt;br /&gt;
* core htmlpurifier - MDL-41017&lt;br /&gt;
* core string - MDL-41019&lt;br /&gt;
* core langmenucache - MDL-41019&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
==Theme caching==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;All large installs and clusters should use transparent proxies (such as Cloudflare or custom nginx).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Small installs without transparent caches (or when in designer mode) depend on performance of theme serving scripts (theme/image.php, theme/styles.php, etc.).&lt;br /&gt;
&lt;br /&gt;
The serving scripts receive revision number in URL, this solves the problem with cache invalidation. We are not using MUC there intentionally because we are not in already open HTTP request with database connection and all standard libraries already loaded, the data there must be served quickly with as little memory and CPU cycles as possible.&lt;br /&gt;
&lt;br /&gt;
The standard theme caches may be stored in local node caches, we could store the theme caches in $CFG-&amp;gt;localcachedir/theme/ directory.&lt;br /&gt;
&lt;br /&gt;
Theme designer mode is not using any revisions. For performance reasons we must use some cache, the only option seems to be the standard shared $CFG-&amp;gt;cachedir/theme/. Using localcachedir is not an option here, we might try to improve the general performance here and if possible skip all caching in theme designer mode.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Theme caching was improved in 2.6, it is using localcachedir, see MDL-40563.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Javascript caching==&lt;br /&gt;
&lt;br /&gt;
We used JS caching in cachedir for performance reasons because we were doing on-the-fly JS compression. Ideally we should switch to build system for all JS files and store the minimised files along the source files in git and just add proper headers in lib/javascript.php script.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;JavaScript caching was improved in 2.6, it is using localcachedir, see MDL-40546.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Language installation and customisations==&lt;br /&gt;
&lt;br /&gt;
Each string is constructed from the following sources:&lt;br /&gt;
# en pack in plugin/core - always distributed with plugin&lt;br /&gt;
# current language pack, including all its parents - downloaded into $CFG-&amp;gt;langotherroot (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
# local string tweaks - created with tool_customlang, stored in $CFG-&amp;gt;langlocalroot in directories with &amp;quot;_local&amp;quot; suffix (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
&lt;br /&gt;
We can use existing $CFG-&amp;gt;langrev in cache keys to add support for local lang caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
Please note that language packs and local modifications are PHP files, you need to verify file timestamps or blacklist these locations in OP code caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
There is another cache for available translations which is stored in $CFG-&amp;gt;langmenucachefile, we can move this to MUC and allow local node caches too.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Lang caching is improved in 2.6, see MDL-41019.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==PHP accelerators==&lt;br /&gt;
&lt;br /&gt;
Potential problems:&lt;br /&gt;
* file time stamps must be verified in Moodle 2.5 and bellow&lt;br /&gt;
&lt;br /&gt;
===opcache extension===&lt;br /&gt;
&lt;br /&gt;
Standard &#039;&#039;opcache&#039;&#039; extension is strongly recommended for Moodle 2.6 forward, it is the only solution officially supported by PHP developers. Starting with Moodle 2.6 we should recommend the opcache extension during environment test. All other PHP accelerators should be actively discourage (warning on environment page).&lt;br /&gt;
&lt;br /&gt;
Please note that HQ developers are not required to test current stable branches with any PHP accelerators.&lt;br /&gt;
&lt;br /&gt;
The goal is to use opcaching without checking of file modification times - problem here are dynamically generated PHP files that are stored in dataroot (component cache, lang packs, local lang modifications, muc config, etc.), we need to invalidate the op code cache explicitly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;OPcache extension is fully supported in Moodle 2.6, see MDL-40415.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Browser sessions==&lt;br /&gt;
&lt;br /&gt;
User session data should be stored in some reliable shared storage, all cluster nodes need to operate with the same session data, the data must not be disappearing randomly.&lt;br /&gt;
&lt;br /&gt;
All sessions drivers should be updating the list of active sessions in the session table, the serialised session data can be stored somewhere else.&lt;br /&gt;
&lt;br /&gt;
Moodle session drivers need to support some special features:&lt;br /&gt;
* Session timeout is controlled from Moodle code  - it is required for reliable SSO implementations.&lt;br /&gt;
* We need to be able to query list of all sessions belonging to one user - this allows us to logout deleted users (for example spammers).&lt;br /&gt;
* Locking is strongly recommended because race conditions may create hard to diagnose problems - users need to logout/login to recover from these problems.&lt;br /&gt;
* Sometimes the structure of session data changes and then upgrade requires logout of all active users.&lt;br /&gt;
* Some add-ons/patches use the information from sessions table to implement limits for concurrent user logins.&lt;br /&gt;
&lt;br /&gt;
By default new installations are using a databases session driver with locking support. There is a legacy file based session driver for sites that cannot use db sessions, but it does not support any advanced features above and is therefore not recommended.&lt;br /&gt;
&lt;br /&gt;
PHP lacks a reliable cross-platform locking support, this is one if major problems when implementing new session drivers. Without locking the changes in user session may be lost resulting in hard to diagnose problems. Another problem when adding new session driver is that the sessions table needs to be updated at least once per minute.&lt;br /&gt;
&lt;br /&gt;
* MDL-31501 is the ticket for implementing a workable memcached session storage backend.&lt;br /&gt;
* MDL-25500 is the ticket to implement a general locking mechanism.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Not implemented yet.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==File pool==&lt;br /&gt;
&lt;br /&gt;
At present there is a filedir in dataroot where we store all contents of files in Moodle. Theoretically the code could be abstracted to allow storage of file contents in non-filesystem storage.&lt;br /&gt;
&lt;br /&gt;
The default location is $CFG-&amp;gt;dataroot/filedir, alterantive value can be specified in $CFG-&amp;gt;filedir setting. $CFG-&amp;gt;filedir does not require locking, it may be outside of $CFG-&amp;gt;dataroot. The file system/sharing may use very aggressive caching techniques because the files never change, the node needs to contact the master when writing or on cache miss. &lt;br /&gt;
&lt;br /&gt;
The original idea was to have a setting for preventing of file removals from the $CFG-&amp;gt;filedir directory, this would allow you to put files from multiple installations into just one giant file pool that could be replicated to all nodes - files would be only added there and never deleted automatically. The only potential problem is size of this huge dir and there would have to be a special new tool that exports used files from one site to another that is not using the shared file pool. The setting was supposed to be in file_storage::deleted_file_cleanup() method (one if that simply exits method).&lt;br /&gt;
&lt;br /&gt;
MDL-40528 contains a refactoring of trashdir operations that could help anybody who decides to reimplement the fole_storage class. The sample backup recovery class might be also user for simple local filedir cache on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
==Installation procedure==&lt;br /&gt;
&lt;br /&gt;
 1. Build a 1 node cluster&lt;br /&gt;
   - NFS backing storage&lt;br /&gt;
   - Configuration parameters like there are lots of nodes&lt;br /&gt;
   - Database setup on own host and such.&lt;br /&gt;
   - Build load balancer configuration.&lt;br /&gt;
   - Run moodle install cli&lt;br /&gt;
   - Add appropriate configuration items to get the system working behind load balancer&lt;br /&gt;
 2. Add more nodes to the cluster by replicating the first node.&lt;br /&gt;
&lt;br /&gt;
==Upgrade procedure==&lt;br /&gt;
&lt;br /&gt;
===Sample estimation===&lt;br /&gt;
# tweak load balancer to redirect all users to some static non-moodle page&lt;br /&gt;
# shutdown all nodes except one&lt;br /&gt;
# optionally enable CLI maintenance mode&lt;br /&gt;
# upload new PHP files to all nodes&lt;br /&gt;
# rebuild component cache if alternative read only location used&lt;br /&gt;
# upgrade the node from CLI&lt;br /&gt;
# disable CLI maintenance mode&lt;br /&gt;
# start other nodes (this guarantees localcachedir purging)&lt;br /&gt;
# enable normal operation&lt;br /&gt;
&lt;br /&gt;
===Large in-house NFS backend VM upgrade===&lt;br /&gt;
CLI Maintenance mode may be useful, but either way, you we stop all web nodes and also ensure that the current cron run has finished, otherwise you can get into all sort of strife.  Trying to do an upgrade during the forum digest time or stats run is not possible.  Both can run for &amp;gt;1 hour.&lt;br /&gt;
&lt;br /&gt;
Opcode resets are a problem when moving from CLI to apache for fcgi.  As I understand it, each has its own opcache location and that needs to be managed properly.  Hence the just shutdown the web nodes to force resets.&lt;br /&gt;
&lt;br /&gt;
 1. Disable all users except administrator who is upgrading. (This is done via IP at our load balancer)&lt;br /&gt;
 2. Stop apache on all nodes&lt;br /&gt;
 3. Stop cron from running and ensure it&#039;s finished.&lt;br /&gt;
&lt;br /&gt;
 We then ignore the fact we are in a cluster for a few instructions and operate on one node.&lt;br /&gt;
&lt;br /&gt;
 3.1 Backup/snapshot database and dataroot&lt;br /&gt;
&lt;br /&gt;
 4. Upload new php files to &#039;master&#039; node.&lt;br /&gt;
 5. Upgrade &#039;master&#039; node.  admin/cli/upgrade.php&lt;br /&gt;
 6. Start up &#039;master&#039; node apache, and test with admin login.&lt;br /&gt;
 7. If all successful, copy code to all other nodes&lt;br /&gt;
 8. Turn on other nodes.&lt;br /&gt;
 9. Browse around a bit to ensure you have warmed the opcache (cold cache can cause floods with 500+ users logging in within 10 seconds of go-live)&lt;br /&gt;
 10. Turn the system back on for all users.&lt;br /&gt;
&lt;br /&gt;
==Database clustering==&lt;br /&gt;
&lt;br /&gt;
Anything ACID compliant should be ok. For example even-odd master-master MySQL is not ok.&lt;br /&gt;
&lt;br /&gt;
TODO: add descriptions of ACID compliant DB cluster setups&lt;br /&gt;
&lt;br /&gt;
==More information==&lt;br /&gt;
&lt;br /&gt;
* [http://thamblings.blogspot.cz/2013/07/deploying-moodle-continued.html Deploying Moodle]&lt;br /&gt;
* [https://docs.moodle.org/25/en/Server_cluster Server cluster (user docs)]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48309</id>
		<title>Server clustering improvements proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48309"/>
		<updated>2015-07-21T02:06:58Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Sample estimation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.6}}&lt;br /&gt;
&lt;br /&gt;
Author: [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 4 July 2013 (WST) and others&lt;br /&gt;
&lt;br /&gt;
MDL-40979 was raised to group together this issues that are raised out of this document and the discussion.  All issues should be linked to that EPIC.&lt;br /&gt;
&lt;br /&gt;
==Cluster configuration requirements==&lt;br /&gt;
&lt;br /&gt;
# Cluster node clocks must be synchronised with difference &amp;lt;1s.&lt;br /&gt;
# Database setup must be ACID compliant.&lt;br /&gt;
# $CFG-&amp;gt;dataroot must be a shared directory.&lt;br /&gt;
# $CFG-&amp;gt;cachedir must be a shared directory.&lt;br /&gt;
&lt;br /&gt;
Note that these last two often cause confusion.  These directories must be shared because Moodle code relies on that, all cluster nodes must see the same data there.  Cluster headaches do occur when there is a lot of data in here, so our aim is to REDUCE dependence on shared caches as much as possible, technically it is not possible to have only local caches.&lt;br /&gt;
&lt;br /&gt;
==config.php settings==&lt;br /&gt;
Each node in cluster may use local set of php files including config.php, these may be synchronised via git for example, rsync, etc.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;wwwroot===&lt;br /&gt;
It must be the same on all nodes, it must be the public facing URL. It cannot be dynamic.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;sslproxy===&lt;br /&gt;
Enable if you have https:// wwwroot but the SSL is not done by Apache.&lt;br /&gt;
&lt;br /&gt;
Do not forget to enable &#039;&#039;Secure cookies only&#039;&#039; to make your site really secure, without it cookie stealing is still trivial.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;reverseproxy===&lt;br /&gt;
Enable if your nodes are accessed via different URL. Please note that it is not compatible with $CFG-&amp;gt;loginhttps.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dirroot===&lt;br /&gt;
It is strongly recommended that $CFG-&amp;gt;dirroot (which is automatically set via realpath(config.php)) contains the same path on all nodes. It does not need to point to the same shared directory though. The reason is that some some low level code may use the dirroot value for cache invalidation.&lt;br /&gt;
&lt;br /&gt;
The simplest solution is to have the same directory structure on each cluster node and synchronise these during each upgrade.&lt;br /&gt;
&lt;br /&gt;
The dirroot should be always read only for apache process because otherwise built in add-on installation and plugin uninstallation would get the nodes out of sync.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dataroot===&lt;br /&gt;
&lt;br /&gt;
This &#039;&#039;&#039;MUST&#039;&#039;&#039; be a shared directory where each cluster node is accessing the files directly. It must be very reliable, administrators cannot manipulate files directly there.&lt;br /&gt;
&lt;br /&gt;
Locking support is not required, if any code tries to use file locks in dataroot outside of cachedir or muc directory it is a bug.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;tempdir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;tempdir is a directory that must be shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The contents of this directory may be deleted if there is no pending HTTP request.&lt;br /&gt;
&lt;br /&gt;
In 2.9 and later user request directory where possible.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;cachedir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;cachedir is a directory shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Cache invalidation is done by deleting or overriding of existing files, this needs to be automatically replicated to all cluster nodes, otherwise the cache may return stale or invalid data which often leads to fatal errors or data loss.&lt;br /&gt;
&lt;br /&gt;
The existing documentation clearly states that this directory must be shared, all existing code including add-ons may expect this, it is therefore not possible to change this requirement without breaking backwards compatibility.&lt;br /&gt;
&lt;br /&gt;
Please note that MUC caches have similar problem, the current design expects that each node is contacting the same caches. It should be possible to create new MUC backends that do not require shared cache backends in a way similar to the proposed $CFG-&amp;gt;localcachedir .&lt;br /&gt;
&lt;br /&gt;
You can safely purge cachedir when restarting the whole cluster, you may get some notices or temporary errors if you purge this directory while other requests are active.&lt;br /&gt;
&lt;br /&gt;
Netspot admins came up with a hypothesis that &amp;quot;cachedir does not have to be shared&amp;quot;, it is easy to disapprove it - we need to find a single case where the sharing is required. Let&#039;s look at the caching of data from config table in $CFG global variable. If one node modifies CFG value others would not be notified about the change and would continue using stale value. Workaround seems to be to create a new revision number that is incremented after any change in $CFG and share it with all nodes. The question is where to put it so that it is shared by all nodes? Storing it in database would require one extra read on each page and one extra write on each update, that is not acceptable. We cannot put the revision into a shared filesystem because we would not have it. We cannot rely on presence of memcache or any shared data storage in default installation either. In most other cases we store the revision flags in CFG itself, it is clearly not possible in this case because it would not be shared by nodes. Somebody said &amp;quot;but it works without sharing for all our clients for at least a year&amp;quot; - that does not prove anything, you would have to make sure it works also for everybody else with all add-ons, custom modifications and minimal number of PHP extensions required by Moodle.&lt;br /&gt;
&lt;br /&gt;
In any case cachedir is shared by definition since the beginning of its existence, it is a fact that developers writing code may depend on. If you do not like it then use local cache dir.&lt;br /&gt;
&lt;br /&gt;
== New $CFG-&amp;gt;localcachedir==&lt;br /&gt;
&lt;br /&gt;
The difference from normal $CFG-&amp;gt;cachedir is that the directory does not have to be shared by all cluster nodes, the files stored in $CFG-&amp;gt;localcachedir MUST NOT change! Default directory is &amp;quot;$CFG-&amp;gt;dataroot/localcache&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All files there must use unique revision numbers or hashes because the cached data cannot be invalidated by other mechanism - it will support only adding of new files, but no file deletes or overrides. The $CFG-&amp;gt;localcachedir will be growing over time, all local cache files will be deleted during purge_all_caches() (automatically during upgrades).&lt;br /&gt;
&lt;br /&gt;
When using hashes please make sure the number of files in one directory is kept to some reasonable number because some filesystems might have problems with large number of files in one directory.&lt;br /&gt;
&lt;br /&gt;
Note that some caches cannot be easily moved to localcachedir because you need a reliable revision number here, but sometimes it is either not possible or very slow because you need to store the revision number somewhere and you need to bump up the revision number after any change and you would need to store it in database. Caching is not free, each usage must be carefully evaluated.&lt;br /&gt;
&lt;br /&gt;
Design requirements:&lt;br /&gt;
* Everything must be automatic without extra administrative overhead.&lt;br /&gt;
* purge_all_caches() on any node triggers local cache purging on all other nodes before adding any new files there.&lt;br /&gt;
* Performance on standalone servers must not be worse.&lt;br /&gt;
&lt;br /&gt;
Usage restrictions:&lt;br /&gt;
* No file deletes&lt;br /&gt;
* No file modifications&lt;br /&gt;
* No file overwriting&lt;br /&gt;
* Soft limit on maximum number of files in one directory (few thousands)&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* Clustered servers may use fast local filesystem such as tempfs.&lt;br /&gt;
* No opcache cache invalidation problems if php files included from localcachedir (because the files must not change).&lt;br /&gt;
&lt;br /&gt;
Candidates for migration from $CFG-&amp;gt;cachedir:&lt;br /&gt;
* JS cache MDL-40546 &lt;br /&gt;
* Theme caches MDL-40563&lt;br /&gt;
* HTMLPurifier cache MDL-41017&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40545.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Component cache==&lt;br /&gt;
&lt;br /&gt;
Class core_component is using a $CFG-&amp;gt;cachedir/core_component.php cache that contains a complete list of all plugins and all classes present in $CFG-&amp;gt;dirroot. The implementation must be as fast as possible and the results must be extremely reliable.&lt;br /&gt;
&lt;br /&gt;
The cache is automatically invalidated on admin/index.php page and during installation and every upgrade. It is also cleared during purge_all_caches(), but that is only a side effect of storing it in cachedir and it is not required.&lt;br /&gt;
&lt;br /&gt;
core_component class cannot depend on database, MUC or any core libraries - that is the reason why there cannot be any revision flag, there is nowhere to store it, the sha1() of that file content would be the revision. But we would have to go through all plugin directories to find out if it was changed or what revision to use. There are only two options - either we store this file in shared cache or admin invalidates this cache manually, the second option it clearly not acceptable for standard installations.&lt;br /&gt;
&lt;br /&gt;
===Alternative component cache location===&lt;br /&gt;
&lt;br /&gt;
This is useful for clustered installations only. Typically the $CFG-&amp;gt;alternative_component_cache = &#039;/local/cache/dir/core_component.php&#039; would point to local node cache directory. Before upgrade the administrator would have to manually execute following on each node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ php admin/cli/alternative_component_cache.php --rebuild&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively you could put the cache file directly into dirroot and distribute it together with new PHP source files. Yet another possibility would be to purge all local caches on all nodes before upgrade or simply change the script name in config.php on all nodes before upgrade.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40475.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==MUC and clustering==&lt;br /&gt;
&lt;br /&gt;
At present administrators are free to create new stores and assign them to existing definitions of each cache. Unfortunately the documentation or admin UI does not mention that by default all those definitions require cache stores to be shared by all cluster nodes! Some cache keys may include revision numbers and all settings which makes them compatible with local caches, we need to document it somewhere.&lt;br /&gt;
&lt;br /&gt;
I would like to propose a new flag in cache definition &#039;&#039;&#039;localcache&#039;&#039;&#039; which would indicate that it is safe to use local cache stores on cluster nodes. For now we can at least document it in db/caches.php as inline comments. This information should be clearly visible on the cache store/definition settings page. Maybe we could add setting to cache stores which indicates if it is a shared or local cache. The only potential problem is that it might confuse admins that know little about clustering or cache invalidation.&lt;br /&gt;
&lt;br /&gt;
In theory the installation could create two file stores by default - one using current $CFG-&amp;gt;cachedir and second using $CFG-&amp;gt;localcachedir and assign them to definitions based on localcache flag. This could help new admins when setting up clusters, all they would have to do would be to move localcachedir to cluster node ram disks.&lt;br /&gt;
&lt;br /&gt;
Note that MODE_REQUEST are local by definition and MODE_SESSION are always shared (because session is shared), this means we need to consider only MODE_APPLICATION definitions here.&lt;br /&gt;
&lt;br /&gt;
List of caches/definitions that are compatible with local caching on cluster nodes:&lt;br /&gt;
* core htmlpurifier - MDL-41017&lt;br /&gt;
* core string - MDL-41019&lt;br /&gt;
* core langmenucache - MDL-41019&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
==Theme caching==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;All large installs and clusters should use transparent proxies (such as Cloudflare or custom nginx).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Small installs without transparent caches (or when in designer mode) depend on performance of theme serving scripts (theme/image.php, theme/styles.php, etc.).&lt;br /&gt;
&lt;br /&gt;
The serving scripts receive revision number in URL, this solves the problem with cache invalidation. We are not using MUC there intentionally because we are not in already open HTTP request with database connection and all standard libraries already loaded, the data there must be served quickly with as little memory and CPU cycles as possible.&lt;br /&gt;
&lt;br /&gt;
The standard theme caches may be stored in local node caches, we could store the theme caches in $CFG-&amp;gt;localcachedir/theme/ directory.&lt;br /&gt;
&lt;br /&gt;
Theme designer mode is not using any revisions. For performance reasons we must use some cache, the only option seems to be the standard shared $CFG-&amp;gt;cachedir/theme/. Using localcachedir is not an option here, we might try to improve the general performance here and if possible skip all caching in theme designer mode.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Theme caching was improved in 2.6, it is using localcachedir, see MDL-40563.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Javascript caching==&lt;br /&gt;
&lt;br /&gt;
We used JS caching in cachedir for performance reasons because we were doing on-the-fly JS compression. Ideally we should switch to build system for all JS files and store the minimised files along the source files in git and just add proper headers in lib/javascript.php script.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;JavaScript caching was improved in 2.6, it is using localcachedir, see MDL-40546.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Language installation and customisations==&lt;br /&gt;
&lt;br /&gt;
Each string is constructed from the following sources:&lt;br /&gt;
# en pack in plugin/core - always distributed with plugin&lt;br /&gt;
# current language pack, including all its parents - downloaded into $CFG-&amp;gt;langotherroot (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
# local string tweaks - created with tool_customlang, stored in $CFG-&amp;gt;langlocalroot in directories with &amp;quot;_local&amp;quot; suffix (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
&lt;br /&gt;
We can use existing $CFG-&amp;gt;langrev in cache keys to add support for local lang caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
Please note that language packs and local modifications are PHP files, you need to verify file timestamps or blacklist these locations in OP code caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
There is another cache for available translations which is stored in $CFG-&amp;gt;langmenucachefile, we can move this to MUC and allow local node caches too.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Lang caching is improved in 2.6, see MDL-41019.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==PHP accelerators==&lt;br /&gt;
&lt;br /&gt;
Potential problems:&lt;br /&gt;
* file time stamps must be verified in Moodle 2.5 and bellow&lt;br /&gt;
&lt;br /&gt;
===opcache extension===&lt;br /&gt;
&lt;br /&gt;
Standard &#039;&#039;opcache&#039;&#039; extension is strongly recommended for Moodle 2.6 forward, it is the only solution officially supported by PHP developers. Starting with Moodle 2.6 we should recommend the opcache extension during environment test. All other PHP accelerators should be actively discourage (warning on environment page).&lt;br /&gt;
&lt;br /&gt;
Please note that HQ developers are not required to test current stable branches with any PHP accelerators.&lt;br /&gt;
&lt;br /&gt;
The goal is to use opcaching without checking of file modification times - problem here are dynamically generated PHP files that are stored in dataroot (component cache, lang packs, local lang modifications, muc config, etc.), we need to invalidate the op code cache explicitly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;OPcache extension is fully supported in Moodle 2.6, see MDL-40415.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Browser sessions==&lt;br /&gt;
&lt;br /&gt;
User session data should be stored in some reliable shared storage, all cluster nodes need to operate with the same session data, the data must not be disappearing randomly.&lt;br /&gt;
&lt;br /&gt;
All sessions drivers should be updating the list of active sessions in the session table, the serialised session data can be stored somewhere else.&lt;br /&gt;
&lt;br /&gt;
Moodle session drivers need to support some special features:&lt;br /&gt;
* Session timeout is controlled from Moodle code  - it is required for reliable SSO implementations.&lt;br /&gt;
* We need to be able to query list of all sessions belonging to one user - this allows us to logout deleted users (for example spammers).&lt;br /&gt;
* Locking is strongly recommended because race conditions may create hard to diagnose problems - users need to logout/login to recover from these problems.&lt;br /&gt;
* Sometimes the structure of session data changes and then upgrade requires logout of all active users.&lt;br /&gt;
* Some add-ons/patches use the information from sessions table to implement limits for concurrent user logins.&lt;br /&gt;
&lt;br /&gt;
By default new installations are using a databases session driver with locking support. There is a legacy file based session driver for sites that cannot use db sessions, but it does not support any advanced features above and is therefore not recommended.&lt;br /&gt;
&lt;br /&gt;
PHP lacks a reliable cross-platform locking support, this is one if major problems when implementing new session drivers. Without locking the changes in user session may be lost resulting in hard to diagnose problems. Another problem when adding new session driver is that the sessions table needs to be updated at least once per minute.&lt;br /&gt;
&lt;br /&gt;
* MDL-31501 is the ticket for implementing a workable memcached session storage backend.&lt;br /&gt;
* MDL-25500 is the ticket to implement a general locking mechanism.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Not implemented yet.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==File pool==&lt;br /&gt;
&lt;br /&gt;
At present there is a filedir in dataroot where we store all contents of files in Moodle. Theoretically the code could be abstracted to allow storage of file contents in non-filesystem storage.&lt;br /&gt;
&lt;br /&gt;
The default location is $CFG-&amp;gt;dataroot/filedir, alterantive value can be specified in $CFG-&amp;gt;filedir setting. $CFG-&amp;gt;filedir does not require locking, it may be outside of $CFG-&amp;gt;dataroot. The file system/sharing may use very aggressive caching techniques because the files never change, the node needs to contact the master when writing or on cache miss. &lt;br /&gt;
&lt;br /&gt;
The original idea was to have a setting for preventing of file removals from the $CFG-&amp;gt;filedir directory, this would allow you to put files from multiple installations into just one giant file pool that could be replicated to all nodes - files would be only added there and never deleted automatically. The only potential problem is size of this huge dir and there would have to be a special new tool that exports used files from one site to another that is not using the shared file pool. The setting was supposed to be in file_storage::deleted_file_cleanup() method (one if that simply exits method).&lt;br /&gt;
&lt;br /&gt;
MDL-40528 contains a refactoring of trashdir operations that could help anybody who decides to reimplement the fole_storage class. The sample backup recovery class might be also user for simple local filedir cache on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
==Installation procedure==&lt;br /&gt;
&lt;br /&gt;
 1. Build a 1 node cluster&lt;br /&gt;
   - NFS backing storage&lt;br /&gt;
   - Configuration parameters like there are lots of nodes&lt;br /&gt;
   - Database setup on own host and such.&lt;br /&gt;
   - Build load balancer configuration.&lt;br /&gt;
   - Run moodle install cli&lt;br /&gt;
   - Add appropriate configuration items to get the system working behind load balancer&lt;br /&gt;
 2. Add more nodes to the cluster by replicating the first node.&lt;br /&gt;
&lt;br /&gt;
==Upgrade procedure==&lt;br /&gt;
&lt;br /&gt;
===Sample estimation===&lt;br /&gt;
# tweak load balancer to redirect all users to some static non-moodle page&lt;br /&gt;
# shutdown all nodes except one&lt;br /&gt;
# optionally enable CLI maintenance mode&lt;br /&gt;
# upload new PHP files to all nodes&lt;br /&gt;
# rebuild component cache if alternative read only location used&lt;br /&gt;
# upgrade the node from CLI&lt;br /&gt;
# disable CLI maintenance mode&lt;br /&gt;
# start other nodes (this guarantees localcachedir purging)&lt;br /&gt;
# enable normal operation&lt;br /&gt;
&lt;br /&gt;
===Large in-house NFS backend VM upgrade===&lt;br /&gt;
CLI Maintenance mode may be useful, but either way, you we stop all web nodes and also ensure that the current cron run has finished, otherwise you can get into all sort of strife.  Trying to do an upgrade during the forum digest time or stats run is not possible.  Both can run for &amp;gt;1 hour.&lt;br /&gt;
&lt;br /&gt;
Opcode resets are a problem when moving from CLI to apache for fcgi.  As I understand it, each has its own opcache location and that needs to be managed properly.  Hence the just shutdown the web nodes to force resets.&lt;br /&gt;
&lt;br /&gt;
 1. Disable all users except administrator who is upgrading. (This is done via IP at our load balancer)&lt;br /&gt;
 2. Stop apache on all nodes&lt;br /&gt;
 3. Stop cron from running and ensure it&#039;s finished.&lt;br /&gt;
&lt;br /&gt;
 We then ignore the fact we are in a cluster for a few instructions and operate on one node.&lt;br /&gt;
&lt;br /&gt;
 3.1 Backup/snapshot database and dataroot&lt;br /&gt;
&lt;br /&gt;
 4. Upload new php files to &#039;master&#039; node.&lt;br /&gt;
 5. Upgrade &#039;master&#039; node.  admin/cli/upgrade.php&lt;br /&gt;
 6. Start up &#039;master&#039; node apache, and test with admin login.&lt;br /&gt;
 7. If all successful, copy code to all other nodes&lt;br /&gt;
 8. Turn on other nodes.&lt;br /&gt;
 9. Browse around a bit to ensure you have warmed the opcache (cold cache can cause floods with 500+ users logging in within 10 seconds of go-live)&lt;br /&gt;
 10. Turn the system back on for all users.&lt;br /&gt;
&lt;br /&gt;
==Database clustering==&lt;br /&gt;
&lt;br /&gt;
Anything ACID compliant should be ok. For example even-odd master-master MySQL is not ok.&lt;br /&gt;
&lt;br /&gt;
TODO: add descriptions of ACID compliant DB cluster setups&lt;br /&gt;
&lt;br /&gt;
==More information==&lt;br /&gt;
&lt;br /&gt;
* [http://thamblings.blogspot.cz/2013/07/deploying-moodle-continued.html Deploying Moodle]&lt;br /&gt;
* [https://docs.moodle.org/25/en/Server_cluster Server cluster (user docs)]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48308</id>
		<title>Server clustering improvements proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48308"/>
		<updated>2015-07-21T02:06:16Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* $CFG-&amp;gt;tempdir */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.6}}&lt;br /&gt;
&lt;br /&gt;
Author: [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 4 July 2013 (WST) and others&lt;br /&gt;
&lt;br /&gt;
MDL-40979 was raised to group together this issues that are raised out of this document and the discussion.  All issues should be linked to that EPIC.&lt;br /&gt;
&lt;br /&gt;
==Cluster configuration requirements==&lt;br /&gt;
&lt;br /&gt;
# Cluster node clocks must be synchronised with difference &amp;lt;1s.&lt;br /&gt;
# Database setup must be ACID compliant.&lt;br /&gt;
# $CFG-&amp;gt;dataroot must be a shared directory.&lt;br /&gt;
# $CFG-&amp;gt;cachedir must be a shared directory.&lt;br /&gt;
&lt;br /&gt;
Note that these last two often cause confusion.  These directories must be shared because Moodle code relies on that, all cluster nodes must see the same data there.  Cluster headaches do occur when there is a lot of data in here, so our aim is to REDUCE dependence on shared caches as much as possible, technically it is not possible to have only local caches.&lt;br /&gt;
&lt;br /&gt;
==config.php settings==&lt;br /&gt;
Each node in cluster may use local set of php files including config.php, these may be synchronised via git for example, rsync, etc.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;wwwroot===&lt;br /&gt;
It must be the same on all nodes, it must be the public facing URL. It cannot be dynamic.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;sslproxy===&lt;br /&gt;
Enable if you have https:// wwwroot but the SSL is not done by Apache.&lt;br /&gt;
&lt;br /&gt;
Do not forget to enable &#039;&#039;Secure cookies only&#039;&#039; to make your site really secure, without it cookie stealing is still trivial.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;reverseproxy===&lt;br /&gt;
Enable if your nodes are accessed via different URL. Please note that it is not compatible with $CFG-&amp;gt;loginhttps.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dirroot===&lt;br /&gt;
It is strongly recommended that $CFG-&amp;gt;dirroot (which is automatically set via realpath(config.php)) contains the same path on all nodes. It does not need to point to the same shared directory though. The reason is that some some low level code may use the dirroot value for cache invalidation.&lt;br /&gt;
&lt;br /&gt;
The simplest solution is to have the same directory structure on each cluster node and synchronise these during each upgrade.&lt;br /&gt;
&lt;br /&gt;
The dirroot should be always read only for apache process because otherwise built in add-on installation and plugin uninstallation would get the nodes out of sync.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dataroot===&lt;br /&gt;
&lt;br /&gt;
This &#039;&#039;&#039;MUST&#039;&#039;&#039; be a shared directory where each cluster node is accessing the files directly. It must be very reliable, administrators cannot manipulate files directly there.&lt;br /&gt;
&lt;br /&gt;
Locking support is not required, if any code tries to use file locks in dataroot outside of cachedir or muc directory it is a bug.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;tempdir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;tempdir is a directory that must be shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The contents of this directory may be deleted if there is no pending HTTP request.&lt;br /&gt;
&lt;br /&gt;
In 2.9 and later user request directory where possible.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;cachedir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;cachedir is a directory shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Cache invalidation is done by deleting or overriding of existing files, this needs to be automatically replicated to all cluster nodes, otherwise the cache may return stale or invalid data which often leads to fatal errors or data loss.&lt;br /&gt;
&lt;br /&gt;
The existing documentation clearly states that this directory must be shared, all existing code including add-ons may expect this, it is therefore not possible to change this requirement without breaking backwards compatibility.&lt;br /&gt;
&lt;br /&gt;
Please note that MUC caches have similar problem, the current design expects that each node is contacting the same caches. It should be possible to create new MUC backends that do not require shared cache backends in a way similar to the proposed $CFG-&amp;gt;localcachedir .&lt;br /&gt;
&lt;br /&gt;
You can safely purge cachedir when restarting the whole cluster, you may get some notices or temporary errors if you purge this directory while other requests are active.&lt;br /&gt;
&lt;br /&gt;
Netspot admins came up with a hypothesis that &amp;quot;cachedir does not have to be shared&amp;quot;, it is easy to disapprove it - we need to find a single case where the sharing is required. Let&#039;s look at the caching of data from config table in $CFG global variable. If one node modifies CFG value others would not be notified about the change and would continue using stale value. Workaround seems to be to create a new revision number that is incremented after any change in $CFG and share it with all nodes. The question is where to put it so that it is shared by all nodes? Storing it in database would require one extra read on each page and one extra write on each update, that is not acceptable. We cannot put the revision into a shared filesystem because we would not have it. We cannot rely on presence of memcache or any shared data storage in default installation either. In most other cases we store the revision flags in CFG itself, it is clearly not possible in this case because it would not be shared by nodes. Somebody said &amp;quot;but it works without sharing for all our clients for at least a year&amp;quot; - that does not prove anything, you would have to make sure it works also for everybody else with all add-ons, custom modifications and minimal number of PHP extensions required by Moodle.&lt;br /&gt;
&lt;br /&gt;
In any case cachedir is shared by definition since the beginning of its existence, it is a fact that developers writing code may depend on. If you do not like it then use local cache dir.&lt;br /&gt;
&lt;br /&gt;
== New $CFG-&amp;gt;localcachedir==&lt;br /&gt;
&lt;br /&gt;
The difference from normal $CFG-&amp;gt;cachedir is that the directory does not have to be shared by all cluster nodes, the files stored in $CFG-&amp;gt;localcachedir MUST NOT change! Default directory is &amp;quot;$CFG-&amp;gt;dataroot/localcache&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All files there must use unique revision numbers or hashes because the cached data cannot be invalidated by other mechanism - it will support only adding of new files, but no file deletes or overrides. The $CFG-&amp;gt;localcachedir will be growing over time, all local cache files will be deleted during purge_all_caches() (automatically during upgrades).&lt;br /&gt;
&lt;br /&gt;
When using hashes please make sure the number of files in one directory is kept to some reasonable number because some filesystems might have problems with large number of files in one directory.&lt;br /&gt;
&lt;br /&gt;
Note that some caches cannot be easily moved to localcachedir because you need a reliable revision number here, but sometimes it is either not possible or very slow because you need to store the revision number somewhere and you need to bump up the revision number after any change and you would need to store it in database. Caching is not free, each usage must be carefully evaluated.&lt;br /&gt;
&lt;br /&gt;
Design requirements:&lt;br /&gt;
* Everything must be automatic without extra administrative overhead.&lt;br /&gt;
* purge_all_caches() on any node triggers local cache purging on all other nodes before adding any new files there.&lt;br /&gt;
* Performance on standalone servers must not be worse.&lt;br /&gt;
&lt;br /&gt;
Usage restrictions:&lt;br /&gt;
* No file deletes&lt;br /&gt;
* No file modifications&lt;br /&gt;
* No file overwriting&lt;br /&gt;
* Soft limit on maximum number of files in one directory (few thousands)&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* Clustered servers may use fast local filesystem such as tempfs.&lt;br /&gt;
* No opcache cache invalidation problems if php files included from localcachedir (because the files must not change).&lt;br /&gt;
&lt;br /&gt;
Candidates for migration from $CFG-&amp;gt;cachedir:&lt;br /&gt;
* JS cache MDL-40546 &lt;br /&gt;
* Theme caches MDL-40563&lt;br /&gt;
* HTMLPurifier cache MDL-41017&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40545.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Component cache==&lt;br /&gt;
&lt;br /&gt;
Class core_component is using a $CFG-&amp;gt;cachedir/core_component.php cache that contains a complete list of all plugins and all classes present in $CFG-&amp;gt;dirroot. The implementation must be as fast as possible and the results must be extremely reliable.&lt;br /&gt;
&lt;br /&gt;
The cache is automatically invalidated on admin/index.php page and during installation and every upgrade. It is also cleared during purge_all_caches(), but that is only a side effect of storing it in cachedir and it is not required.&lt;br /&gt;
&lt;br /&gt;
core_component class cannot depend on database, MUC or any core libraries - that is the reason why there cannot be any revision flag, there is nowhere to store it, the sha1() of that file content would be the revision. But we would have to go through all plugin directories to find out if it was changed or what revision to use. There are only two options - either we store this file in shared cache or admin invalidates this cache manually, the second option it clearly not acceptable for standard installations.&lt;br /&gt;
&lt;br /&gt;
===Alternative component cache location===&lt;br /&gt;
&lt;br /&gt;
This is useful for clustered installations only. Typically the $CFG-&amp;gt;alternative_component_cache = &#039;/local/cache/dir/core_component.php&#039; would point to local node cache directory. Before upgrade the administrator would have to manually execute following on each node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ php admin/cli/alternative_component_cache.php --rebuild&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively you could put the cache file directly into dirroot and distribute it together with new PHP source files. Yet another possibility would be to purge all local caches on all nodes before upgrade or simply change the script name in config.php on all nodes before upgrade.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40475.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==MUC and clustering==&lt;br /&gt;
&lt;br /&gt;
At present administrators are free to create new stores and assign them to existing definitions of each cache. Unfortunately the documentation or admin UI does not mention that by default all those definitions require cache stores to be shared by all cluster nodes! Some cache keys may include revision numbers and all settings which makes them compatible with local caches, we need to document it somewhere.&lt;br /&gt;
&lt;br /&gt;
I would like to propose a new flag in cache definition &#039;&#039;&#039;localcache&#039;&#039;&#039; which would indicate that it is safe to use local cache stores on cluster nodes. For now we can at least document it in db/caches.php as inline comments. This information should be clearly visible on the cache store/definition settings page. Maybe we could add setting to cache stores which indicates if it is a shared or local cache. The only potential problem is that it might confuse admins that know little about clustering or cache invalidation.&lt;br /&gt;
&lt;br /&gt;
In theory the installation could create two file stores by default - one using current $CFG-&amp;gt;cachedir and second using $CFG-&amp;gt;localcachedir and assign them to definitions based on localcache flag. This could help new admins when setting up clusters, all they would have to do would be to move localcachedir to cluster node ram disks.&lt;br /&gt;
&lt;br /&gt;
Note that MODE_REQUEST are local by definition and MODE_SESSION are always shared (because session is shared), this means we need to consider only MODE_APPLICATION definitions here.&lt;br /&gt;
&lt;br /&gt;
List of caches/definitions that are compatible with local caching on cluster nodes:&lt;br /&gt;
* core htmlpurifier - MDL-41017&lt;br /&gt;
* core string - MDL-41019&lt;br /&gt;
* core langmenucache - MDL-41019&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
==Theme caching==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;All large installs and clusters should use transparent proxies (such as Cloudflare or custom nginx).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Small installs without transparent caches (or when in designer mode) depend on performance of theme serving scripts (theme/image.php, theme/styles.php, etc.).&lt;br /&gt;
&lt;br /&gt;
The serving scripts receive revision number in URL, this solves the problem with cache invalidation. We are not using MUC there intentionally because we are not in already open HTTP request with database connection and all standard libraries already loaded, the data there must be served quickly with as little memory and CPU cycles as possible.&lt;br /&gt;
&lt;br /&gt;
The standard theme caches may be stored in local node caches, we could store the theme caches in $CFG-&amp;gt;localcachedir/theme/ directory.&lt;br /&gt;
&lt;br /&gt;
Theme designer mode is not using any revisions. For performance reasons we must use some cache, the only option seems to be the standard shared $CFG-&amp;gt;cachedir/theme/. Using localcachedir is not an option here, we might try to improve the general performance here and if possible skip all caching in theme designer mode.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Theme caching was improved in 2.6, it is using localcachedir, see MDL-40563.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Javascript caching==&lt;br /&gt;
&lt;br /&gt;
We used JS caching in cachedir for performance reasons because we were doing on-the-fly JS compression. Ideally we should switch to build system for all JS files and store the minimised files along the source files in git and just add proper headers in lib/javascript.php script.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;JavaScript caching was improved in 2.6, it is using localcachedir, see MDL-40546.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Language installation and customisations==&lt;br /&gt;
&lt;br /&gt;
Each string is constructed from the following sources:&lt;br /&gt;
# en pack in plugin/core - always distributed with plugin&lt;br /&gt;
# current language pack, including all its parents - downloaded into $CFG-&amp;gt;langotherroot (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
# local string tweaks - created with tool_customlang, stored in $CFG-&amp;gt;langlocalroot in directories with &amp;quot;_local&amp;quot; suffix (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
&lt;br /&gt;
We can use existing $CFG-&amp;gt;langrev in cache keys to add support for local lang caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
Please note that language packs and local modifications are PHP files, you need to verify file timestamps or blacklist these locations in OP code caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
There is another cache for available translations which is stored in $CFG-&amp;gt;langmenucachefile, we can move this to MUC and allow local node caches too.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Lang caching is improved in 2.6, see MDL-41019.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==PHP accelerators==&lt;br /&gt;
&lt;br /&gt;
Potential problems:&lt;br /&gt;
* file time stamps must be verified in Moodle 2.5 and bellow&lt;br /&gt;
&lt;br /&gt;
===opcache extension===&lt;br /&gt;
&lt;br /&gt;
Standard &#039;&#039;opcache&#039;&#039; extension is strongly recommended for Moodle 2.6 forward, it is the only solution officially supported by PHP developers. Starting with Moodle 2.6 we should recommend the opcache extension during environment test. All other PHP accelerators should be actively discourage (warning on environment page).&lt;br /&gt;
&lt;br /&gt;
Please note that HQ developers are not required to test current stable branches with any PHP accelerators.&lt;br /&gt;
&lt;br /&gt;
The goal is to use opcaching without checking of file modification times - problem here are dynamically generated PHP files that are stored in dataroot (component cache, lang packs, local lang modifications, muc config, etc.), we need to invalidate the op code cache explicitly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;OPcache extension is fully supported in Moodle 2.6, see MDL-40415.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Browser sessions==&lt;br /&gt;
&lt;br /&gt;
User session data should be stored in some reliable shared storage, all cluster nodes need to operate with the same session data, the data must not be disappearing randomly.&lt;br /&gt;
&lt;br /&gt;
All sessions drivers should be updating the list of active sessions in the session table, the serialised session data can be stored somewhere else.&lt;br /&gt;
&lt;br /&gt;
Moodle session drivers need to support some special features:&lt;br /&gt;
* Session timeout is controlled from Moodle code  - it is required for reliable SSO implementations.&lt;br /&gt;
* We need to be able to query list of all sessions belonging to one user - this allows us to logout deleted users (for example spammers).&lt;br /&gt;
* Locking is strongly recommended because race conditions may create hard to diagnose problems - users need to logout/login to recover from these problems.&lt;br /&gt;
* Sometimes the structure of session data changes and then upgrade requires logout of all active users.&lt;br /&gt;
* Some add-ons/patches use the information from sessions table to implement limits for concurrent user logins.&lt;br /&gt;
&lt;br /&gt;
By default new installations are using a databases session driver with locking support. There is a legacy file based session driver for sites that cannot use db sessions, but it does not support any advanced features above and is therefore not recommended.&lt;br /&gt;
&lt;br /&gt;
PHP lacks a reliable cross-platform locking support, this is one if major problems when implementing new session drivers. Without locking the changes in user session may be lost resulting in hard to diagnose problems. Another problem when adding new session driver is that the sessions table needs to be updated at least once per minute.&lt;br /&gt;
&lt;br /&gt;
* MDL-31501 is the ticket for implementing a workable memcached session storage backend.&lt;br /&gt;
* MDL-25500 is the ticket to implement a general locking mechanism.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Not implemented yet.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==File pool==&lt;br /&gt;
&lt;br /&gt;
At present there is a filedir in dataroot where we store all contents of files in Moodle. Theoretically the code could be abstracted to allow storage of file contents in non-filesystem storage.&lt;br /&gt;
&lt;br /&gt;
The default location is $CFG-&amp;gt;dataroot/filedir, alterantive value can be specified in $CFG-&amp;gt;filedir setting. $CFG-&amp;gt;filedir does not require locking, it may be outside of $CFG-&amp;gt;dataroot. The file system/sharing may use very aggressive caching techniques because the files never change, the node needs to contact the master when writing or on cache miss. &lt;br /&gt;
&lt;br /&gt;
The original idea was to have a setting for preventing of file removals from the $CFG-&amp;gt;filedir directory, this would allow you to put files from multiple installations into just one giant file pool that could be replicated to all nodes - files would be only added there and never deleted automatically. The only potential problem is size of this huge dir and there would have to be a special new tool that exports used files from one site to another that is not using the shared file pool. The setting was supposed to be in file_storage::deleted_file_cleanup() method (one if that simply exits method).&lt;br /&gt;
&lt;br /&gt;
MDL-40528 contains a refactoring of trashdir operations that could help anybody who decides to reimplement the fole_storage class. The sample backup recovery class might be also user for simple local filedir cache on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
==Installation procedure==&lt;br /&gt;
&lt;br /&gt;
 1. Build a 1 node cluster&lt;br /&gt;
   - NFS backing storage&lt;br /&gt;
   - Configuration parameters like there are lots of nodes&lt;br /&gt;
   - Database setup on own host and such.&lt;br /&gt;
   - Build load balancer configuration.&lt;br /&gt;
   - Run moodle install cli&lt;br /&gt;
   - Add appropriate configuration items to get the system working behind load balancer&lt;br /&gt;
 2. Add more nodes to the cluster by replicating the first node.&lt;br /&gt;
&lt;br /&gt;
==Upgrade procedure==&lt;br /&gt;
&lt;br /&gt;
===Sample estimation===&lt;br /&gt;
# tweak load balancer to redirect all users to some static non-moodle page&lt;br /&gt;
# shutdown all nodes except one&lt;br /&gt;
# optionally enable CLI maintenance mode&lt;br /&gt;
# upload new PHP files to all nodes&lt;br /&gt;
# rebuild component cache if alternative read only location used&lt;br /&gt;
# upgrade the node from CLI&lt;br /&gt;
# disable CLI maintenance mode&lt;br /&gt;
# start other nodes (this guarantees localcachedir and tempdir purging)&lt;br /&gt;
# enable normal operation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Large in-house NFS backend VM upgrade===&lt;br /&gt;
CLI Maintenance mode may be useful, but either way, you we stop all web nodes and also ensure that the current cron run has finished, otherwise you can get into all sort of strife.  Trying to do an upgrade during the forum digest time or stats run is not possible.  Both can run for &amp;gt;1 hour.&lt;br /&gt;
&lt;br /&gt;
Opcode resets are a problem when moving from CLI to apache for fcgi.  As I understand it, each has its own opcache location and that needs to be managed properly.  Hence the just shutdown the web nodes to force resets.&lt;br /&gt;
&lt;br /&gt;
 1. Disable all users except administrator who is upgrading. (This is done via IP at our load balancer)&lt;br /&gt;
 2. Stop apache on all nodes&lt;br /&gt;
 3. Stop cron from running and ensure it&#039;s finished.&lt;br /&gt;
&lt;br /&gt;
 We then ignore the fact we are in a cluster for a few instructions and operate on one node.&lt;br /&gt;
&lt;br /&gt;
 3.1 Backup/snapshot database and dataroot&lt;br /&gt;
&lt;br /&gt;
 4. Upload new php files to &#039;master&#039; node.&lt;br /&gt;
 5. Upgrade &#039;master&#039; node.  admin/cli/upgrade.php&lt;br /&gt;
 6. Start up &#039;master&#039; node apache, and test with admin login.&lt;br /&gt;
 7. If all successful, copy code to all other nodes&lt;br /&gt;
 8. Turn on other nodes.&lt;br /&gt;
 9. Browse around a bit to ensure you have warmed the opcache (cold cache can cause floods with 500+ users logging in within 10 seconds of go-live)&lt;br /&gt;
 10. Turn the system back on for all users.&lt;br /&gt;
&lt;br /&gt;
==Database clustering==&lt;br /&gt;
&lt;br /&gt;
Anything ACID compliant should be ok. For example even-odd master-master MySQL is not ok.&lt;br /&gt;
&lt;br /&gt;
TODO: add descriptions of ACID compliant DB cluster setups&lt;br /&gt;
&lt;br /&gt;
==More information==&lt;br /&gt;
&lt;br /&gt;
* [http://thamblings.blogspot.cz/2013/07/deploying-moodle-continued.html Deploying Moodle]&lt;br /&gt;
* [https://docs.moodle.org/25/en/Server_cluster Server cluster (user docs)]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48307</id>
		<title>Server clustering improvements proposal</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Server_clustering_improvements_proposal&amp;diff=48307"/>
		<updated>2015-07-21T02:05:49Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* $CFG-&amp;gt;tempdir */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.6}}&lt;br /&gt;
&lt;br /&gt;
Author: [[User:Petr Škoda (škoďák)|Petr Škoda (škoďák)]] 4 July 2013 (WST) and others&lt;br /&gt;
&lt;br /&gt;
MDL-40979 was raised to group together this issues that are raised out of this document and the discussion.  All issues should be linked to that EPIC.&lt;br /&gt;
&lt;br /&gt;
==Cluster configuration requirements==&lt;br /&gt;
&lt;br /&gt;
# Cluster node clocks must be synchronised with difference &amp;lt;1s.&lt;br /&gt;
# Database setup must be ACID compliant.&lt;br /&gt;
# $CFG-&amp;gt;dataroot must be a shared directory.&lt;br /&gt;
# $CFG-&amp;gt;cachedir must be a shared directory.&lt;br /&gt;
&lt;br /&gt;
Note that these last two often cause confusion.  These directories must be shared because Moodle code relies on that, all cluster nodes must see the same data there.  Cluster headaches do occur when there is a lot of data in here, so our aim is to REDUCE dependence on shared caches as much as possible, technically it is not possible to have only local caches.&lt;br /&gt;
&lt;br /&gt;
==config.php settings==&lt;br /&gt;
Each node in cluster may use local set of php files including config.php, these may be synchronised via git for example, rsync, etc.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;wwwroot===&lt;br /&gt;
It must be the same on all nodes, it must be the public facing URL. It cannot be dynamic.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;sslproxy===&lt;br /&gt;
Enable if you have https:// wwwroot but the SSL is not done by Apache.&lt;br /&gt;
&lt;br /&gt;
Do not forget to enable &#039;&#039;Secure cookies only&#039;&#039; to make your site really secure, without it cookie stealing is still trivial.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;reverseproxy===&lt;br /&gt;
Enable if your nodes are accessed via different URL. Please note that it is not compatible with $CFG-&amp;gt;loginhttps.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dirroot===&lt;br /&gt;
It is strongly recommended that $CFG-&amp;gt;dirroot (which is automatically set via realpath(config.php)) contains the same path on all nodes. It does not need to point to the same shared directory though. The reason is that some some low level code may use the dirroot value for cache invalidation.&lt;br /&gt;
&lt;br /&gt;
The simplest solution is to have the same directory structure on each cluster node and synchronise these during each upgrade.&lt;br /&gt;
&lt;br /&gt;
The dirroot should be always read only for apache process because otherwise built in add-on installation and plugin uninstallation would get the nodes out of sync.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;dataroot===&lt;br /&gt;
&lt;br /&gt;
This &#039;&#039;&#039;MUST&#039;&#039;&#039; be a shared directory where each cluster node is accessing the files directly. It must be very reliable, administrators cannot manipulate files directly there.&lt;br /&gt;
&lt;br /&gt;
Locking support is not required, if any code tries to use file locks in dataroot outside of cachedir or muc directory it is a bug.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;tempdir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;cachedir is a directory shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The contents of this directory may be deleted if there is no pending HTTP request.&lt;br /&gt;
&lt;br /&gt;
In 2.9 and later user request directory where possible.&lt;br /&gt;
&lt;br /&gt;
===$CFG-&amp;gt;cachedir===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirement: $CFG-&amp;gt;cachedir is a directory shared by all cluster nodes.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Cache invalidation is done by deleting or overriding of existing files, this needs to be automatically replicated to all cluster nodes, otherwise the cache may return stale or invalid data which often leads to fatal errors or data loss.&lt;br /&gt;
&lt;br /&gt;
The existing documentation clearly states that this directory must be shared, all existing code including add-ons may expect this, it is therefore not possible to change this requirement without breaking backwards compatibility.&lt;br /&gt;
&lt;br /&gt;
Please note that MUC caches have similar problem, the current design expects that each node is contacting the same caches. It should be possible to create new MUC backends that do not require shared cache backends in a way similar to the proposed $CFG-&amp;gt;localcachedir .&lt;br /&gt;
&lt;br /&gt;
You can safely purge cachedir when restarting the whole cluster, you may get some notices or temporary errors if you purge this directory while other requests are active.&lt;br /&gt;
&lt;br /&gt;
Netspot admins came up with a hypothesis that &amp;quot;cachedir does not have to be shared&amp;quot;, it is easy to disapprove it - we need to find a single case where the sharing is required. Let&#039;s look at the caching of data from config table in $CFG global variable. If one node modifies CFG value others would not be notified about the change and would continue using stale value. Workaround seems to be to create a new revision number that is incremented after any change in $CFG and share it with all nodes. The question is where to put it so that it is shared by all nodes? Storing it in database would require one extra read on each page and one extra write on each update, that is not acceptable. We cannot put the revision into a shared filesystem because we would not have it. We cannot rely on presence of memcache or any shared data storage in default installation either. In most other cases we store the revision flags in CFG itself, it is clearly not possible in this case because it would not be shared by nodes. Somebody said &amp;quot;but it works without sharing for all our clients for at least a year&amp;quot; - that does not prove anything, you would have to make sure it works also for everybody else with all add-ons, custom modifications and minimal number of PHP extensions required by Moodle.&lt;br /&gt;
&lt;br /&gt;
In any case cachedir is shared by definition since the beginning of its existence, it is a fact that developers writing code may depend on. If you do not like it then use local cache dir.&lt;br /&gt;
&lt;br /&gt;
== New $CFG-&amp;gt;localcachedir==&lt;br /&gt;
&lt;br /&gt;
The difference from normal $CFG-&amp;gt;cachedir is that the directory does not have to be shared by all cluster nodes, the files stored in $CFG-&amp;gt;localcachedir MUST NOT change! Default directory is &amp;quot;$CFG-&amp;gt;dataroot/localcache&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
All files there must use unique revision numbers or hashes because the cached data cannot be invalidated by other mechanism - it will support only adding of new files, but no file deletes or overrides. The $CFG-&amp;gt;localcachedir will be growing over time, all local cache files will be deleted during purge_all_caches() (automatically during upgrades).&lt;br /&gt;
&lt;br /&gt;
When using hashes please make sure the number of files in one directory is kept to some reasonable number because some filesystems might have problems with large number of files in one directory.&lt;br /&gt;
&lt;br /&gt;
Note that some caches cannot be easily moved to localcachedir because you need a reliable revision number here, but sometimes it is either not possible or very slow because you need to store the revision number somewhere and you need to bump up the revision number after any change and you would need to store it in database. Caching is not free, each usage must be carefully evaluated.&lt;br /&gt;
&lt;br /&gt;
Design requirements:&lt;br /&gt;
* Everything must be automatic without extra administrative overhead.&lt;br /&gt;
* purge_all_caches() on any node triggers local cache purging on all other nodes before adding any new files there.&lt;br /&gt;
* Performance on standalone servers must not be worse.&lt;br /&gt;
&lt;br /&gt;
Usage restrictions:&lt;br /&gt;
* No file deletes&lt;br /&gt;
* No file modifications&lt;br /&gt;
* No file overwriting&lt;br /&gt;
* Soft limit on maximum number of files in one directory (few thousands)&lt;br /&gt;
&lt;br /&gt;
Benefits:&lt;br /&gt;
* Clustered servers may use fast local filesystem such as tempfs.&lt;br /&gt;
* No opcache cache invalidation problems if php files included from localcachedir (because the files must not change).&lt;br /&gt;
&lt;br /&gt;
Candidates for migration from $CFG-&amp;gt;cachedir:&lt;br /&gt;
* JS cache MDL-40546 &lt;br /&gt;
* Theme caches MDL-40563&lt;br /&gt;
* HTMLPurifier cache MDL-41017&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40545.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Component cache==&lt;br /&gt;
&lt;br /&gt;
Class core_component is using a $CFG-&amp;gt;cachedir/core_component.php cache that contains a complete list of all plugins and all classes present in $CFG-&amp;gt;dirroot. The implementation must be as fast as possible and the results must be extremely reliable.&lt;br /&gt;
&lt;br /&gt;
The cache is automatically invalidated on admin/index.php page and during installation and every upgrade. It is also cleared during purge_all_caches(), but that is only a side effect of storing it in cachedir and it is not required.&lt;br /&gt;
&lt;br /&gt;
core_component class cannot depend on database, MUC or any core libraries - that is the reason why there cannot be any revision flag, there is nowhere to store it, the sha1() of that file content would be the revision. But we would have to go through all plugin directories to find out if it was changed or what revision to use. There are only two options - either we store this file in shared cache or admin invalidates this cache manually, the second option it clearly not acceptable for standard installations.&lt;br /&gt;
&lt;br /&gt;
===Alternative component cache location===&lt;br /&gt;
&lt;br /&gt;
This is useful for clustered installations only. Typically the $CFG-&amp;gt;alternative_component_cache = &#039;/local/cache/dir/core_component.php&#039; would point to local node cache directory. Before upgrade the administrator would have to manually execute following on each node:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ php admin/cli/alternative_component_cache.php --rebuild&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively you could put the cache file directly into dirroot and distribute it together with new PHP source files. Yet another possibility would be to purge all local caches on all nodes before upgrade or simply change the script name in config.php on all nodes before upgrade.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Implemented in Moodle 2.6, see MDL-40475.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==MUC and clustering==&lt;br /&gt;
&lt;br /&gt;
At present administrators are free to create new stores and assign them to existing definitions of each cache. Unfortunately the documentation or admin UI does not mention that by default all those definitions require cache stores to be shared by all cluster nodes! Some cache keys may include revision numbers and all settings which makes them compatible with local caches, we need to document it somewhere.&lt;br /&gt;
&lt;br /&gt;
I would like to propose a new flag in cache definition &#039;&#039;&#039;localcache&#039;&#039;&#039; which would indicate that it is safe to use local cache stores on cluster nodes. For now we can at least document it in db/caches.php as inline comments. This information should be clearly visible on the cache store/definition settings page. Maybe we could add setting to cache stores which indicates if it is a shared or local cache. The only potential problem is that it might confuse admins that know little about clustering or cache invalidation.&lt;br /&gt;
&lt;br /&gt;
In theory the installation could create two file stores by default - one using current $CFG-&amp;gt;cachedir and second using $CFG-&amp;gt;localcachedir and assign them to definitions based on localcache flag. This could help new admins when setting up clusters, all they would have to do would be to move localcachedir to cluster node ram disks.&lt;br /&gt;
&lt;br /&gt;
Note that MODE_REQUEST are local by definition and MODE_SESSION are always shared (because session is shared), this means we need to consider only MODE_APPLICATION definitions here.&lt;br /&gt;
&lt;br /&gt;
List of caches/definitions that are compatible with local caching on cluster nodes:&lt;br /&gt;
* core htmlpurifier - MDL-41017&lt;br /&gt;
* core string - MDL-41019&lt;br /&gt;
* core langmenucache - MDL-41019&lt;br /&gt;
*&lt;br /&gt;
&lt;br /&gt;
==Theme caching==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;All large installs and clusters should use transparent proxies (such as Cloudflare or custom nginx).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Small installs without transparent caches (or when in designer mode) depend on performance of theme serving scripts (theme/image.php, theme/styles.php, etc.).&lt;br /&gt;
&lt;br /&gt;
The serving scripts receive revision number in URL, this solves the problem with cache invalidation. We are not using MUC there intentionally because we are not in already open HTTP request with database connection and all standard libraries already loaded, the data there must be served quickly with as little memory and CPU cycles as possible.&lt;br /&gt;
&lt;br /&gt;
The standard theme caches may be stored in local node caches, we could store the theme caches in $CFG-&amp;gt;localcachedir/theme/ directory.&lt;br /&gt;
&lt;br /&gt;
Theme designer mode is not using any revisions. For performance reasons we must use some cache, the only option seems to be the standard shared $CFG-&amp;gt;cachedir/theme/. Using localcachedir is not an option here, we might try to improve the general performance here and if possible skip all caching in theme designer mode.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Theme caching was improved in 2.6, it is using localcachedir, see MDL-40563.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Javascript caching==&lt;br /&gt;
&lt;br /&gt;
We used JS caching in cachedir for performance reasons because we were doing on-the-fly JS compression. Ideally we should switch to build system for all JS files and store the minimised files along the source files in git and just add proper headers in lib/javascript.php script.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;JavaScript caching was improved in 2.6, it is using localcachedir, see MDL-40546.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Language installation and customisations==&lt;br /&gt;
&lt;br /&gt;
Each string is constructed from the following sources:&lt;br /&gt;
# en pack in plugin/core - always distributed with plugin&lt;br /&gt;
# current language pack, including all its parents - downloaded into $CFG-&amp;gt;langotherroot (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
# local string tweaks - created with tool_customlang, stored in $CFG-&amp;gt;langlocalroot in directories with &amp;quot;_local&amp;quot; suffix (usually $CFG-&amp;gt;dataroot/lang)&lt;br /&gt;
&lt;br /&gt;
We can use existing $CFG-&amp;gt;langrev in cache keys to add support for local lang caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
Please note that language packs and local modifications are PHP files, you need to verify file timestamps or blacklist these locations in OP code caches on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
There is another cache for available translations which is stored in $CFG-&amp;gt;langmenucachefile, we can move this to MUC and allow local node caches too.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Lang caching is improved in 2.6, see MDL-41019.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==PHP accelerators==&lt;br /&gt;
&lt;br /&gt;
Potential problems:&lt;br /&gt;
* file time stamps must be verified in Moodle 2.5 and bellow&lt;br /&gt;
&lt;br /&gt;
===opcache extension===&lt;br /&gt;
&lt;br /&gt;
Standard &#039;&#039;opcache&#039;&#039; extension is strongly recommended for Moodle 2.6 forward, it is the only solution officially supported by PHP developers. Starting with Moodle 2.6 we should recommend the opcache extension during environment test. All other PHP accelerators should be actively discourage (warning on environment page).&lt;br /&gt;
&lt;br /&gt;
Please note that HQ developers are not required to test current stable branches with any PHP accelerators.&lt;br /&gt;
&lt;br /&gt;
The goal is to use opcaching without checking of file modification times - problem here are dynamically generated PHP files that are stored in dataroot (component cache, lang packs, local lang modifications, muc config, etc.), we need to invalidate the op code cache explicitly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;OPcache extension is fully supported in Moodle 2.6, see MDL-40415.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Browser sessions==&lt;br /&gt;
&lt;br /&gt;
User session data should be stored in some reliable shared storage, all cluster nodes need to operate with the same session data, the data must not be disappearing randomly.&lt;br /&gt;
&lt;br /&gt;
All sessions drivers should be updating the list of active sessions in the session table, the serialised session data can be stored somewhere else.&lt;br /&gt;
&lt;br /&gt;
Moodle session drivers need to support some special features:&lt;br /&gt;
* Session timeout is controlled from Moodle code  - it is required for reliable SSO implementations.&lt;br /&gt;
* We need to be able to query list of all sessions belonging to one user - this allows us to logout deleted users (for example spammers).&lt;br /&gt;
* Locking is strongly recommended because race conditions may create hard to diagnose problems - users need to logout/login to recover from these problems.&lt;br /&gt;
* Sometimes the structure of session data changes and then upgrade requires logout of all active users.&lt;br /&gt;
* Some add-ons/patches use the information from sessions table to implement limits for concurrent user logins.&lt;br /&gt;
&lt;br /&gt;
By default new installations are using a databases session driver with locking support. There is a legacy file based session driver for sites that cannot use db sessions, but it does not support any advanced features above and is therefore not recommended.&lt;br /&gt;
&lt;br /&gt;
PHP lacks a reliable cross-platform locking support, this is one if major problems when implementing new session drivers. Without locking the changes in user session may be lost resulting in hard to diagnose problems. Another problem when adding new session driver is that the sessions table needs to be updated at least once per minute.&lt;br /&gt;
&lt;br /&gt;
* MDL-31501 is the ticket for implementing a workable memcached session storage backend.&lt;br /&gt;
* MDL-25500 is the ticket to implement a general locking mechanism.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Not implemented yet.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==File pool==&lt;br /&gt;
&lt;br /&gt;
At present there is a filedir in dataroot where we store all contents of files in Moodle. Theoretically the code could be abstracted to allow storage of file contents in non-filesystem storage.&lt;br /&gt;
&lt;br /&gt;
The default location is $CFG-&amp;gt;dataroot/filedir, alterantive value can be specified in $CFG-&amp;gt;filedir setting. $CFG-&amp;gt;filedir does not require locking, it may be outside of $CFG-&amp;gt;dataroot. The file system/sharing may use very aggressive caching techniques because the files never change, the node needs to contact the master when writing or on cache miss. &lt;br /&gt;
&lt;br /&gt;
The original idea was to have a setting for preventing of file removals from the $CFG-&amp;gt;filedir directory, this would allow you to put files from multiple installations into just one giant file pool that could be replicated to all nodes - files would be only added there and never deleted automatically. The only potential problem is size of this huge dir and there would have to be a special new tool that exports used files from one site to another that is not using the shared file pool. The setting was supposed to be in file_storage::deleted_file_cleanup() method (one if that simply exits method).&lt;br /&gt;
&lt;br /&gt;
MDL-40528 contains a refactoring of trashdir operations that could help anybody who decides to reimplement the fole_storage class. The sample backup recovery class might be also user for simple local filedir cache on cluster nodes.&lt;br /&gt;
&lt;br /&gt;
==Installation procedure==&lt;br /&gt;
&lt;br /&gt;
 1. Build a 1 node cluster&lt;br /&gt;
   - NFS backing storage&lt;br /&gt;
   - Configuration parameters like there are lots of nodes&lt;br /&gt;
   - Database setup on own host and such.&lt;br /&gt;
   - Build load balancer configuration.&lt;br /&gt;
   - Run moodle install cli&lt;br /&gt;
   - Add appropriate configuration items to get the system working behind load balancer&lt;br /&gt;
 2. Add more nodes to the cluster by replicating the first node.&lt;br /&gt;
&lt;br /&gt;
==Upgrade procedure==&lt;br /&gt;
&lt;br /&gt;
===Sample estimation===&lt;br /&gt;
# tweak load balancer to redirect all users to some static non-moodle page&lt;br /&gt;
# shutdown all nodes except one&lt;br /&gt;
# optionally enable CLI maintenance mode&lt;br /&gt;
# upload new PHP files to all nodes&lt;br /&gt;
# rebuild component cache if alternative read only location used&lt;br /&gt;
# upgrade the node from CLI&lt;br /&gt;
# disable CLI maintenance mode&lt;br /&gt;
# start other nodes (this guarantees localcachedir and tempdir purging)&lt;br /&gt;
# enable normal operation&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Large in-house NFS backend VM upgrade===&lt;br /&gt;
CLI Maintenance mode may be useful, but either way, you we stop all web nodes and also ensure that the current cron run has finished, otherwise you can get into all sort of strife.  Trying to do an upgrade during the forum digest time or stats run is not possible.  Both can run for &amp;gt;1 hour.&lt;br /&gt;
&lt;br /&gt;
Opcode resets are a problem when moving from CLI to apache for fcgi.  As I understand it, each has its own opcache location and that needs to be managed properly.  Hence the just shutdown the web nodes to force resets.&lt;br /&gt;
&lt;br /&gt;
 1. Disable all users except administrator who is upgrading. (This is done via IP at our load balancer)&lt;br /&gt;
 2. Stop apache on all nodes&lt;br /&gt;
 3. Stop cron from running and ensure it&#039;s finished.&lt;br /&gt;
&lt;br /&gt;
 We then ignore the fact we are in a cluster for a few instructions and operate on one node.&lt;br /&gt;
&lt;br /&gt;
 3.1 Backup/snapshot database and dataroot&lt;br /&gt;
&lt;br /&gt;
 4. Upload new php files to &#039;master&#039; node.&lt;br /&gt;
 5. Upgrade &#039;master&#039; node.  admin/cli/upgrade.php&lt;br /&gt;
 6. Start up &#039;master&#039; node apache, and test with admin login.&lt;br /&gt;
 7. If all successful, copy code to all other nodes&lt;br /&gt;
 8. Turn on other nodes.&lt;br /&gt;
 9. Browse around a bit to ensure you have warmed the opcache (cold cache can cause floods with 500+ users logging in within 10 seconds of go-live)&lt;br /&gt;
 10. Turn the system back on for all users.&lt;br /&gt;
&lt;br /&gt;
==Database clustering==&lt;br /&gt;
&lt;br /&gt;
Anything ACID compliant should be ok. For example even-odd master-master MySQL is not ok.&lt;br /&gt;
&lt;br /&gt;
TODO: add descriptions of ACID compliant DB cluster setups&lt;br /&gt;
&lt;br /&gt;
==More information==&lt;br /&gt;
&lt;br /&gt;
* [http://thamblings.blogspot.cz/2013/07/deploying-moodle-continued.html Deploying Moodle]&lt;br /&gt;
* [https://docs.moodle.org/25/en/Server_cluster Server cluster (user docs)]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_meeting_April_2015&amp;diff=47605</id>
		<title>Developer meeting April 2015</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_meeting_April_2015&amp;diff=47605"/>
		<updated>2015-04-19T21:08:42Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Timezones handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; April 2015 meeting notes&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Time&lt;br /&gt;
| [http://www.timeanddate.com/worldclock/fixedtime.html?year=2015&amp;amp;month=4&amp;amp;day=21&amp;amp;hour=07&amp;amp;min=0&amp;amp;sec=0 07:00 UTC on Tuesday, 21 April 2015] [http://www.google.com/calendar/event?action=TEMPLATE&amp;amp;text=Moodle+General+developer+meeting&amp;amp;dates=20150421T070000Z/20150421T090000Z&amp;amp;details=&amp;amp;location= &amp;lt;span class=&amp;quot;btn btn-info&amp;quot;&amp;gt;Add to my calendar&amp;lt;/span&amp;gt;]&lt;br /&gt;
|-&lt;br /&gt;
| Meeting room&lt;br /&gt;
| [http://www.youtube.com/watch?v=g329dAC_oqI Live stream at YouTube]&lt;br /&gt;
|-&lt;br /&gt;
| Forum discussion&lt;br /&gt;
| [https://moodle.org/mod/forum/discuss.php?d=311824 GDF thread]&lt;br /&gt;
|-&lt;br /&gt;
| Chat&lt;br /&gt;
| [https://moodle.org/local/chatlogs/info.php Regular dev chat]&lt;br /&gt;
|-&lt;br /&gt;
| Twitter&lt;br /&gt;
| [https://twitter.com/search?q=%23moodledev #moodledev]&lt;br /&gt;
|-&lt;br /&gt;
| Event page&lt;br /&gt;
| [https://plus.google.com/events/c003f0fctdrmd3oo9dn6jpbpqu4 Google+ event page]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Agenda ==&lt;br /&gt;
&lt;br /&gt;
The meeting focuses on changes in the upcoming Moodle 2.9 release with special attention paid to impact of these changes on community contributors and plugin authors.&lt;br /&gt;
&lt;br /&gt;
Work in progress - individual items to be confirmed, the exact order is subject of change.&lt;br /&gt;
&lt;br /&gt;
=== Navigation improvements ===&lt;br /&gt;
&lt;br /&gt;
=== First experiences with mustache, the new template framework ===&lt;br /&gt;
&lt;br /&gt;
* by [https://moodle.org/user/profile.php?id=25214 Urs Hunkler] (confirmed)&lt;br /&gt;
* See [https://moodle.org/mod/forum/discuss.php?d=311119 the discussion] for more details.&lt;br /&gt;
&lt;br /&gt;
To see how to work with the Moodle Mustache implementation I refactored the »clean« theme to a Mustache theme. The process went quite well. I&#039;ll try to show the main thoughts and steps in the refactoring process in about 10 minutes. We may have some time to talk about Moodle Mustache afterwards.&lt;br /&gt;
&lt;br /&gt;
You may have a look at the theme »cleanm« in my [https://github.com/uhunkler/moodle/tree/MOODLE_29_mustaches Git repo].&lt;br /&gt;
&lt;br /&gt;
[[User:Urs Hunkler|Urs Hunkler]] ([[User talk:Urs Hunkler|talk]]) 23:32, 13 April 2015 (AWST)&lt;br /&gt;
&lt;br /&gt;
=== Unified AJAX script handler ===&lt;br /&gt;
&lt;br /&gt;
* MDL-49163&lt;br /&gt;
&lt;br /&gt;
=== Timezones handling ===&lt;br /&gt;
&lt;br /&gt;
* by [https://moodle.org/user/profile.php?id=12863 Petr Škoda] (confirmed)&lt;br /&gt;
* MDL-49684&lt;br /&gt;
Moodle 2.9 is switching to native PHP date and time code. The old homegrown DST switching routines were completely removed. Instead of downloading the timezone.txt file administrators need to keep their PHP timezone up-to-date. There are still some remaining date/time bugs throughout the codebase, but this change makes the fixing much easier because developers may finally use the DateTime class or legacy date functions in PHP.&lt;br /&gt;
&lt;br /&gt;
=== Per-request temp directories ===&lt;br /&gt;
&lt;br /&gt;
* by Andrew Nicols&lt;br /&gt;
* MDL-44874&lt;br /&gt;
&lt;br /&gt;
=== Behat tests runs in parallel ===&lt;br /&gt;
&lt;br /&gt;
* by Rajesh Taneja&lt;br /&gt;
* MDL-39752&lt;br /&gt;
As we have over 33000 behat steps in moodle and it&#039;s growing rapidly. It takes around 12 hours to execute whole behat suite, which is not expectable for any testing environment. With initial work from Tony and Damyon, we came up with strategy of splitting feature files in different processes and run them in parallel. I will try cover options and demo for running behat in parallel.&lt;br /&gt;
&lt;br /&gt;
== More ==&lt;br /&gt;
&lt;br /&gt;
* If you have something you&#039;d like to add to this page, please contact [https://moodle.org/user/profile.php?id=1601 David Mudrák].&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_meeting_April_2015&amp;diff=47604</id>
		<title>Developer meeting April 2015</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_meeting_April_2015&amp;diff=47604"/>
		<updated>2015-04-19T21:08:01Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Timezones handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; April 2015 meeting notes&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Time&lt;br /&gt;
| [http://www.timeanddate.com/worldclock/fixedtime.html?year=2015&amp;amp;month=4&amp;amp;day=21&amp;amp;hour=07&amp;amp;min=0&amp;amp;sec=0 07:00 UTC on Tuesday, 21 April 2015] [http://www.google.com/calendar/event?action=TEMPLATE&amp;amp;text=Moodle+General+developer+meeting&amp;amp;dates=20150421T070000Z/20150421T090000Z&amp;amp;details=&amp;amp;location= &amp;lt;span class=&amp;quot;btn btn-info&amp;quot;&amp;gt;Add to my calendar&amp;lt;/span&amp;gt;]&lt;br /&gt;
|-&lt;br /&gt;
| Meeting room&lt;br /&gt;
| [http://www.youtube.com/watch?v=g329dAC_oqI Live stream at YouTube]&lt;br /&gt;
|-&lt;br /&gt;
| Forum discussion&lt;br /&gt;
| [https://moodle.org/mod/forum/discuss.php?d=311824 GDF thread]&lt;br /&gt;
|-&lt;br /&gt;
| Chat&lt;br /&gt;
| [https://moodle.org/local/chatlogs/info.php Regular dev chat]&lt;br /&gt;
|-&lt;br /&gt;
| Twitter&lt;br /&gt;
| [https://twitter.com/search?q=%23moodledev #moodledev]&lt;br /&gt;
|-&lt;br /&gt;
| Event page&lt;br /&gt;
| [https://plus.google.com/events/c003f0fctdrmd3oo9dn6jpbpqu4 Google+ event page]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Agenda ==&lt;br /&gt;
&lt;br /&gt;
The meeting focuses on changes in the upcoming Moodle 2.9 release with special attention paid to impact of these changes on community contributors and plugin authors.&lt;br /&gt;
&lt;br /&gt;
Work in progress - individual items to be confirmed, the exact order is subject of change.&lt;br /&gt;
&lt;br /&gt;
=== Navigation improvements ===&lt;br /&gt;
&lt;br /&gt;
=== First experiences with mustache, the new template framework ===&lt;br /&gt;
&lt;br /&gt;
* by [https://moodle.org/user/profile.php?id=25214 Urs Hunkler] (confirmed)&lt;br /&gt;
* See [https://moodle.org/mod/forum/discuss.php?d=311119 the discussion] for more details.&lt;br /&gt;
&lt;br /&gt;
To see how to work with the Moodle Mustache implementation I refactored the »clean« theme to a Mustache theme. The process went quite well. I&#039;ll try to show the main thoughts and steps in the refactoring process in about 10 minutes. We may have some time to talk about Moodle Mustache afterwards.&lt;br /&gt;
&lt;br /&gt;
You may have a look at the theme »cleanm« in my [https://github.com/uhunkler/moodle/tree/MOODLE_29_mustaches Git repo].&lt;br /&gt;
&lt;br /&gt;
[[User:Urs Hunkler|Urs Hunkler]] ([[User talk:Urs Hunkler|talk]]) 23:32, 13 April 2015 (AWST)&lt;br /&gt;
&lt;br /&gt;
=== Unified AJAX script handler ===&lt;br /&gt;
&lt;br /&gt;
* MDL-49163&lt;br /&gt;
&lt;br /&gt;
=== Timezones handling ===&lt;br /&gt;
&lt;br /&gt;
* by [https://moodle.org/user/profile.php?id=12863 Petr Škoda] (confirmed)&lt;br /&gt;
* MDL-49684&lt;br /&gt;
Moodle 2.9.0 is switching to native PHP date and time code. The old homegrown DST switching routines were completely removed. Instead of downloading the timezone.txt file administrators need to keep their PHP timezone up-to-date. There are still some remaining date/time bugs throughout the codebase, but this change makes the fixing much easier because developers may finally use the DateTime class or legacy date functions in PHP.&lt;br /&gt;
&lt;br /&gt;
=== Per-request temp directories ===&lt;br /&gt;
&lt;br /&gt;
* by Andrew Nicols&lt;br /&gt;
* MDL-44874&lt;br /&gt;
&lt;br /&gt;
=== Behat tests runs in parallel ===&lt;br /&gt;
&lt;br /&gt;
* by Rajesh Taneja&lt;br /&gt;
* MDL-39752&lt;br /&gt;
As we have over 33000 behat steps in moodle and it&#039;s growing rapidly. It takes around 12 hours to execute whole behat suite, which is not expectable for any testing environment. With initial work from Tony and Damyon, we came up with strategy of splitting feature files in different processes and run them in parallel. I will try cover options and demo for running behat in parallel.&lt;br /&gt;
&lt;br /&gt;
== More ==&lt;br /&gt;
&lt;br /&gt;
* If you have something you&#039;d like to add to this page, please contact [https://moodle.org/user/profile.php?id=1601 David Mudrák].&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_meeting_April_2015&amp;diff=47603</id>
		<title>Developer meeting April 2015</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_meeting_April_2015&amp;diff=47603"/>
		<updated>2015-04-19T21:03:24Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Timezones handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; April 2015 meeting notes&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Time&lt;br /&gt;
| [http://www.timeanddate.com/worldclock/fixedtime.html?year=2015&amp;amp;month=4&amp;amp;day=21&amp;amp;hour=07&amp;amp;min=0&amp;amp;sec=0 07:00 UTC on Tuesday, 21 April 2015] [http://www.google.com/calendar/event?action=TEMPLATE&amp;amp;text=Moodle+General+developer+meeting&amp;amp;dates=20150421T070000Z/20150421T090000Z&amp;amp;details=&amp;amp;location= &amp;lt;span class=&amp;quot;btn btn-info&amp;quot;&amp;gt;Add to my calendar&amp;lt;/span&amp;gt;]&lt;br /&gt;
|-&lt;br /&gt;
| Meeting room&lt;br /&gt;
| [http://www.youtube.com/watch?v=g329dAC_oqI Live stream at YouTube]&lt;br /&gt;
|-&lt;br /&gt;
| Forum discussion&lt;br /&gt;
| [https://moodle.org/mod/forum/discuss.php?d=311824 GDF thread]&lt;br /&gt;
|-&lt;br /&gt;
| Chat&lt;br /&gt;
| [https://moodle.org/local/chatlogs/info.php Regular dev chat]&lt;br /&gt;
|-&lt;br /&gt;
| Twitter&lt;br /&gt;
| [https://twitter.com/search?q=%23moodledev #moodledev]&lt;br /&gt;
|-&lt;br /&gt;
| Event page&lt;br /&gt;
| [https://plus.google.com/events/c003f0fctdrmd3oo9dn6jpbpqu4 Google+ event page]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Agenda ==&lt;br /&gt;
&lt;br /&gt;
The meeting focuses on changes in the upcoming Moodle 2.9 release with special attention paid to impact of these changes on community contributors and plugin authors.&lt;br /&gt;
&lt;br /&gt;
Work in progress - individual items to be confirmed, the exact order is subject of change.&lt;br /&gt;
&lt;br /&gt;
=== Navigation improvements ===&lt;br /&gt;
&lt;br /&gt;
=== First experiences with mustache, the new template framework ===&lt;br /&gt;
&lt;br /&gt;
* by [https://moodle.org/user/profile.php?id=25214 Urs Hunkler] (confirmed)&lt;br /&gt;
* See [https://moodle.org/mod/forum/discuss.php?d=311119 the discussion] for more details.&lt;br /&gt;
&lt;br /&gt;
To see how to work with the Moodle Mustache implementation I refactored the »clean« theme to a Mustache theme. The process went quite well. I&#039;ll try to show the main thoughts and steps in the refactoring process in about 10 minutes. We may have some time to talk about Moodle Mustache afterwards.&lt;br /&gt;
&lt;br /&gt;
You may have a look at the theme »cleanm« in my [https://github.com/uhunkler/moodle/tree/MOODLE_29_mustaches Git repo].&lt;br /&gt;
&lt;br /&gt;
[[User:Urs Hunkler|Urs Hunkler]] ([[User talk:Urs Hunkler|talk]]) 23:32, 13 April 2015 (AWST)&lt;br /&gt;
&lt;br /&gt;
=== Unified AJAX script handler ===&lt;br /&gt;
&lt;br /&gt;
* MDL-49163&lt;br /&gt;
&lt;br /&gt;
=== Timezones handling ===&lt;br /&gt;
&lt;br /&gt;
* by [https://moodle.org/user/profile.php?id=12863 Petr Škoda] (confirmed)&lt;br /&gt;
* MDL-49684&lt;br /&gt;
Moodle 2.9.0 is switching to native PHP date and time code. The old homegrown DST switching routines were completely removed.&lt;br /&gt;
&lt;br /&gt;
=== Per-request temp directories ===&lt;br /&gt;
&lt;br /&gt;
* by Andrew Nicols&lt;br /&gt;
* MDL-44874&lt;br /&gt;
&lt;br /&gt;
=== Behat tests runs in parallel ===&lt;br /&gt;
&lt;br /&gt;
* by Rajesh Taneja&lt;br /&gt;
* MDL-39752&lt;br /&gt;
As we have over 33000 behat steps in moodle and it&#039;s growing rapidly. It takes around 12 hours to execute whole behat suite, which is not expectable for any testing environment. With initial work from Tony and Damyon, we came up with strategy of splitting feature files in different processes and run them in parallel. I will try cover options and demo for running behat in parallel.&lt;br /&gt;
&lt;br /&gt;
== More ==&lt;br /&gt;
&lt;br /&gt;
* If you have something you&#039;d like to add to this page, please contact [https://moodle.org/user/profile.php?id=1601 David Mudrák].&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_meeting_October_2014&amp;diff=46543</id>
		<title>Developer meeting October 2014</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_meeting_October_2014&amp;diff=46543"/>
		<updated>2014-10-20T19:48:51Z</updated>

		<summary type="html">&lt;p&gt;Skodak: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; October 2014 meeting notes&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Time&lt;br /&gt;
| [http://timeanddate.com/worldclock/fixedtime.html?year=2014&amp;amp;month=10&amp;amp;day=21&amp;amp;hour=13&amp;amp;min=0&amp;amp;sec=0 13:00 UTC on Tuesday, 21 October 2014]&lt;br /&gt;
|-&lt;br /&gt;
| Meeting room&lt;br /&gt;
| [https://www.youtube.com/watch?v=lc4rOo6Tu_o Live stream at YouTube]&lt;br /&gt;
|-&lt;br /&gt;
| Chat&lt;br /&gt;
| [https://moodle.org/local/chatlogs/info.php Regular dev chat]&lt;br /&gt;
|-&lt;br /&gt;
| Twitter&lt;br /&gt;
| [https://twitter.com/search?q=%23moodledev #moodledev]&lt;br /&gt;
|-&lt;br /&gt;
| Event page&lt;br /&gt;
| [https://plus.google.com/events/ctssr21hp0nitv3i8vg5l4aa3t8 Google+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This meeting will focus on the impending release.&lt;br /&gt;
&lt;br /&gt;
The meeting will be streamed live on YouTube with chat through the regular Dev chat room and comments on Twitter.&lt;br /&gt;
&lt;br /&gt;
== Agenda ==&lt;br /&gt;
; Moodle 2.8 overview: by Martin Dougiamas, see [[Moodle 2.8 release notes]]&lt;br /&gt;
; Inbound Message API: by Andrew Nicols, MDL-46282&lt;br /&gt;
; String deprecation process: by Marina Glancy and David Mudrák, MDL-46585, see [[String deprecation]]&lt;br /&gt;
; Assignment table restructure: by Damyon Wiese, MDL-46171, see [https://github.com/moodle/moodle/blob/master/mod/assign/upgrade.txt mod/assign/upgrade.txt]&lt;br /&gt;
; Mobile App development news and roadmap: by Juan Leyva&lt;br /&gt;
; Plugins directory news and roadmap: by David Mudrák ([https://moodle.org/mod/forum/view.php?id=8149 plugins traffic blog], [https://moodle.org/plugins/browse.php?list=award&amp;amp;id=2 featured plugins])&lt;br /&gt;
; The future of MNet: see [[MNet Roadmap]]&lt;br /&gt;
; Proposal for making the quiz continue to work when the internet connection drops: by Tim Hunt, MDL-47688.&lt;br /&gt;
; Date/Time/Timezone cleanup: proposed by Petr Skoda&lt;br /&gt;
&lt;br /&gt;
If you have something you&#039;d like to add to this page, please edit this page or contact [https://moodle.org/user/profile.php?id=1601 David Mudrák].&lt;br /&gt;
&lt;br /&gt;
== Questions from the audience ==&lt;br /&gt;
&lt;br /&gt;
# How is Moodle HQ reacting to the developer community reaction to the new logging/event system? ( [https://moodle.org/mod/forum/discuss.php?d=272042 very] [https://moodle.org/mod/forum/discuss.php?d=267920 many] [https://moodle.org/mod/forum/discuss.php?d=256457 related] [https://moodle.org/mod/forum/discuss.php?d=257934 threads])&lt;br /&gt;
# Does Moodle HQ have a response to Yahoo&#039;s recent announcement that it has removed support for YUI (discussed [https://moodle.org/mod/forum/discuss.php?d=268190 here])?&lt;br /&gt;
# Are there any goodies for the upcoming version of Moodle 3 that you are targeting in the long-term roadmap?&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Developer_meeting_October_2014&amp;diff=46474</id>
		<title>Developer meeting October 2014</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Developer_meeting_October_2014&amp;diff=46474"/>
		<updated>2014-10-16T02:23:43Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Agenda */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Developer meetings]] &amp;gt; October 2014 meeting notes&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Time&lt;br /&gt;
| [http://timeanddate.com/worldclock/fixedtime.html?year=2014&amp;amp;month=10&amp;amp;day=21&amp;amp;hour=13&amp;amp;min=0&amp;amp;sec=0 13:00 UTC on Tuesday, 21 October 2014]&lt;br /&gt;
|-&lt;br /&gt;
| Meeting room&lt;br /&gt;
| [https://www.youtube.com/watch?v=lc4rOo6Tu_o Live stream at YouTube]&lt;br /&gt;
|-&lt;br /&gt;
| Chat&lt;br /&gt;
| [https://moodle.org/local/chatlogs/info.php Regular dev chat]&lt;br /&gt;
|-&lt;br /&gt;
| Twitter&lt;br /&gt;
| [https://twitter.com/search?q=%23moodledev #moodledev]&lt;br /&gt;
|-&lt;br /&gt;
| Event page&lt;br /&gt;
| [https://plus.google.com/events/ctssr21hp0nitv3i8vg5l4aa3t8 Google+]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This meeting will focus on the impending release.&lt;br /&gt;
&lt;br /&gt;
The meeting will be streamed live on YouTube with chat through the regular Dev chat room and comments on Twitter.&lt;br /&gt;
&lt;br /&gt;
== Agenda ==&lt;br /&gt;
; Moodle 2.8 overview: by Martin Dougiamas, see [[Moodle 2.8 release notes]]&lt;br /&gt;
; Inbound Message API: by Andrew Nicols, MDL-46282&lt;br /&gt;
; String deprecation process: by Marina Glancy and David Mudrák, MDL-46585, see [[String deprecation]]&lt;br /&gt;
; Assignment table restructure: by Damyon Wiese, MDL-46171, see [https://github.com/moodle/moodle/blob/master/mod/assign/upgrade.txt mod/assign/upgrade.txt]&lt;br /&gt;
; Mobile App development news and roadmap: by Juan Leyva&lt;br /&gt;
; Featured plugins in the plugins directory: by David Mudrák, see [https://moodle.org/mod/forum/view.php?id=8149 plugins traffic blog] and [https://moodle.org/plugins/browse.php?list=award&amp;amp;id=2 their list].&lt;br /&gt;
; The future of MNet: see [[MNet Roadmap]]&lt;br /&gt;
; Proposal for making the quiz continue to work when the internet connection drops: by Tim Hunt, MDL-47688.&lt;br /&gt;
; Data/timezone cleanup: proposed by Petr Skoda&lt;br /&gt;
&lt;br /&gt;
If you have something you&#039;d like to add to this page, please edit this page or contact [https://moodle.org/user/profile.php?id=1601 David Mudrák].&lt;br /&gt;
&lt;br /&gt;
== Questions from the audience ==&lt;br /&gt;
&lt;br /&gt;
# How is Moodle HQ reacting to the developer community reaction to the new logging/event system? ( [https://moodle.org/mod/forum/discuss.php?d=272042 very] [https://moodle.org/mod/forum/discuss.php?d=267920 many] [https://moodle.org/mod/forum/discuss.php?d=256457 related] [https://moodle.org/mod/forum/discuss.php?d=257934 threads])&lt;br /&gt;
# Does Moodle HQ have a response to Yahoo&#039;s recent announcement that it has removed support for YUI (discussed [https://moodle.org/mod/forum/discuss.php?d=268190 here])?&lt;br /&gt;
# Are there any goodies for the upcoming version of Moodle 3 that you are targeting in the long-term roadmap?&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46451</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46451"/>
		<updated>2014-10-14T22:22:32Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Accuracy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objectid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters - indicating &#039;c&#039;reate, &#039;r&#039;ead, &#039;u&#039;pdate or &#039;d&#039;elete operation. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the logging subsystem, and cannot be used later when logged event is displayed.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
It is important to trigger individual events for each and every action, bulk events are very strongly discouraged because existing observers would not receive important information. Changes from one to many would break backwards compatibility with observers and reporting.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46450</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46450"/>
		<updated>2014-10-14T22:19:27Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Accuracy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objectid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters - indicating &#039;c&#039;reate, &#039;r&#039;ead, &#039;u&#039;pdate or &#039;d&#039;elete operation. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the logging subsystem, and cannot be used later when logged event is displayed.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
It is important to trigger individual events for each and every action, bulk events are very strongly discouraged.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46449</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46449"/>
		<updated>2014-10-14T22:16:27Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Record caching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objectid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters - indicating &#039;c&#039;reate, &#039;r&#039;ead, &#039;u&#039;pdate or &#039;d&#039;elete operation. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the logging subsystem, and cannot be used later when logged event is displayed.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46448</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46448"/>
		<updated>2014-10-14T22:12:12Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Properties */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objectid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters - indicating &#039;c&#039;reate, &#039;r&#039;ead, &#039;u&#039;pdate or &#039;d&#039;elete operation. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46447</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46447"/>
		<updated>2014-10-14T22:10:25Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Properties */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objectid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46446</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46446"/>
		<updated>2014-10-14T21:59:54Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Triggering events */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events are in namespace &#039;\core\event\&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46445</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46445"/>
		<updated>2014-10-14T21:58:35Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Triggering events */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Event class name is a unique identifier of each event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46444</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46444"/>
		<updated>2014-10-14T21:57:17Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Differences from old event handling */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is a separate record snapshot cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# There is no database access in new event dispatching code.&lt;br /&gt;
# There is no support for delayed cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46443</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46443"/>
		<updated>2014-10-14T21:53:05Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Event dispatching */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available &#039;events.php&#039; files from core and all plugins. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Original handlers could not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers of the current event are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46442</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46442"/>
		<updated>2014-10-14T21:50:00Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Event observers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded during upgrade.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available in &#039;events.php&#039; files. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Current handlers must not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46441</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46441"/>
		<updated>2014-10-14T21:48:00Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Backwards compatibility and migration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters have been migrated to method get_legacy_log_data() in new events. Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available in &#039;events.php&#039; files. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Current handlers must not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46440</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46440"/>
		<updated>2014-10-14T21:44:50Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Events API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. During development new event definitions and observers can be added without the need to upgrade, only purging of the MUC cache is required.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters has been migrated inside new events method, in get_legacy_log_data(). Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available in &#039;events.php&#039; files. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Current handlers must not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46439</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46439"/>
		<updated>2014-10-14T21:43:03Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Events API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions are automatically included when needed, without having to maintain lists of known event types. New event definitions can be added without the need to upgrade, only purging of the MUC cache is required after adding a new observer.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters has been migrated inside new events method, in get_legacy_log_data(). Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available in &#039;events.php&#039; files. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Current handlers must not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46438</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46438"/>
		<updated>2014-10-14T21:41:15Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Events API */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as event description).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions is automatically included when needed, without having to maintain lists of known event types. New event definitions can be added without the need to upgrade, only purging of the MUC cache is required after adding a new observer.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters has been migrated inside new events method, in get_legacy_log_data(). Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available in &#039;events.php&#039; files. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Current handlers must not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46437</id>
		<title>Events API</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Events_API&amp;diff=46437"/>
		<updated>2014-10-14T21:39:37Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Event observers */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox Project&lt;br /&gt;
|name = Events 2&lt;br /&gt;
|state = Completed&lt;br /&gt;
|tracker = MDL-39797 , MDL-39952, MDL-39846&lt;br /&gt;
|discussion = https://moodle.org/mod/forum/discuss.php?d=229425&lt;br /&gt;
|assignee = Backend Team&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= What are events? =&lt;br /&gt;
&lt;br /&gt;
Events are atomic pieces of information describing something that happened in Moodle. Events are primarily the result of user actions, but could also be the result of the [[:en:Cron|cron]] process or administration actions [[:en:Administration via command line|undertaken via the command line]].&lt;br /&gt;
&lt;br /&gt;
When an action takes place, an event is created by a [[Core APIs|core API]] or [[Plugins|plugin]]. The Events system then disseminates this event information to observers registered for this event. In this way, the events system acts as a communication backbone throughout the Moodle system. Event observers can not modify event data or interrupt the dispatching of events, it is a one way communication channel.&lt;br /&gt;
&lt;br /&gt;
= Why was a new events system needed? =&lt;br /&gt;
&lt;br /&gt;
The need to improve the Events system was prompted by a need for a richer and more efficient logging system, however the benefits of this improvement are useful to other parts of Moodle that observe event information.&lt;br /&gt;
&lt;br /&gt;
* The events need to be more strictly defined for logging and other advanced use cases. They need to contain more information, organised in a standardised way (in addition to the fields from the legacy log table and log_actions table).&lt;br /&gt;
* Complex data types were allowed in old events, which was causing major problems when serialising/storing/unserialising the data.&lt;br /&gt;
* The logging tables and events contain similar information and were triggered at the same places; utilising events for logging would remove this code duplication. All events should be loggable and all current log entries should be triggered as events.&lt;br /&gt;
* The logging system is an event observer, listening to all events and directing them to logging storage plugins in a controllable way.&lt;br /&gt;
* It is possible to subscribe to &#039;*&#039; event, which would allow a system to potentially observe, and selectively deal with, all events. Previously, handlers did not receive event names which made this problematic.&lt;br /&gt;
* Previously, event handlers could trigger exceptions during site upgrades, which would lead to fatal upgrade problems. The new design eliminates this.&lt;br /&gt;
* Failure in previous handlers blocked dispatching of subsequent events. Problems in new observers would only be logged and execution would continue normally.&lt;br /&gt;
* Previously, execution of external handlers during DB transactions blocked other handlers. This would be eliminated by in-memory buffer for external events.&lt;br /&gt;
* Previously there was no observer priority.&lt;br /&gt;
* Previously, nested events were not dispatched sequentially, which would change the order of events were received by lower priority handlers.&lt;br /&gt;
&lt;br /&gt;
= Performance =&lt;br /&gt;
Some basic profiling was conducted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note&amp;quot;&amp;gt;This next two paragraphs need to be replaced with results.&amp;lt;/p&amp;gt;&lt;br /&gt;
There is a general plan to complete pre- and post-implementation testing as development happens. The new system will be implemented in parallel with the old one, which should help with comparison of new and old logging and event triggering performance on each page.&lt;br /&gt;
&lt;br /&gt;
Our aim is to capture more information about actions in Moodle by triggering more events and logging more information about each event. This is going to impact negatively on performance. We hope to offset that impact by improving log storage, simplifying event dispatching and adding other core performance improvements. The proposed class structure of the base event should allow some new advanced techniques, which may also improve performance in some scenarios.&lt;br /&gt;
&lt;br /&gt;
More details will be added to this section soon.&lt;br /&gt;
&lt;br /&gt;
= Events API =&lt;br /&gt;
&lt;br /&gt;
Each plugin defines the events that it can report (trigger) by extending an abstract base class, once for each possible event. This approach has several benefits.&lt;br /&gt;
; Events are active objects&lt;br /&gt;
: When they are triggered and possibly after they are reinstantiated (say, when they are retrieved from a log), an event object is able to provide callback functions for various purposes (such as capability checks).&lt;br /&gt;
; Automatic inclusion&lt;br /&gt;
: Event class definitions is automatically included when needed, without having to maintain lists of known event types. New event definitions can be added without the need to upgrade, only purging of the MUC cache is required after adding a new observer.&lt;br /&gt;
; Maintainability&lt;br /&gt;
: It is relatively simple to add new events and migrate existing events. Code review is simplified because there is less duplication of code when triggering same events and all event related information/code is concentrated in one file in fixed locations.&lt;br /&gt;
; Self documenting&lt;br /&gt;
: The behaviour of events is combined with the definition of events in one place (file). It is easy for event observer writers to know what events a plugin can trigger. This includes support for autocompletion and code inspection in modern IDEs. A list of all events is now available as a report to administrators and researchers.&lt;br /&gt;
; Quick, self-validating data structure&lt;br /&gt;
: As events are instantiated objects, the PHP processor will validate the structure and type of event classes. This does not ensure data value validity, but does give some assurance of consistency and it also detects unintentional typos.&lt;br /&gt;
&lt;br /&gt;
== Backwards compatibility and migration ==&lt;br /&gt;
&lt;br /&gt;
Events:&lt;br /&gt;
* All legacy events in the standard distribution have been replaced with the new events API and events_trigger() has been deprecated.&lt;br /&gt;
* For events that already exist in Moodle 2.5, the additional legacy information has been added to the event data (in properties &#039;legacyeventname&#039; and &#039;legacyeventdata&#039;)&lt;br /&gt;
* The legacy events handling code is maintained  separately and will continue being supported in Moodle 2.7.&lt;br /&gt;
* All legacy events-handlers have been migrated to new observers in standard distribution.&lt;br /&gt;
* In future, more subsystems may be migrated to events-observers, ex.: gradebook history, completion.&lt;br /&gt;
&lt;br /&gt;
Logging:&lt;br /&gt;
* The function add_to_log() has been deprecated with a notice as of Moodle 2.7.&lt;br /&gt;
* Existing add_to_log() parameters has been migrated inside new events method, in get_legacy_log_data(). Calls to core_event_base::trigger() will lead to entries being added to the legacy log table if the legacy log plugin is enabled.&lt;br /&gt;
&lt;br /&gt;
See https://docs.moodle.org/dev/Migrating_logging_calls_in_plugins&lt;br /&gt;
&lt;br /&gt;
== Event dispatching and observers ==&lt;br /&gt;
&lt;br /&gt;
The new event dispatching system is completely separate from the old events code. Original event handlers are now called observers with the description stored in the same db/events.php file, but as a new array with a different format.&lt;br /&gt;
&lt;br /&gt;
=== Event observers ===&lt;br /&gt;
&lt;br /&gt;
Observers are described in db/events.php in the array $observers, the array is not indexed and contains a list of observers defined as an array with the following properties;&lt;br /&gt;
* eventname – fully qualified event class name or &amp;quot;*&amp;quot; indicating all events, ex.: &#039;&#039;\plugintype_pluginname\event\something_happened&#039;&#039;.&lt;br /&gt;
* callback - PHP callable type.&lt;br /&gt;
* includefile - optional. File to be included before calling the observer. Path relative to dirroot.&lt;br /&gt;
* priority - optional. Defaults to 0. Observers with higher priority are notified first.&lt;br /&gt;
* internal - optional. Defaults to true. Non-internal observers are not called during database transactions, but instead after a successful commit of the transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&lt;br /&gt;
$observers = array(&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_one&#039;,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;\core\event\sample_executed&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::external_observer&#039;,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 200,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; false,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
    array(&lt;br /&gt;
        &#039;eventname&#039;   =&amp;gt; &#039;*&#039;,&lt;br /&gt;
        &#039;callback&#039;    =&amp;gt; &#039;core_event_sample_observer::observe_all&#039;,&lt;br /&gt;
        &#039;includefile&#039; =&amp;gt; null,&lt;br /&gt;
        &#039;internal&#039;    =&amp;gt; true,&lt;br /&gt;
        &#039;priority&#039;    =&amp;gt; 9999,&lt;br /&gt;
    ),&lt;br /&gt;
&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE: Event observers are cached. If you add or change observers you need to purge the caches or they will not be recognised. Plugin developers need to bump up the version number to guarantee that the list of observers is reloaded.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Event dispatching ===&lt;br /&gt;
&lt;br /&gt;
A list of available observers is constructed on the fly directly from all available in &#039;events.php&#039; files. Previously handlers were installed only during installation and upgrade. This has little risk of performance regression because the list is already cached in MUC. Observers get events before installation or any upgrade, however observers are not notified during the initial installation of Moodle core tables.&lt;br /&gt;
&lt;br /&gt;
Developers of observers must make sure that execution does not end with a fatal error under any condition (before install, before upgrade or normal operation). Exceptions are automatically captured, logged in the PHP error log, and notification of other observers continues. Current handlers must not throw any exceptions at any time.&lt;br /&gt;
&lt;br /&gt;
Observers are notified sequentially in the same order in which events were triggered. This means that events triggered in observers are queued in FIFO buffer and are processed after all observers are notified.&lt;br /&gt;
&lt;br /&gt;
=== Differences from old event handling ===&lt;br /&gt;
&lt;br /&gt;
# New events contain a lot more structured information.&lt;br /&gt;
# There is separate context cache that may be used when deleting data or for observer performance improvements.&lt;br /&gt;
# No database access is allowed in new event dispatching code.&lt;br /&gt;
# There is no support for cron execution. This eliminates performance problems, simplifies events dispatching and prevents abuse of cron events.&lt;br /&gt;
# Events triggered in observers are processed in a different order.&lt;br /&gt;
# External events are buffered when a transaction is in progress, instead of being sent to the cron queue.&lt;br /&gt;
# It is possible to define multiple observers for one event in one events.php file.&lt;br /&gt;
# It is possible to subscribe an observer to all events.&lt;br /&gt;
# The new event manager is using frankenstyle autoloading, which leads to a smaller memory footprint when events are not used on the current page.&lt;br /&gt;
&lt;br /&gt;
== Triggering events ==&lt;br /&gt;
&lt;br /&gt;
* All event definitions are classes extending the \core\event\base class.&lt;br /&gt;
* Events are triggered by creating a new instance of the class event and executing $event-&amp;gt;trigger().&lt;br /&gt;
* Each event class names are a unique identifier of the event.&lt;br /&gt;
* Class names and namespace follow the identifier scheme \&#039;&#039;&#039;frankenstyle_component&#039;&#039;&#039;\event\&#039;&#039;&#039;some_object_action&#039;&#039;&#039;. Core events have prefix &#039;core_&#039;.&lt;br /&gt;
* Each event class is defined in a separate file. File name and location must match the class name for the use of auto loading, for example: &#039;&#039;&#039;plugindir&#039;&#039;&#039;/classes/event/&#039;&#039;&#039;something_happened&#039;&#039;&#039;.php&lt;br /&gt;
* The event identifier suffix has the form &#039;&#039;some_object_action&#039;&#039;  (&#039;&#039;&#039;something_happened&#039;&#039;&#039; in the example above) and should follow the standard naming convention. The last word after the underscore is automatically parsed as its action, the rest of word is its object.&lt;br /&gt;
&lt;br /&gt;
Decision:[[#Verb_list| Recommended verb list]]&lt;br /&gt;
&lt;br /&gt;
Examples: \core\event\course_completed, \mod_assign\event\submission_commented, \mod_forum\event\post_shared, \mod_forum\event\post_responded, etc.&lt;br /&gt;
&lt;br /&gt;
* Ideally, it should be possible to trigger an event without gathering additional information for the event. To reduce the cost of data gathering, specifically the cost of database reads, at least the minimal values needed to trigger an event should be already available in variables.&lt;br /&gt;
&lt;br /&gt;
An example of triggering an event:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$event = \mod_myplugin\event\something_happened::create(array(&#039;context&#039; =&amp;gt; $context, &#039;objectid&#039; =&amp;gt; YYY, &#039;other&#039; =&amp;gt; ZZZ));&lt;br /&gt;
// ... code that may add some record snapshots&lt;br /&gt;
$event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Use of PHP autoloading ===&lt;br /&gt;
&lt;br /&gt;
All new OOP APIs in Moodle 2.6 onwards are going to use class auto loading - see [[Automatic class loading]]. New events use PHP within strictly defined namespaces, which concentrate all event classes in the classes/event/ subdirectory.&lt;br /&gt;
&lt;br /&gt;
=== Why separate classes? ===&lt;br /&gt;
Pros&lt;br /&gt;
* Maintainability - It is much easier to review, debug and integrate.&lt;br /&gt;
* Self documenting, behaviour is combined with definition.&lt;br /&gt;
* It is extremely flexible for plugin developers and core devs too.&lt;br /&gt;
* Automatic lists events can be generated without being installed - PHPDocs as events documentation.&lt;br /&gt;
* It is included only when needed using autoloading.&lt;br /&gt;
* Self-validating data structure (by PHP).&lt;br /&gt;
* Some developers will find it easier to copy whole class files as templates.&lt;br /&gt;
Cons&lt;br /&gt;
* Big learning curve for developers without OOP skills (all other new subsystems in Moodle already use OOP, you can not code without these skills any more).&lt;br /&gt;
* Some developers may find it harder to copy-and-paste examples because they will need to create new class first and use it afterwards (this can be viewed as a benefit because it forces developers to think more about events).&lt;br /&gt;
* This has increased the number lines of code in Moodle for events and logging.&lt;br /&gt;
&lt;br /&gt;
== Information contained in events ==&lt;br /&gt;
&lt;br /&gt;
Events have to contain as much information as they can, but this should not affect the performance. That&#039;s why part of the information is available in properties, and the rest via methods. This allows for delayed computation of data until the time it is really needed, if it ever is.&lt;br /&gt;
&lt;br /&gt;
=== Properties ===&lt;br /&gt;
&lt;br /&gt;
The following is a list of properties that the developer has to pass to the event upon creation, or ones that can be automatically generated where possible and cost free. Some of these properties are not mandatory.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Property name&lt;br /&gt;
! Title&lt;br /&gt;
! Type&lt;br /&gt;
! Required&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;eventname&#039;&#039;&lt;br /&gt;
| Event name&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Automatically computed by copying class name&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;component&#039;&#039;&lt;br /&gt;
| Component&lt;br /&gt;
| &#039;&#039;static, automatic from top namespace&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Component declaring the event, automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;action&#039;&#039;&lt;br /&gt;
| Action&lt;br /&gt;
| &#039;&#039;static, automatic from last word in class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;target&#039;&#039;&lt;br /&gt;
| target of action&lt;br /&gt;
| &#039;&#039;static, automatic from class name&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| Target on which the action is taken, can be automatically computed from class name.&lt;br /&gt;
|-&lt;br /&gt;
| objecttable&lt;br /&gt;
| Database table name&lt;br /&gt;
| static&lt;br /&gt;
| optional (Must be set if objetid present)&lt;br /&gt;
| Database table name which represents the event object to the best. Never use a relationship table here.&lt;br /&gt;
|-&lt;br /&gt;
| objectid&lt;br /&gt;
| Object ID&lt;br /&gt;
| variable&lt;br /&gt;
| Optional (Must be set if objettable present)&lt;br /&gt;
| Id of the object record from objecttable.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;crud&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Transaction type&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| One of [crud] letters. Statically declared in the event class method init().&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; / &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
| Level&lt;br /&gt;
| &#039;&#039;static&#039;&#039;&lt;br /&gt;
| optional&lt;br /&gt;
| Level of educational value of the event. Statically declared in the event class method init(). Changed from &#039;&#039;&#039;&#039;&#039;level&#039;&#039;&#039;&#039;&#039; to &#039;&#039;&#039;&#039;&#039;edulevel&#039;&#039;&#039;&#039;&#039; in Moodle 2.7 (See below for more details)&lt;br /&gt;
|-&lt;br /&gt;
| contextid&lt;br /&gt;
| Context ID&lt;br /&gt;
| mandatory&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| contextlevel&lt;br /&gt;
| Context level&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| This tells you if it was a course, activity, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| contextinstanceid&lt;br /&gt;
| Context instanceid&lt;br /&gt;
| automatic from context&lt;br /&gt;
| -&lt;br /&gt;
| Based on context level this may be course id , course module id, course category, etc.&lt;br /&gt;
|-&lt;br /&gt;
| userid&lt;br /&gt;
| User ID&lt;br /&gt;
| defaults to current user&lt;br /&gt;
| -&lt;br /&gt;
| User ID, or 0 when not logged in, or -1 when other (System, CLI, Cron, ...)&lt;br /&gt;
|-&lt;br /&gt;
| courseid&lt;br /&gt;
| Affected course&lt;br /&gt;
| defaults to course context from context&lt;br /&gt;
| -&lt;br /&gt;
| This is used only for contexts at and bellow course level - this can be used to filter events by course (includes all course activities)&lt;br /&gt;
|-&lt;br /&gt;
| relateduserid&lt;br /&gt;
| Affected user&lt;br /&gt;
| variable&lt;br /&gt;
| optional&lt;br /&gt;
| Is this action related to some user? This could be used for some personal timeline view.&lt;br /&gt;
|-&lt;br /&gt;
| anonymous&lt;br /&gt;
| Anonymous action&lt;br /&gt;
| variable&lt;br /&gt;
| optional (Defaults to 0)&lt;br /&gt;
| Is this action anonymous? Reports should ignore events with anonymous set to 1.&lt;br /&gt;
|-&lt;br /&gt;
| other&lt;br /&gt;
| All other data&lt;br /&gt;
| variable array&lt;br /&gt;
| optional&lt;br /&gt;
| Any other fields needed for event description - scalars or arrays, must be serialisable using json_encode()&lt;br /&gt;
|-&lt;br /&gt;
| timecreated&lt;br /&gt;
| Time of the event&lt;br /&gt;
| automatic&lt;br /&gt;
| -&lt;br /&gt;
| Time when the event was triggered.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* static: same for all event instances of this class&lt;br /&gt;
* variable: might not be same for all instances of this event class&lt;br /&gt;
* mandatory: required in order to trigger the event&lt;br /&gt;
* optional: not necessarily required to trigger the event&lt;br /&gt;
&lt;br /&gt;
==== Level property ====&lt;br /&gt;
&lt;br /&gt;
The edulevel property helps define the educational value of the event. It is intentional that the list is limited to only 3 different constants as having too many options would make it harder for developers to pick the right one(s). We also have to keep in mind that this is not supposed to answer all the questions about a particular event, other event properties like the courseid, the context, the component name can be used with the level to get more granular reports.&lt;br /&gt;
&lt;br /&gt;
Remember that this is event based. If the user that has triggered the event is not really &amp;quot;participating&amp;quot; because he is an admin, or a manager, then it is the job of the report to filter those. The event itself has a static educational level.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Teaching&#039;&#039;&#039; (LEVEL_TEACHING: 1)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by someone (typically a teacher) and has a teaching value (anything that is effecting the learning experience/environment of the students). This should not be combined with &amp;quot;Participating&amp;quot; events.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A teacher grading a student&lt;br /&gt;
* A teacher modifying the course settings&lt;br /&gt;
* A teacher adding a new section to the course page&lt;br /&gt;
* A teacher modifying a module settings&lt;br /&gt;
* A teacher adding a page to course&lt;br /&gt;
* A teacher leaving a feedback&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A teacher posting in a forum (it might affect the learning experience, but not necessarily, so the teacher is just participating)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Participating&#039;&#039;&#039; (LEVEL_PARTICIPATING: 2)&lt;br /&gt;
&lt;br /&gt;
Any event/action that is performed by a user, that is related (or could be related) to his learning experience.&lt;br /&gt;
&lt;br /&gt;
Valid events:&lt;br /&gt;
&lt;br /&gt;
* A user posting to a forum&lt;br /&gt;
* A user submitting an assignment&lt;br /&gt;
* A user blogging&lt;br /&gt;
* A user reading someone&#039;s blog&lt;br /&gt;
* A user posting a comment&lt;br /&gt;
* A user chatting on a chat activity&lt;br /&gt;
* A user viewing the course page&lt;br /&gt;
* A user deletes a blog post&lt;br /&gt;
&lt;br /&gt;
INVALID events:&lt;br /&gt;
&lt;br /&gt;
* A user updating his profile&lt;br /&gt;
* A user visiting someone&#039;s profile&lt;br /&gt;
* A user viewing his /my/ page&lt;br /&gt;
* A user sending a message to another one&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Other&#039;&#039;&#039; (LEVEL_OTHER: 0)&lt;br /&gt;
&lt;br /&gt;
Any other action, whether they are related to the site administration, or are specific to user. They do not have any educational value.&lt;br /&gt;
&lt;br /&gt;
=== Methods ===&lt;br /&gt;
&lt;br /&gt;
The computation of this data is not required by default, but can be accessed by any event observer if need be.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Method&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| get_name()&lt;br /&gt;
| Returns localised name of the event, it is the same for all instances.&lt;br /&gt;
|-&lt;br /&gt;
| get_description()&lt;br /&gt;
| Returns non-localised description of one particular event. There are plans to make this localised in future.&lt;br /&gt;
&lt;br /&gt;
It is recommended that the string begins with identifying the user who triggered the event by providing the user id in quotations. This applies to other variables used in the description as well. If an activity is also mentioned then the course module id should be used, not the id from the activity table. For example &amp;quot;The user with the id &#039;$this-&amp;gt;userid&#039; updated the activity &#039;youractivity&#039; with the course module id &#039;$this-&amp;gt;contextinstanceid&#039;.&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| can_view($user)&lt;br /&gt;
| This method is deprecated, please do not use this.&lt;br /&gt;
|-&lt;br /&gt;
| get_url()&lt;br /&gt;
| Returns Moodle URL where the event can be observed afterwards. Can be null, if no valid location is present.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventname()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_eventdata()&lt;br /&gt;
| Information necessary for event backward compatibility.&lt;br /&gt;
|-&lt;br /&gt;
| get_legacy_logdata()&lt;br /&gt;
| Information necessary for logging backward compatibility.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Record caching===&lt;br /&gt;
&lt;br /&gt;
The standard event data may not contain all the information observers need. The built-in record snapshot support in events allows developers to attach more auxiliary information when triggering events, it may be for example course record, some record that was just deleted, etc. &lt;br /&gt;
* Snapshots are expected to be an exact snapshot of the database table at the instance when the event was triggered.&lt;br /&gt;
* Snapshot can be set and requested for any table. If not cached, it defaults to direct $DB-&amp;gt;get_record calls.&lt;br /&gt;
* Please be aware that the snapshots are not stored in the event, and cannot be restored.&lt;br /&gt;
* Snapshot are supposed to be used only by observers. They should never be used by reports or by the event itself.&lt;br /&gt;
* When using a snapshot in an observer, please make sure you are taking proper care of handling exceptions as the record you are requesting could have been deleted in the time, in between your observer is notified about the event and the trigger.&lt;br /&gt;
* We recommend all delete event must add snapshot of the deleted record.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_assigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
    $event = \core\event\role_unassigned::create(&lt;br /&gt;
        array(&#039;context&#039;=&amp;gt;$context, &#039;objectid&#039;=&amp;gt;$ra-&amp;gt;roleid, &#039;relateduserid&#039;=&amp;gt;$ra-&amp;gt;userid,&lt;br /&gt;
            &#039;other&#039;=&amp;gt;array(&#039;id&#039;=&amp;gt;$ra-&amp;gt;id, &#039;component&#039;=&amp;gt;$ra-&amp;gt;component, &#039;itemid&#039;=&amp;gt;$ra-&amp;gt;itemid)));&lt;br /&gt;
    $event-&amp;gt;add_record_snapshot(&#039;role_assignments&#039;, $ra);&lt;br /&gt;
    $event-&amp;gt;trigger();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The related methods are:&lt;br /&gt;
* public function add_record_snapshot($tablename, $record)&lt;br /&gt;
* public function get_record_snapshot($tablename, $id)&lt;br /&gt;
&lt;br /&gt;
== Events naming convention ==&lt;br /&gt;
&lt;br /&gt;
Clear event names help developers when reading what events are triggered, and defining the events properties when defining the event class.&lt;br /&gt;
&lt;br /&gt;
 Decision: \&amp;lt;component&amp;gt;\event\&amp;lt;some_object&amp;gt;_&amp;lt;verb&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Existing events ===&lt;br /&gt;
&lt;br /&gt;
List of existing events in Moodle code base, along with their 2.5 couterparts.&lt;br /&gt;
&lt;br /&gt;
This list is out of date. For a full list of events check out the [https://docs.moodle.org/en/Event_list_report Event list report] which is located in &amp;quot;Site administration &amp;gt; Reports &amp;gt; Event list&amp;quot; of your Moodle installation (2.7+).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Fully qualified event name&lt;br /&gt;
! 2.5 name&lt;br /&gt;
! Component&lt;br /&gt;
! Object&lt;br /&gt;
! Action (Verb)&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_file_uploaded&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| To be deprecated MDL-35197&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_file\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_file&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;assignsubmission_onlinetext\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| assignsubmission_onlinetext&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;block_comments\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| block_comments&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_exportimscp\event\book_exported&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_exportimscp&lt;br /&gt;
| book&lt;br /&gt;
| exported&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\book_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| book&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;booktool_print\event\chapter_printed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| booktool_print&lt;br /&gt;
| chapter&lt;br /&gt;
| printed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\base&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| base&lt;br /&gt;
| -&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_association_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_association&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entries_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| blog_entries&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_created&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_added&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_deleted&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_deleted&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\blog_entry_updated&#039;&#039;&#039;&lt;br /&gt;
| blog_entry_edited&lt;br /&gt;
| core&lt;br /&gt;
| blog_entry&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_created&#039;&#039;&#039;&lt;br /&gt;
| cohort_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_deleted&#039;&#039;&#039;&lt;br /&gt;
| cohort_deleted&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_added&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_added&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_member_removed&#039;&#039;&#039;&lt;br /&gt;
| cohort_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| cohort_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\cohort_updated&#039;&#039;&#039;&lt;br /&gt;
| cohort_updated&lt;br /&gt;
| core&lt;br /&gt;
| cohort&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_category_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_category_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_category&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completed&#039;&#039;&#039;&lt;br /&gt;
| course_completed&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| completed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_content_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_content_removed&lt;br /&gt;
| core&lt;br /&gt;
| course_content&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_created&#039;&#039;&#039;&lt;br /&gt;
| course_created&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_deleted&#039;&#039;&#039;&lt;br /&gt;
| course_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_completion_updated&#039;&#039;&#039;&lt;br /&gt;
| activity_completion_changed&lt;br /&gt;
| core&lt;br /&gt;
| course_module_completion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_created&#039;&#039;&#039;&lt;br /&gt;
| mod_created&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_deleted&#039;&#039;&#039;&lt;br /&gt;
| mod_deleted&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module_instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_updated&#039;&#039;&#039;&lt;br /&gt;
| mod_updated&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_reset_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_reset&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_restored&#039;&#039;&#039;&lt;br /&gt;
| course_restored&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_section_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| course_section&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\course_updated&#039;&#039;&#039;&lt;br /&gt;
| course_updated&lt;br /&gt;
| core&lt;br /&gt;
| course&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\email_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| email&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_created&#039;&#039;&#039;&lt;br /&gt;
| groups_group_created&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_group_deleted&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_added&#039;&#039;&#039;&lt;br /&gt;
| groups_member_added&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_member_removed&#039;&#039;&#039;&lt;br /&gt;
| groups_member_removed&lt;br /&gt;
| core&lt;br /&gt;
| group_member&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\group_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_group_updated&lt;br /&gt;
| core&lt;br /&gt;
| group&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_created&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_created&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_deleted&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_deleted&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\grouping_updated&#039;&#039;&#039;&lt;br /&gt;
| groups_grouping_updated&lt;br /&gt;
| core&lt;br /&gt;
| grouping&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\manager&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| manager&lt;br /&gt;
| anager&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\mnet_access_control_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| mnet_access_control&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\note_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| note&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\notes_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| notes&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_assign_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_assign&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_override_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_override&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_allow_switch_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_allow_switch&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_assigned&#039;&#039;&#039;&lt;br /&gt;
| role_assigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| assigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_capabilities_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role_capabilities&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\role_unassigned&#039;&#039;&#039;&lt;br /&gt;
| role_unassigned&lt;br /&gt;
| core&lt;br /&gt;
| role&lt;br /&gt;
| unassigned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_created&#039;&#039;&#039;&lt;br /&gt;
| user_created&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_deleted&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_created&#039;&#039;&#039;&lt;br /&gt;
| user_enrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_deleted&#039;&#039;&#039;&lt;br /&gt;
| user_unenrolled&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_enrolment_updated&#039;&#039;&#039;&lt;br /&gt;
| user_enrol_modified&lt;br /&gt;
| core&lt;br /&gt;
| user_enrolment&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedin&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedin&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedinas&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedinas&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_loggedout&#039;&#039;&#039;&lt;br /&gt;
| user_logout&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| loggedout&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_profile_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| user_profile&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\user_updated&#039;&#039;&#039;&lt;br /&gt;
| user_updated&lt;br /&gt;
| core&lt;br /&gt;
| user&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_function_called&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_function&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_login_failed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_login&lt;br /&gt;
| failed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_service_user_removed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_service_user&lt;br /&gt;
| removed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;core\event\webservice_token_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| core&lt;br /&gt;
| webservice_token&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;logstore_legacy\event\legacy_logged&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| logstore_legacy&lt;br /&gt;
| legacy&lt;br /&gt;
| logged&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\all_submissions_downloaded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| all_submissions&lt;br /&gt;
| downloaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\assessable_submitted&#039;&#039;&#039;&lt;br /&gt;
| assessable_submitted&lt;br /&gt;
| mod_assign&lt;br /&gt;
| assessable&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\extension_granted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| extension&lt;br /&gt;
| granted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\identities_revealed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| identities&lt;br /&gt;
| revealed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\marker_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| marker&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\statement_accepted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| statement&lt;br /&gt;
| accepted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_duplicated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| duplicated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_graded&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| graded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_locked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| locked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_status_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission_status&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_unlocked&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| unlocked&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| Abstract class &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_assign\event\workflow_state_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_assign&lt;br /&gt;
| workflow_state&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\chapter_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| chapter&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_book\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_book&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\message_sent&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| message&lt;br /&gt;
| sent&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_chat\event\sessions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_chat&lt;br /&gt;
| sessions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\answer_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| answer&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_choice\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_choice&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\field_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| field&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\record_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| record&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_data\event\template_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_data&lt;br /&gt;
| template&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_feedback\event\response_submitted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_feedback&lt;br /&gt;
| response&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_folder\event\folder_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_folder&lt;br /&gt;
| folder&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_forum&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\course_searched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| course&lt;br /&gt;
| searched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_moved&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| moved&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\discussion_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| discussion&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\forum_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| forum&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\post_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| post&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_disabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| disabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\readtracking_enabled&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| readtracking&lt;br /&gt;
| enabled&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscribers_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscribers&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\subscription_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| subscription&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_forum\event\userreport_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_forum&lt;br /&gt;
| userreport&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_glossary\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_glossary&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\essay_attempt_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| essay_attempt&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscore_added&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscore&lt;br /&gt;
| added&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\highscores_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| highscores&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_ended&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| ended&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lesson\event\lesson_started&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lesson&lt;br /&gt;
| lesson&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_lti&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_lti\event\unknown_service_api_called&#039;&#039;&#039;&lt;br /&gt;
| lti_unknown_service_api_call&lt;br /&gt;
| mod_lti&lt;br /&gt;
| unknown_service_api&lt;br /&gt;
| called&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_page\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_page&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_abandoned&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_abandoned&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| abandoned&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_becameoverdue&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_overdue&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| becameoverdue&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_started&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_started&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| started&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_quiz\event\attempt_submitted&#039;&#039;&#039;&lt;br /&gt;
| quiz_attempt_submitted&lt;br /&gt;
| mod_quiz&lt;br /&gt;
| attempt&lt;br /&gt;
| submitted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_resource\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_resource&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\attempt_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| attempt&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\interactions_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| interactions&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\sco_launched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| sco&lt;br /&gt;
| launched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\tracks_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| tracks&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_scorm\event\user_report_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_scorm&lt;br /&gt;
| user_report&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_url\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_url&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comment_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comment&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\comments_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| comments&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_instance_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module_instance_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_diff_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_diff&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_history_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_history&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_locks_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_locks&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_map_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_map&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_deleted&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| deleted&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_restored&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| restored&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_version_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page_version&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_wiki\event\page_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_wiki&lt;br /&gt;
| page&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessable_uploaded&#039;&#039;&#039;&lt;br /&gt;
| assessable_content_uploaded&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessable&lt;br /&gt;
| uploaded&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| evaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_evaluations_reset&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment_evaluations&lt;br /&gt;
| reset&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\assessment_reevaluated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| assessment&lt;br /&gt;
| reevaluated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\course_module_viewed&#039;&#039;&#039;&lt;br /&gt;
| workshop_viewed&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| course_module&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\instances_list_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| instances_list&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\phase_switched&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| phase&lt;br /&gt;
| switched&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_assessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| assessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_created&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| created&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_reassessed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| reassessed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_updated&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| updated&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;mod_workshop\event\submission_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| mod_workshop&lt;br /&gt;
| submission&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_log\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_log&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_loglive\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_loglive&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_outline\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_outline&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_participation\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_participation&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;report_stats\event\content_viewed&#039;&#039;&#039;&lt;br /&gt;
| -&lt;br /&gt;
| report_stats&lt;br /&gt;
| content&lt;br /&gt;
| viewed&lt;br /&gt;
| &lt;br /&gt;
|- &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Verb list ===&lt;br /&gt;
All events must use a verb from this list. New verbs can be added to this list if required, but additions should only be made if there is no valid alternative (we want to keep this list as small as possible).&lt;br /&gt;
{| class=&amp;quot;nicetable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
!verb&lt;br /&gt;
!Explanation&lt;br /&gt;
!Source&lt;br /&gt;
|-&lt;br /&gt;
|abandoned&lt;br /&gt;
|When a attempt is abandoned by user (Quiz attempt)&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|accepted&lt;br /&gt;
|Example: Accepting a statement when submitting an assignment.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|added&lt;br /&gt;
|	Used to represent &amp;quot;something that already exists is now part of/bound to another entity&amp;quot;. Examples: &amp;quot;Admin added role to user X&amp;quot;, &amp;quot;Admin added user X to group A&amp;quot;. Wrong example: &amp;quot;User added course in category&amp;quot; because it is a &#039;move&#039; action, except if a course can be part of multiple categories. The good examples work because: A user can have multiple roles, a user can be in multiple groups.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|answered&lt;br /&gt;
| Indicates the actor responded to a Question&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|assessed&lt;br /&gt;
| Some submitted material has been assessed&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|assigned&lt;br /&gt;
| Assign some privilege or role to user.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|attempted&lt;br /&gt;
| Trying to do an activity. Example: attempting a Math class.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|awarded&lt;br /&gt;
| ex:-teacher awarded student a badge.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|backedup&lt;br /&gt;
| When a backup has been performed.&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|becomeoverdue&lt;br /&gt;
| When an activity is overdue Example: Quiz attempt is overdue&lt;br /&gt;
|Moodle	&lt;br /&gt;
|-&lt;br /&gt;
|called&lt;br /&gt;
| When a call to something is made like an API @see unknown_service_api_called.php&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|commented&lt;br /&gt;
|Offered an opinion or written experience of the activity. Can be used with the learner as the actor or a system as an actor. Comments can be sent from either party with the idea that the other will read and react to the content.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|completed&lt;br /&gt;
|To experience the activity in its entirety. Used to affirm the completion of content. This can be simply experiencing all the content, be tied to objectives or interactions, or determined in any other way. Any content that has been initialized, but not yet completed, should be considered incomplete. There is no verb to &#039;incomplete&#039; an activity, one would void the statement which completes the activity.&amp;quot;&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|created&lt;br /&gt;
|Used to represent &amp;quot;something new has been created&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|deleted&lt;br /&gt;
|Used to indicate the object in context was deleted.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|disabled&lt;br /&gt;
|When an activity is disabled. Example: forum read tracking disabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|downloaded&lt;br /&gt;
|When a user download file from user. Example submission/report downloaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|duplicated&lt;br /&gt;
|For something that has been copied.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|enabled&lt;br /&gt;
|When some setting is enabled. Example: forum read tracking enabled.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|ended&lt;br /&gt;
|When a process ends. Example: Lesson ended or course reset ended.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|evaluated&lt;br /&gt;
|Material has been evaluated.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|exported&lt;br /&gt;
|When a report is exported in certain format.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|failed&lt;br /&gt;
|Learner did not perform the activity to a level of pre-determined satisfaction. Used to affirm the lack of success a learner experienced within the learning content in relation to a threshold. If the user performed below the minimum to the level of this threshold, the content is &#039;failed&#039;. The opposite of &#039;passed&#039;. This is also used in case when message sending is failed.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|graded&lt;br /&gt;
|Used to represent an activity was graded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|granted&lt;br /&gt;
|User is granted some extension or capability. Example: extension granted for submission.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|imported&lt;br /&gt;
|The act of moving an object into another location or system.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|launched&lt;br /&gt;
|When an external object is launched. Try consider started if there is related stopped event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|When an activity is locked. Should have a related unlocked event.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedin/loggedout&lt;br /&gt;
|	For login and logout.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|loggedinas&lt;br /&gt;
|	 If user is logged in as different user. This is used by only one event (user_loggedinas). Adding this verb makes event name more clear, then using loggedin verb.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|locked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|moved&lt;br /&gt;
|	Used to indicate the object in context was moved.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|passed&lt;br /&gt;
|Used to affirm the success a learner experienced within the learning content in relation to a threshold. If the user performed at a minimum to the level of this threshold, the content is &#039;passed&#039;. The opposite of &#039;failed&#039;.&lt;br /&gt;
|Tincan&lt;br /&gt;
|-&lt;br /&gt;
|printed&lt;br /&gt;
|Something is printed.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reassessed&lt;br /&gt;
|Submitted material has been assessed again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reevaluated&lt;br /&gt;
|Material has been evaluated again.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|removed&lt;br /&gt;
|By opposition to &amp;quot;Added&amp;quot;. This does not mean that the object has been deleted, but removed from the entity, or not bound to it any more.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|reset&lt;br /&gt;
|Sets one or more properties back to the default value.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|restored&lt;br /&gt;
|When restoring a backup. Rolling back to a previous state.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|revealed&lt;br /&gt;
|Some identity is revealed. Example: Identities revealed after blind marking.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|searched&lt;br /&gt;
|Something is searched. Example: searched in course.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|sent&lt;br /&gt;
|Message sent.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|started&lt;br /&gt;
|Some activity started&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|submitted&lt;br /&gt;
|This is very close to &amp;quot;Attempted&amp;quot;. Depends on context which one should be used. For example:- &amp;quot;Admin submitted a form. Student attempted a quiz.&amp;quot;  is correct, however some cases might not be as clear as the previous example. We can say both &amp;quot;Student submitted an assignment&amp;quot; or &amp;quot;student attempted an assignment&amp;quot;. We need to make the difference clear.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|suspended&lt;br /&gt;
| Suspend something. (example a user)&lt;br /&gt;
| Tincan (However the context is different)&lt;br /&gt;
|-&lt;br /&gt;
|switched&lt;br /&gt;
|Something has been switched. For example:- The workshop phase has been switched to assessment&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unassigned&lt;br /&gt;
|As opposed to assigned. When some role is unassigned.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|unlocked&lt;br /&gt;
|&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|upgraded&lt;br /&gt;
|Something was upgraded, some module probably&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|updated&lt;br /&gt;
|Used to indicate the object in context was updated. Simple example is &amp;quot;Admin updated course xyz&amp;quot;.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|uploaded&lt;br /&gt;
|When an assignment is uploaded.&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|viewed&lt;br /&gt;
|Something has been viewed. For example:- &amp;quot;Student viewed chapter 1 of book 1.&amp;quot;&lt;br /&gt;
|Moodle&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Rules ===&lt;br /&gt;
&lt;br /&gt;
==== Use singular ====&lt;br /&gt;
&lt;br /&gt;
Plurals must be used on objects when it&#039;s a &#039;&#039;One to Many&#039;&#039; relationship. Ex: bulk import, mass deletion, ... In any other case, use the singular.&lt;br /&gt;
&lt;br /&gt;
==== Ends with a verb ====&lt;br /&gt;
&lt;br /&gt;
The last word (after the last underscore) must be a verb.&lt;br /&gt;
&lt;br /&gt;
==== Consistency among child events ====&lt;br /&gt;
&lt;br /&gt;
If an event is extending a parent class, it should have the same exact name as the parent event.&lt;br /&gt;
&lt;br /&gt;
=== Deprecated events ===&lt;br /&gt;
Following are the events that were supported in 2.5, but deprecated in 2.6 or later&lt;br /&gt;
&lt;br /&gt;
groups_groupings_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groupings_groups_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_groups_deleted (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
groups_members_removed (see MDL-41312)&lt;br /&gt;
&lt;br /&gt;
== Shared events ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Not supported at this stage.&lt;br /&gt;
&lt;br /&gt;
In Moodle 2.5 we have a good example of a shared event: &#039;assessable_content_uploaded&#039; which is triggered in &#039;&#039;forum&#039;&#039;, &#039;assignment&#039;&#039; and &#039;&#039;workshop&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The problem with shared events is that we cannot easily track what component triggered them. Of course we could add a new property to the event to keep track of that, but we would soon need more information and more properties. Also, in the case of a logger, the event received would be unique, where in fact it should be considered different depending on the component firing it.&lt;br /&gt;
&lt;br /&gt;
In our first implementation, we will create one specific event per module. This flexibility does not prevent any observer from capturing them, but still makes sure that the consistency and specificity of each event is maintained.&lt;br /&gt;
&lt;br /&gt;
It could happen that some events are defined in core and shared, but this should not really happen as low-level APIs should trigger the event, and a module should call that low API instead of doing the job itself.&lt;br /&gt;
&lt;br /&gt;
== One to many ==&lt;br /&gt;
&lt;br /&gt;
 Decision: Each event should have a one to one relationship. We can reconsider this at a later stage, if the performance hit is extremely high.&lt;br /&gt;
&lt;br /&gt;
In 2.5, some events are triggered when an action happens on multiple objects. We have to decide whether we want to keep supporting &#039;&#039;One to Many&#039;&#039; events or not.&lt;br /&gt;
&lt;br /&gt;
Keeping a list of all changes for multiple actions may be problematic because you would have to keep them all in memory until all things are processed. This might also result in the order of events being incorrect. The only correct solution seems to be to trigger each item individually and then many things at the end. Performance needs to be improved elsewhere...&lt;br /&gt;
&lt;br /&gt;
=== Accuracy ===&lt;br /&gt;
&lt;br /&gt;
When uploading a bunch of users using the CSV upload feature, if only one event is triggered, it means that the observers of &#039;&#039;user_created&#039;&#039; won&#039;t be triggered. And so some functionality can be lost as, as a plugin developer, I expect this &#039;&#039;user_created&#039;&#039; to be triggered regardless of the way they have been uploaded. Of course, the developer could observe the event &#039;&#039;bulk_user_imported&#039;&#039;, but that means that he could miss some relevant observers.&lt;br /&gt;
&lt;br /&gt;
This applies to existing events.&lt;br /&gt;
&lt;br /&gt;
=== Performance ===&lt;br /&gt;
&lt;br /&gt;
Triggering one event is cheaper then repeating the same events x number of times...&lt;br /&gt;
&lt;br /&gt;
=== Information tracking ===&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;bulk&#039;&#039; event, might not be verbose enough to allow for proper logging afterwards. Though this is the responsibility of the logger, we probably want to make it easy to store relevant information.&lt;br /&gt;
&lt;br /&gt;
=== Double event ===&lt;br /&gt;
&lt;br /&gt;
In the case of a bulk user import, if we were to trigger an event per user created, we probably want to trigger one event &#039;user_bulk_upload_started&#039; when the action starts.&lt;br /&gt;
&lt;br /&gt;
== Unit Testing ==&lt;br /&gt;
&lt;br /&gt;
With unit testing for this system we want to assert the following:&lt;br /&gt;
&lt;br /&gt;
* That event strict validation and custom validation works.&lt;br /&gt;
* Missing event data is auto filled with accurate data.&lt;br /&gt;
* Typos in properties passed to ::create() are captured (if we decide to validate).&lt;br /&gt;
* The legacy methods return the expected values (use assertEventLegacyData() and assertEventLegacyData())&lt;br /&gt;
* The class properties are correctly overridden (crud, level, action, object, ...).&lt;br /&gt;
* The properties automatically generated (component, name, ...) are correct.&lt;br /&gt;
* Events are dispatched to the corresponding observers.&lt;br /&gt;
* Events are dispatched to the corresponding legacy handlers.&lt;br /&gt;
* Events are dispatched to the * observers.&lt;br /&gt;
* Events perform an add_to_log() if it has legacy log data.&lt;br /&gt;
* &#039;Events restore&#039; restored the whole event data, and does not miss any information.&lt;br /&gt;
* &#039;Events restore&#039; does not generate any extra information.&lt;br /&gt;
* Event methods should check context object or avoid using it, as context might not be valid at time of event restore (use assertEventContextNotUsed())&lt;br /&gt;
&lt;br /&gt;
= PHP docs =&lt;br /&gt;
* All events php docs must include @since parameter, indicating when the event was first included in standard Moodle distribution.&lt;br /&gt;
* All events must declare the $other properties using mark down in the php docs. This later might be converted to a self documenting structure. (See MDL-45108)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * blog_association_created&lt;br /&gt;
 *&lt;br /&gt;
 * Class for event to be triggered when a new blog entry is associated with a context.&lt;br /&gt;
 *&lt;br /&gt;
 * @property-read array $other {&lt;br /&gt;
 *      Extra information about event.&lt;br /&gt;
 *&lt;br /&gt;
 *      - string associatetype: type of blog association, course/coursemodule.&lt;br /&gt;
 *      - int blogid: id of blog.&lt;br /&gt;
 *      - int associateid: id of associate.&lt;br /&gt;
 *      - string subject: blog subject.&lt;br /&gt;
 * }&lt;br /&gt;
 *&lt;br /&gt;
 * @package    core&lt;br /&gt;
 * @since      Moodle 2.7&lt;br /&gt;
 * @copyright  2013 onwards Ankit Agarwal&lt;br /&gt;
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Example events =&lt;br /&gt;
&lt;br /&gt;
== Assignment ==&lt;br /&gt;
&lt;br /&gt;
Assumption: Course contains groups with students in each group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1.&#039;&#039;&#039; Teacher creates an assignment with group mode set to &#039;Separate groups&#039; and Feedback type set to comments and files.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has created assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;2.&#039;&#039;&#039; A student views the assignment.&lt;br /&gt;
*Event: User &#039;Student&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;3.&#039;&#039;&#039; A member from one of the groups submits an assignment&lt;br /&gt;
*Event: User &#039;Student&#039; has added a submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;4.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to the teacher and all students in that group.&lt;br /&gt;
&#039;&#039;&#039;5.&#039;&#039;&#039; Teacher views the assignment.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;6.&#039;&#039;&#039; Teacher clicks on &#039;View/grade all submissions&#039;&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the assignment &#039;B&#039; grade area in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;7.&#039;&#039;&#039; Teacher clicks to grade the student&#039;s submission.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;8.&#039;&#039;&#039; Teacher marks the assignment with the setting &#039;Apply grades and feedback to entire group&#039; set to &#039;Yes&#039; leaving a comment and a file.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a file to the course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been marked. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;9.&#039;&#039;&#039; User &#039;Adrian&#039; views the feedback.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;10.&#039;&#039;&#039; User &#039;Adrian&#039; opens the feedback file.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has viewed the file &#039;A&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;11.&#039;&#039;&#039; User &#039;Adrian&#039; adds some changes to the assignment insulting the teachers marking and updates it.&lt;br /&gt;
*Event: User &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039; for group &#039;C&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Teacher&#039; notifying them that user &#039;Adrian&#039; has updated the submission for assignment &#039;B&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Student&#039; notifying them their submission for assignment &#039;B&#039; has been updated. - This is done for all users in the group.&lt;br /&gt;
&#039;&#039;&#039;12.&#039;&#039;&#039; The teacher clicks directly on the link in the email to be taken to the grading page.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has viewed the submission for user &#039;student&#039; for assignment &#039;B&#039; in course &#039;C101&#039;.&lt;br /&gt;
&#039;&#039;&#039;13.&#039;&#039;&#039; The teacher is upset due to the harsh comments and decides to mark Adrian down, but not the rest of the group by setting &#039;Apply grades and feedback to entire group&#039; set to &#039;No&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has marked assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has left a comment for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: User &#039;Teacher&#039; has uploaded a feedback file for assignment &#039;B&#039; for user &#039;Adrian&#039; in course &#039;C101&#039;.&lt;br /&gt;
*Event: Email sent to user &#039;Adrian&#039; notifying them their submission for assignment &#039;B&#039; has been marked.&lt;br /&gt;
&lt;br /&gt;
= FAQs =&lt;br /&gt;
&lt;br /&gt;
; Why not create events in core subsystems? : Because we could not see all core events in one place, it would create problems when naming event classes and finally subsystems are incomplete, we would have to add more now because we could not move the events in the future.&lt;br /&gt;
&lt;br /&gt;
= Possible future work = &lt;br /&gt;
* MDL-45108 &amp;quot;Other&amp;quot; parameters should be defined in a method similar to webservices&lt;br /&gt;
* MDL-45217 Create traits for refactoring event triggers&lt;br /&gt;
* MDL-42897 Converting completion to use events&lt;br /&gt;
* MDL-42898 Develop a timeline page/block&lt;br /&gt;
&lt;br /&gt;
= See Also =&lt;br /&gt;
[[Logging 2]]  &lt;br /&gt;
&lt;br /&gt;
[[Tin Can]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=YUI/Shifter&amp;diff=46297</id>
		<title>YUI/Shifter</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=YUI/Shifter&amp;diff=46297"/>
		<updated>2014-09-22T20:48:53Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* How do I load one of these modules from PHP code? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.5}}&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
{{Moodle 2.7}}&lt;br /&gt;
&lt;br /&gt;
== What is Shifter and what does it do? ==&lt;br /&gt;
&lt;br /&gt;
[http://yui.github.com/shifter Shifter] is a tool written by the YUI team to help &#039;&#039;build&#039;&#039; YUI modules.&lt;br /&gt;
It has been supported since Moodle 2.5 and we encourage its use.&lt;br /&gt;
&lt;br /&gt;
It is written in JavaScript itself, and written as a [http://nodejs.org Node.JS] module which can be installed from [https://npmjs.org/package/shifter NPM].&lt;br /&gt;
&lt;br /&gt;
Shifter takes your source JavaScript file(s), along with some meta-data, and wraps it all together into a built file. This file is known in YUI parlance as a &#039;&#039;&#039;module&#039;&#039;&#039;.&lt;br /&gt;
After building this file, Shifter then produces three versions:&lt;br /&gt;
* the file in its original form (DEBUG - &#039;-debug&#039; filename postfix);&lt;br /&gt;
* the DEBUG file with all debugging calls to Y.Log removed (RAW - no filename postfix); and&lt;br /&gt;
* the RAW file minified using [https://github.com/mishoo/UglifyJS UglifyJS] (&#039;-min&#039; filename postfix).&lt;br /&gt;
&lt;br /&gt;
The meta-data file includes information on the module name, and its dependencies on other modules.&lt;br /&gt;
&lt;br /&gt;
By separating out the actual JS code from its dependencies, we are able to take those dependencies and use them elsewhere in Moodle.&lt;br /&gt;
As an example, this dependency data can be used to inform the Loading system to reduce the number of HTTP requests with Combo Loading. This has a benefical effect upon performance.&lt;br /&gt;
&lt;br /&gt;
Another feature of Shifter is its ability to handle &#039;&#039;rollups&#039;&#039;. Rollups describe the inclusion of multiple YUI classes in the same module. This means that you can have different but related components all in the same module, but without having a single large and less-managable source file.&lt;br /&gt;
&lt;br /&gt;
=== Why do I need build my modules? ===&lt;br /&gt;
&lt;br /&gt;
Technically you don&#039;t, and you can continue to use the old data structure, but by doing so you can benefit from:&lt;br /&gt;
* reduced data sent over the wire due to minification - great for slower connections and mobile devices;&lt;br /&gt;
* reduced number of http queries - the separation of module meta-data means that it can be consumed and fed into the Loader allowing your module to use combo-loading;&lt;br /&gt;
* a slightly simplified JS syntax for your source files.&lt;br /&gt;
&lt;br /&gt;
== Installing Shifter ==&lt;br /&gt;
&lt;br /&gt;
Shifter is written in JavaScript and the [http://nodejs.org Node.JS] environment. You will need to install Node.JS first. This is usually fairly easy as there are pre-built binary packages for &#039;&#039;&#039;Windows and Mac OS&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
After installing Node.JS you then use the Node NPM tool to install Shifter:&lt;br /&gt;
   npm install shifter@0.4.6 -g&lt;br /&gt;
&lt;br /&gt;
Note: At present, the supported version of Shifter for use in Moodle is version &#039;&#039;0.4.6&#039;&#039;. You are not &#039;&#039;required&#039;&#039; to run a specific version of Shifter, but this is the version that Moodle YUI modules will be built with and you may find it beneficial to do so too.&lt;br /&gt;
&lt;br /&gt;
For &#039;&#039;&#039;Ubuntu&#039;&#039;&#039; run:&lt;br /&gt;
&lt;br /&gt;
   sudo apt-get install npm&lt;br /&gt;
   sudo apt-get install python-software-properties python g++ make&lt;br /&gt;
   sudo apt-get update&lt;br /&gt;
   sudo apt-get install nodejs&lt;br /&gt;
   sudo ln -s /usr/bin/nodejs /usr/local/bin/node&lt;br /&gt;
   sudo npm install shifter@0.4.6 -g&lt;br /&gt;
&lt;br /&gt;
If you are behind a proxy, you will need to read http://jjasonclark.com/how-to-setup-node-behind-web-proxy.&lt;br /&gt;
&lt;br /&gt;
== How do I write a YUI module which uses Shifter? ==&lt;br /&gt;
&lt;br /&gt;
Easy - it&#039;s mostly just a case of building the right directory structure.&lt;br /&gt;
&lt;br /&gt;
Assuming that you are creating a new YUI module in your block named fruit, and that your new YUI module will be called fruitbowl, we know the following:&lt;br /&gt;
{|&lt;br /&gt;
|Plugin type&lt;br /&gt;
|block&lt;br /&gt;
|-&lt;br /&gt;
|Plugin name&lt;br /&gt;
|fruit&lt;br /&gt;
|-&lt;br /&gt;
|Plugin frankenstyle name&lt;br /&gt;
|block_fruit&lt;br /&gt;
|-&lt;br /&gt;
|YUI Module name&lt;br /&gt;
|moodle-block_fruit-fruitbowl&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This means that your Moodle plugin directory is:&lt;br /&gt;
  /blocks/fruit&lt;br /&gt;
&lt;br /&gt;
And your &#039;&#039;fruitbowl&#039;&#039; YUI module source will therefore be in:&lt;br /&gt;
  /blocks/fruit/yui/src/fruitbowl&lt;br /&gt;
&lt;br /&gt;
The overall module directory structure looks like this:&lt;br /&gt;
&amp;lt;code bash&amp;gt;&lt;br /&gt;
yui/&lt;br /&gt;
|-- src&lt;br /&gt;
    |-- fruitbowl&lt;br /&gt;
        |-- build.json&lt;br /&gt;
        |-- js&lt;br /&gt;
        |   |-- fruitbowl.js&lt;br /&gt;
        |-- meta&lt;br /&gt;
            |-- fruitbowl.json&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== build.json ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;build.json&#039;&#039; file defines the eventual modules which will be built, and the source files that you&#039;ve written:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;name&amp;quot;: &amp;quot;moodle-block_fruit-fruitbowl&amp;quot;,&lt;br /&gt;
  &amp;quot;builds&amp;quot;: {&lt;br /&gt;
    &amp;quot;moodle-block_fruit-fruitbowl&amp;quot;: {&lt;br /&gt;
      &amp;quot;jsfiles&amp;quot;: [&lt;br /&gt;
        &amp;quot;fruitbowl.js&amp;quot;&lt;br /&gt;
      ]&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== meta/MODNAME.json ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;meta/MODNAME.json&#039;&#039; file describes the list of dependencies for each module:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
  &amp;quot;moodle-block_fruit-fruitbowl&amp;quot;: {&lt;br /&gt;
    &amp;quot;requires&amp;quot;: [&lt;br /&gt;
        &amp;quot;base&amp;quot;,&lt;br /&gt;
        &amp;quot;node&amp;quot;&lt;br /&gt;
    ]&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== js/MODNAME.js ===&lt;br /&gt;
&lt;br /&gt;
The files in the js directory are the contents of your YUI module. This should include setting it up in the &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; namespace. As an example of a very basic structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code javascript&amp;gt;&lt;br /&gt;
M.block_fruit = M.block_fruit || {};&lt;br /&gt;
M.block_fruit.fruitbowl = {&lt;br /&gt;
  init: function() {&lt;br /&gt;
    Y.one(&#039;#example&#039;).set(&#039;innerHTML&#039;, &#039;Example content&#039;);&lt;br /&gt;
  }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Can I put two modules in one directory tree? ===&lt;br /&gt;
&lt;br /&gt;
If you are still using Moodle 2.5, this does not work due to bug MDL-40478 (the non-default files cannot be loaded).&lt;br /&gt;
&lt;br /&gt;
If you are using Moodle 2.6+ this is possible. It may sometimes be sensible if the modules are not independent, e.g. if one module will only ever be used by the other one rather than directly called from PHP, or another module.&lt;br /&gt;
&lt;br /&gt;
If the modules are independent or might well be used separately from each other, then it is probably best to use a separate directory tree for each.&lt;br /&gt;
&lt;br /&gt;
See examples in mod/scorm/yui/src and lib/yui/src/notification.&lt;br /&gt;
&lt;br /&gt;
=== How do I load one of these modules from PHP code? ===&lt;br /&gt;
&lt;br /&gt;
You need to run Shifter so that it generates the compiled code. See below.&lt;br /&gt;
&lt;br /&gt;
Once you&#039;ve done that, you can use PHP code like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$PAGE-&amp;gt;requires-&amp;gt;yui_module(&#039;moodle-block_fruit-fruitbowl&#039;, &#039;M.block_fruit.fruitbowl.init&#039;, array());&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(The last empty array contains parameters for the init function, if required.)&lt;br /&gt;
&lt;br /&gt;
== How do I use shifter? ==&lt;br /&gt;
&lt;br /&gt;
So after writing out your structure, you now need to build it into a module. After installing Shifter, you have several options.&lt;br /&gt;
&lt;br /&gt;
=== During development ===&lt;br /&gt;
&lt;br /&gt;
A really nice way of running shifter during development is to have it detect changes to your files as you save them:&lt;br /&gt;
&lt;br /&gt;
  cd ~/git/moodle/blocks/fruit/yui/src&lt;br /&gt;
  shifter --watch&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;--watch&#039;&#039;&#039; option will watch for any changes to JS, JSON, CSS, or images within any module in the current directory and build that module when it detects changes.&lt;br /&gt;
&#039;&#039;Note: There can be a short delay of a few seconds while the changes are discovered and the file is built&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is great for development because you don&#039;t have to continously run shifter manually.&lt;br /&gt;
&lt;br /&gt;
=== All YUI modules for the Moodle plugin you&#039;re currently working on ===&lt;br /&gt;
&lt;br /&gt;
If you are working on several YUI modules at once, then you can have shifter build all of them at the same time:&lt;br /&gt;
&lt;br /&gt;
  cd ~/git/moodle/blocks/fruit/yui/src&lt;br /&gt;
  shifter --walk&lt;br /&gt;
&lt;br /&gt;
=== Just the module you&#039;re working on now ===&lt;br /&gt;
If you want to build just the module you&#039;re working on at the moment:&lt;br /&gt;
&lt;br /&gt;
  cd ~/git/moodle/blocks/fruit/yui/src&lt;br /&gt;
  shifter --walk fruitbowl&lt;br /&gt;
&lt;br /&gt;
Or:&lt;br /&gt;
&lt;br /&gt;
  cd ~/git/moodle/blocks/fruit/yui/src/fruitbowl&lt;br /&gt;
  shifter&lt;br /&gt;
&lt;br /&gt;
=== Across the whole of Moodle ===&lt;br /&gt;
If you want to build every YUI module in Moodle at once:&lt;br /&gt;
&lt;br /&gt;
  cd ~/git/moodle&lt;br /&gt;
  shifter --walk --recursive&lt;br /&gt;
&lt;br /&gt;
== Submitting my JavaScript back to Moodle core ==&lt;br /&gt;
&lt;br /&gt;
If you&#039;re working on some JavaScript for Moodle core, either in the form of a bug fix or a new feature, then you probably want to know what to do with your built module.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;We ask that you build your module and submit both the changes to tbe built module and the source directory.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In addition, the Continuous Integration server (Jenkins) will run &#039;&#039;shifter --walk --recursive&#039;&#039; on every run to ensure that all built files are up-to-date and correct.&lt;br /&gt;
&lt;br /&gt;
If there are several commits to the same YUI module within a single period of Moodle integration, then the built files will conflict. In this case the integration team will manually build the module and resolve the conflict. If you are aware that there may be multiple changes to the same file, please indicate this when submitting your change for Integration Review. If you are familiar with the changes, you may wish to consider building the issues upon one another too.&lt;br /&gt;
&lt;br /&gt;
== How do I convert my existing module? ==&lt;br /&gt;
&lt;br /&gt;
If you already have an existing moodle YUI module and want to convert it to the new Shifter format, then it&#039;s pretty easy on the whole:&lt;br /&gt;
&lt;br /&gt;
# create a new src/MODNAME directory;&lt;br /&gt;
# create js and meta directories within this;&lt;br /&gt;
# copy over your existing js file into the js directory;&lt;br /&gt;
# extract the meta-data;&lt;br /&gt;
# write your build.json;&lt;br /&gt;
# remove the YUI.add() wrapper from the top and bottom of your js file; and&lt;br /&gt;
# remove the old file.&lt;br /&gt;
&lt;br /&gt;
To create the complete directory structure and copy your existing code into the right directory (steps 1 - 3):&lt;br /&gt;
&lt;br /&gt;
  mkdir -p src/MODNAME/{js,meta}&lt;br /&gt;
  cp MODNAME/MODNAME.js src/MODNAME/js/&lt;br /&gt;
&lt;br /&gt;
Refer to the section above on the correct contents of the build.json and meta/MODNAME.json files.&lt;br /&gt;
&lt;br /&gt;
== Can I run my shifted module in older versions of Moodle 2 (before 2.5)? ==&lt;br /&gt;
&lt;br /&gt;
We are aware that many developers wish to reduce the overhead of maintaining a plugin for multiple versions of Moodle and that using Shifter will make this much harder. Unfortunately you can&#039;t use the shifted version of your module directly, but you can run them in parallel by copying the built file into the old directory structure.&lt;br /&gt;
&lt;br /&gt;
Moodle will always &#039;&#039;prefer&#039;&#039; the built shifted module over the older style module if both are present.&lt;br /&gt;
&lt;br /&gt;
If doing this, we would recommend copying over the minified version of your file so that older versions of moodle benefit from your user of shifted code.&lt;br /&gt;
&lt;br /&gt;
On a Linux-like operating system, you can use the following (again with our fruit example):&lt;br /&gt;
  cp yui/build/moodle-mod_fruit-fruitbowl/moodle-mod_fruit-fruitbowl-min.js yui/fruitbowl/fruitbowl.js&lt;br /&gt;
&lt;br /&gt;
Whilst developing, you may want to use a symlink so that you don&#039;t have to keep copying your changes after building them:&lt;br /&gt;
  ln -s yui/build/moodle-mod_fruit-fruitbowl/moodle-mod_fruit-fruitbowl.js yui/fruitbowl/fruitbowl.js&lt;br /&gt;
&lt;br /&gt;
==See also==&lt;br /&gt;
&lt;br /&gt;
* [[JavaScript guidelines]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45614</id>
		<title>Setting up PhpStorm</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45614"/>
		<updated>2014-07-01T23:46:19Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* General settings */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.jetbrains.com/phpstorm/ PhpStorm] is a commercial IDE, it is arguably the best IDE for PHP developers with features such as code completion, code inspection, phpunit support, Behat support, database editor, debugger, etc.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===OS X===&lt;br /&gt;
&lt;br /&gt;
You can optionally install latest Java JDK 1.7.x from [http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html Oracle] (Java 1.6 from Apple is not maintained much). By default PhpStorm uses only older 1.6.x java, but you can hack PhpStorm 7 to be compatible with Java 1.7 by editing the &amp;quot;PhpStorm.app/Contents/Info.plist&amp;quot; file, set JVMOptions - JVMVersion = 1.7*&lt;br /&gt;
&lt;br /&gt;
==General settings==&lt;br /&gt;
&lt;br /&gt;
* Disable missing @throws tag warning in &amp;quot;Preferences / Project Settings / Inspections / PHP / PHPDoc&amp;quot;&lt;br /&gt;
* Strip trailing whitespace from &amp;quot;Modified Lines&amp;quot; in &amp;quot;Preferences / IDE Settings / Editor&amp;quot;&lt;br /&gt;
* Show line numbers in &amp;quot;Preferences / IDE Settings / Editor / Appearance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Bug tracker integration==&lt;br /&gt;
&lt;br /&gt;
* Add tracker linking in &amp;quot;Preferences / Version control / Issue Navigation&amp;quot;&lt;br /&gt;
* Set Issue ID to &amp;quot;MDL-\d+&amp;quot; and Issue link to &amp;quot;https://tracker.moodle.org/browse/$0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Code formatting==&lt;br /&gt;
&lt;br /&gt;
* Setup coding style to use all rules from [[Coding style]] in &amp;quot;Preferences / Project Settings / Code Style / PHP&amp;quot;  - this will allow you to use automatic code formatting and it does nice code formatting on copy/paste.&lt;br /&gt;
* Set line separator to Unix in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
* Set right margin to 132 or 180 in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Moodle code checker==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PHPUnit integration==&lt;br /&gt;
# Install [[PHPUnit]] via Composer &lt;br /&gt;
# Tell PHPStorm where is composer - go to &amp;quot;Preferences / PHP / Composer&amp;quot;, fill in &amp;quot;Path to PHP executable&amp;quot;, &amp;quot;Path to composer.phar&amp;quot;, &amp;quot;Path to composer.json&amp;quot; and make sure the option &amp;quot;Add packages as libraries&amp;quot; is enabled.&lt;br /&gt;
# Go to &amp;quot;Run / Edit configurations&amp;quot;&lt;br /&gt;
# Add PHPUnit configuration by clicking on &amp;quot;+&amp;quot;&lt;br /&gt;
# Click &amp;quot;Use alternative configuration file&amp;quot; and select your phpunit.xml file&lt;br /&gt;
# Go to &amp;quot;Run / Run ...&amp;quot; and select your new PHPUnit configuration to run&lt;br /&gt;
&lt;br /&gt;
==Database editor==&lt;br /&gt;
# Click on the &amp;quot;Database&amp;quot; tab to see the database window&lt;br /&gt;
# Click &amp;quot;+&amp;quot; in the top left and add &amp;quot;Database source&amp;quot; for your database&lt;br /&gt;
# Note: click on the link to download the necessary drivers directly from IDE&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45613</id>
		<title>Setting up PhpStorm</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45613"/>
		<updated>2014-07-01T23:44:06Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* OS X */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.jetbrains.com/phpstorm/ PhpStorm] is a commercial IDE, it is arguably the best IDE for PHP developers with features such as code completion, code inspection, phpunit support, Behat support, database editor, debugger, etc.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===OS X===&lt;br /&gt;
&lt;br /&gt;
You can optionally install latest Java JDK 1.7.x from [http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html Oracle] (Java 1.6 from Apple is not maintained much). By default PhpStorm uses only older 1.6.x java, but you can hack PhpStorm 7 to be compatible with Java 1.7 by editing the &amp;quot;PhpStorm.app/Contents/Info.plist&amp;quot; file, set JVMOptions - JVMVersion = 1.7*&lt;br /&gt;
&lt;br /&gt;
==General settings==&lt;br /&gt;
&lt;br /&gt;
* Disable missing @throws tag warning in &amp;quot;Preferences / Project Settings / Inspections / PHP / PHPDoc&amp;quot;&lt;br /&gt;
* Strip trailing whitespace from &amp;quot;Modified Lines&amp;quot; in &amp;quot;Preferences / IDE Settings / Editor&amp;quot;&lt;br /&gt;
* Show line numbers in &amp;quot;Preferences / IDE Settings / Editor / Appearance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Code formatting==&lt;br /&gt;
&lt;br /&gt;
* Setup coding style to use all rules from [[Coding style]] in &amp;quot;Preferences / Project Settings / Code Style / PHP&amp;quot;  - this will allow you to use automatic code formatting and it does nice code formatting on copy/paste.&lt;br /&gt;
* Set line separator to Unix in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
* Set right margin to 132 or 180 in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Moodle code checker==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PHPUnit integration==&lt;br /&gt;
# Install [[PHPUnit]] via Composer &lt;br /&gt;
# Tell PHPStorm where is composer - go to &amp;quot;Preferences / PHP / Composer&amp;quot;, fill in &amp;quot;Path to PHP executable&amp;quot;, &amp;quot;Path to composer.phar&amp;quot;, &amp;quot;Path to composer.json&amp;quot; and make sure the option &amp;quot;Add packages as libraries&amp;quot; is enabled.&lt;br /&gt;
# Go to &amp;quot;Run / Edit configurations&amp;quot;&lt;br /&gt;
# Add PHPUnit configuration by clicking on &amp;quot;+&amp;quot;&lt;br /&gt;
# Click &amp;quot;Use alternative configuration file&amp;quot; and select your phpunit.xml file&lt;br /&gt;
# Go to &amp;quot;Run / Run ...&amp;quot; and select your new PHPUnit configuration to run&lt;br /&gt;
&lt;br /&gt;
==Database editor==&lt;br /&gt;
# Click on the &amp;quot;Database&amp;quot; tab to see the database window&lt;br /&gt;
# Click &amp;quot;+&amp;quot; in the top left and add &amp;quot;Database source&amp;quot; for your database&lt;br /&gt;
# Note: click on the link to download the necessary drivers directly from IDE&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45385</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45385"/>
		<updated>2014-06-19T21:52:43Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Class and file naming rules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
==Class and file naming rules==&lt;br /&gt;
The class names of all testcases need to be unique, Frankenstyle prefix is used to guarantee this. Since 2.6 it is possible to use automatic class loader when executing individual unit tests.&lt;br /&gt;
&lt;br /&gt;
* All test case classes start with Frankenstyle prefix, for example: &#039;&#039;&#039;mod_forum_&#039;&#039;&#039;, &#039;&#039;&#039;block_html_&#039;&#039;&#039;, &#039;&#039;&#039;core_&#039;&#039;&#039;.&lt;br /&gt;
* All test case classes end with &#039;&#039;&#039;_testcase&#039;&#039;&#039; suffix.&lt;br /&gt;
* File names are constructed from the class names - the Frankenstyle prefix is removed, suffix &#039;&#039;&#039;_testcase&#039;&#039;&#039; is replaced with &#039;&#039;&#039;_test&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
* class &#039;&#039;&#039;mod_forum_lib_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/mod/forum/tests/lib_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit mod_forum_lib_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
* class &#039;&#039;&#039;core_text_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/lib/texts/text_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit core_text_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests. The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/sample_basic_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/some_permission_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45384</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45384"/>
		<updated>2014-06-19T21:51:59Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Class and file naming rules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
==Class and file naming rules==&lt;br /&gt;
The class names of all testcases need to be unique, Frankenstyle prefix is used to guarantee this. Since 2.7 it is possible to use automatic class loader when executing individual unit tests.&lt;br /&gt;
&lt;br /&gt;
* All test case classes start with Frankenstyle prefix, for example: &#039;&#039;&#039;mod_forum_&#039;&#039;&#039;, &#039;&#039;&#039;block_html_&#039;&#039;&#039;, &#039;&#039;&#039;core_&#039;&#039;&#039;.&lt;br /&gt;
* All test case classes end with &#039;&#039;&#039;_testcase&#039;&#039;&#039; suffix.&lt;br /&gt;
* File names are constructed from the class names - the Frankenstyle prefix is removed, suffix &#039;&#039;&#039;_testcase&#039;&#039;&#039; is replaced with &#039;&#039;&#039;_test&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
* class &#039;&#039;&#039;mod_forum_lib_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/mod/forum/tests/lib_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit mod_forum_lib_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
* class &#039;&#039;&#039;core_text_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/lib/texts/text_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit core_text_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests. The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/sample_basic_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/some_permission_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45371</id>
		<title>Setting up PhpStorm</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45371"/>
		<updated>2014-06-19T00:20:08Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Code formatting */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.jetbrains.com/phpstorm/ PhpStorm] is a commercial IDE, it is arguably the best IDE for PHP developers with features such as code completion, code inspection, phpunit support, Behat support, database editor, debugger, etc.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===OS X===&lt;br /&gt;
Install latest Java JDK 1.7.x from [http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html Oracle] (Java 1.6 from Apple is not maintained much).&lt;br /&gt;
&lt;br /&gt;
You can hack older PhpStorm 7 to be compatible with Java 1.7 by editing the &amp;quot;PhpStorm.app/Contents/Info.plist&amp;quot; file, set JVMOptions - JVMVersion = 1.7*&lt;br /&gt;
&lt;br /&gt;
==General settings==&lt;br /&gt;
&lt;br /&gt;
* Disable missing @throws tag warning in &amp;quot;Preferences / Project Settings / Inspections / PHP / PHPDoc&amp;quot;&lt;br /&gt;
* Strip trailing whitespace from &amp;quot;Modified Lines&amp;quot; in &amp;quot;Preferences / IDE Settings / Editor&amp;quot;&lt;br /&gt;
* Show line numbers in &amp;quot;Preferences / IDE Settings / Editor / Appearance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Code formatting==&lt;br /&gt;
&lt;br /&gt;
* Setup coding style to use all rules from [[Coding style]] in &amp;quot;Preferences / Project Settings / Code Style / PHP&amp;quot;  - this will allow you to use automatic code formatting and it does nice code formatting on copy/paste.&lt;br /&gt;
* Set line separator to Unix in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
* Set right margin to 132 or 180 in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Moodle code checker==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PHPUnit integration==&lt;br /&gt;
# Install [[PHPUnit]] via Composer &lt;br /&gt;
# Tell PHPStorm where is composer - go to &amp;quot;Preferences / PHP / Composer&amp;quot;, fill in &amp;quot;Path to PHP executable&amp;quot;, &amp;quot;Path to composer.phar&amp;quot;, &amp;quot;Path to composer.json&amp;quot; and make sure the option &amp;quot;Add packages as libraries&amp;quot; is enabled.&lt;br /&gt;
# Go to &amp;quot;Run / Edit configurations&amp;quot;&lt;br /&gt;
# Add PHPUnit configuration by clicking on &amp;quot;+&amp;quot;&lt;br /&gt;
# Click &amp;quot;Use alternative configuration file&amp;quot; and select your phpunit.xml file&lt;br /&gt;
# Go to &amp;quot;Run / Run ...&amp;quot; and select your new PHPUnit configuration to run&lt;br /&gt;
&lt;br /&gt;
==Database editor==&lt;br /&gt;
# Click on the &amp;quot;Database&amp;quot; tab to see the database window&lt;br /&gt;
# Click &amp;quot;+&amp;quot; in the top left and add &amp;quot;Database source&amp;quot; for your database&lt;br /&gt;
# Note: click on the link to download the necessary drivers directly from IDE&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_Netbeans&amp;diff=45370</id>
		<title>Setting up Netbeans</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_Netbeans&amp;diff=45370"/>
		<updated>2014-06-19T00:14:57Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* PHPUnit support */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.netbeans.org/features/php/index.html NetBeans] has got a good PHP support. You find a host of information on the website (tutorials, developer blog, screen casts, etc.).&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* CVS integration: see all changes, lines deletion, diff in real time, show annotations, diff history...&lt;br /&gt;
* Ctrl+Click: Go to declaration&lt;br /&gt;
* Export/Import Diff Patch&lt;br /&gt;
* Easy navigation&lt;br /&gt;
* List of functions&lt;br /&gt;
* Code completion&lt;br /&gt;
* Instant rename&lt;br /&gt;
* HTML, CSS, JavaScript support&lt;br /&gt;
* MySQL manager&lt;br /&gt;
* Quick Search&lt;br /&gt;
* Very few bugs&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
* Download the latest stable version from http://netbeans.org. Get the bundle that contains only PHP support.&lt;br /&gt;
* Install and run it.&lt;br /&gt;
&lt;br /&gt;
== Set up for Moodle development ==&lt;br /&gt;
&lt;br /&gt;
* Checkout your Moodle project with a &#039;&#039;&#039;CVS client&#039;&#039;&#039; - see [[:en:CVS for Administrators]] or [[CVS for developers|CVS for Developers]].&lt;br /&gt;
&lt;br /&gt;
* Open File &amp;gt; New Project &amp;gt; PHP &amp;gt; PHP Application &amp;gt; Next &lt;br /&gt;
: You&#039;re going to set the project now. &#039;&#039;Name&#039;&#039;, &#039;&#039;Location&#039;&#039; and &#039;&#039;Folder&#039;&#039; are used by NetBeans and are not related to the source code. So you can choose whatever you like, except your source folder. &#039;&#039;Sources&#039;&#039; has to be your checked out Moodle branch/head folder. The rest is clear enough. Don&#039;t forget to choose UTF-8 for &#039;&#039;Default Encoding&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
: Example:&lt;br /&gt;
&lt;br /&gt;
 Project Name:        Moodle 1.9 Stable&lt;br /&gt;
 Project Location:    C:\Users\jerome\Documents\NetBeansProjects&lt;br /&gt;
 Project Folder:      C:\Users\jerome\Documents\NetBeansProjects\Moodle 1.9 Stable&lt;br /&gt;
 Project Sources:     C:\Users\jerome\Projects\branch19_STABLE\moodle&lt;br /&gt;
 Project URL:         http://localhost/moodle19/&lt;br /&gt;
 Index File:          index.php&lt;br /&gt;
 Create:              unchecked&lt;br /&gt;
 Default Encoding:    UTF-8&lt;br /&gt;
 Set as Main Project: unchecked&lt;br /&gt;
&lt;br /&gt;
* Click on Finish.&lt;br /&gt;
&lt;br /&gt;
* Start coding!&lt;br /&gt;
&lt;br /&gt;
== CVS with NetBeans ==&lt;br /&gt;
&lt;br /&gt;
NetBeans comes with &#039;&#039;&#039;integrated CVS support&#039;&#039;&#039; which might be the easiest way to check out Moodle.&lt;br /&gt;
&lt;br /&gt;
=== Anonymous checkout ===&lt;br /&gt;
&lt;br /&gt;
# In NetBeans, select Window-&amp;gt;Versioning-&amp;gt;CVS-&amp;gt;Checkout&lt;br /&gt;
# Select Team-&amp;gt;CVS-&amp;gt;Checkout&lt;br /&gt;
# Enter into CVS Root: &#039;&#039;:pserver:anonymous@us.cvs.moodle.org:/cvsroot/moodle&#039;&#039;&lt;br /&gt;
: (Non-US-residents might use one of the other [https://docs.moodle.org/en/CVS_for_Administrators#CVS_Servers Moodle CVS servers] nearer to them.)&lt;br /&gt;
# Click &#039;&#039;Next&#039;&#039;&lt;br /&gt;
# Browse or enter into &#039;&#039;Module:&#039;&#039; moodle&lt;br /&gt;
# Browse or enter into &#039;&#039;Branch:&#039;&#039; MOODLE_19_STABLE&lt;br /&gt;
# Browse or enter into &#039;&#039;Local Folder:&#039;&#039; C:\xampp\htdocs&lt;br /&gt;
# Click &#039;&#039;Finish&#039;&#039; (and wait a few minutes for Moodle to be checked out)&lt;br /&gt;
# When you get the dialog box &amp;quot;Do you want to create an IDE project from the checked-out sources?&amp;quot;, Click &amp;quot;Create Project...&amp;quot;&lt;br /&gt;
# Select PHP Application with Existing Sources, and click Next&lt;br /&gt;
# Browse or enter into &#039;&#039;Sources Folder&#039;&#039; C:\xampp\htdocs\moodle&lt;br /&gt;
# Enter into &#039;&#039;Project Name:&#039;&#039; moodle&lt;br /&gt;
# Keep the other defaults and click next&lt;br /&gt;
# &#039;&#039;Run As:&#039;&#039; should have selected &#039;&#039;Local Web Site (running on local web server)&#039;&#039;&lt;br /&gt;
# Enter into Project URL http://localhost/moodle/&lt;br /&gt;
# Browse or enter into &#039;&#039;Index File:&#039;&#039; index.php&lt;br /&gt;
# Click &#039;&#039;Finish&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== Checkout for developers with write access ===&lt;br /&gt;
&lt;br /&gt;
As far as I can tell, there is no way to get NetBeans to work with CVS keys on Mac/Linux via the system SSH binary, so you will need to use the internal SSH and your password (which you can choose to save).&lt;br /&gt;
&lt;br /&gt;
If you wish to use NetBeans CVS and have CVS write access, the procedure is as follows:&lt;br /&gt;
&lt;br /&gt;
====Checkout of main Moodle codebase====&lt;br /&gt;
&lt;br /&gt;
# Follow the above instructions except for point 3&lt;br /&gt;
# At part 3, substitute &#039;&#039;:ext:yourusername&#039;&#039; for the part before the @ and remove the country code from after it, leaving it like this  &#039;&#039;&#039;&#039;&#039;:ext:yourusername&#039;&#039;&#039;@cvs.moodle.org:/cvsroot/moodle&#039;&#039;&lt;br /&gt;
# Follow the rest of the instructions as above&lt;br /&gt;
&lt;br /&gt;
If you wish to work with a plugin, you will need to check this out separately and add it to the Moodle code project you have just made. This because for some reason, the &#039;Do you want to create a project&#039; option fails to show any of the files once you open it if you try to check out the plugin on its own (NetBeans 6.7.1 on a Mac).&lt;br /&gt;
&lt;br /&gt;
====Checkout of contrib code====&lt;br /&gt;
&lt;br /&gt;
# Follow the above steps up to point 3, and again substitute &#039;&#039;:ext:yourusername&#039;&#039; and click &#039;next&#039;. Note that you should not try to specify the full contrib repository path yet.&lt;br /&gt;
# Click &#039;Browse...&#039; next to the &#039;Module&#039; dialogue&lt;br /&gt;
# Find the plugin you wish to work with in CONTRIB&lt;br /&gt;
# Click &#039;OK&#039;&lt;br /&gt;
# Proceed as before up to point 6, then press &#039;Close&#039; when asked if you want to create a new project.&lt;br /&gt;
# Now navigate to the folder you earlier specified in the &#039;local folder&#039; dialogue and you will find a folder marked &#039;contrib&#039;.&lt;br /&gt;
# navigate to the plugin folder, copy that folder, and then navigate to your main Moodle project folder and paste it where it belongs.&lt;br /&gt;
&lt;br /&gt;
Note that the last three points may cause you some grief when attempting to commit changes. CVS doesn&#039;t seem to like having subfolders with different origins. A workaround that operates well for me is to check out the contrib code manually into a folder using the command line as specified in the CVS for developers instructions, then import that code as a new project with existing sources. This allows easy commits and updates, whilst keeping it separate. You can then make a symlink from you main Moodle project to your contrib directory, restart NetBeans (the CVS info and symlink stuff is only refreshed on restart) and then right click the linked directory and choose &#039;Ignore&#039;, then do the same and choose &#039;Exclude from commit&#039;. You can now use the code as if it were part of Moodle, still getting all the code completion stuff, and also do clean updates and commits from the secondary project. [[User:Matt Gibson|Matt Gibson]] 19:53, 6 June 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
===Adding a branch to your plugin===&lt;br /&gt;
Your plugin will likely start with just a HEAD tag and at some point, you will want to branch it so that you can have versions for different Moodles. To add a MOODLE_20_STABLE branch, for example, do the following.&lt;br /&gt;
&lt;br /&gt;
# Checkout as above, but use the MOODLE_20_STABLE branch instead of MOODLE_19_STABLE&lt;br /&gt;
# You will end up with an empty folder, which you copy into place as above.&lt;br /&gt;
# Find the folder in NetBeans, then right click and choose CVS-&amp;gt;Merge changes from branch...&lt;br /&gt;
# Choose to merge from whatever branch has all the current code, using the help link if not sure what to do.&lt;br /&gt;
&lt;br /&gt;
There is a small chance that the Merge link will not be there, in which case, you will have to copy the files into the directory by hand outside netbeans and then check them in. If you do this, make sure you don&#039;t copy over the &#039;CVS&#039; folders that will have been made when you checked out the MOODLE_19_STABLE code.&lt;br /&gt;
&lt;br /&gt;
=== A few warnings ===&lt;br /&gt;
&lt;br /&gt;
Some of these warnings could also apply to other IDEs:&lt;br /&gt;
&lt;br /&gt;
* If you want to delete a file from your computer but not from CVS, delete it from Windows Explorer/Nautilus/Finder. Otherwise your next commit could delete the file from CVS. &amp;lt;br/&amp;gt;In case you have already deleted a wrong file from NetBeans:  with Windows Explorer/Nautilus/Finder, delete all the folder content of this deleted file (including the CVS folder) and update the folder.&lt;br /&gt;
* If you rename files and that other people are working on them, NetBeans could end up to mess up your CVS folder (even though that is quite rare). Then NetBeans CVS will refuse to update your code displaying a no explicit error as &#039;&#039;&#039;Update Failed&#039;&#039;&#039;. In this case, delete the content of the damaged folder with Windows Explorer/Nautilus/Finder. Then update this folder.&lt;br /&gt;
* If you create a patch or a new PHP file with NetBeans on Microsoft Windows, please check that it&#039;s a Unix format file. You may want to use another software to create Unix format patch/php files.&lt;br /&gt;
&lt;br /&gt;
== Git with NetBeans ==&lt;br /&gt;
&lt;br /&gt;
=== NBGit | Git Support for NetBeans ===&lt;br /&gt;
&lt;br /&gt;
&amp;quot;NBGit is a module for the NetBeans IDE that adds support for working with the Git version control system. It uses the JGit library created as part of EGit to interact with Git repositories. Because the module is Java code all the way, it should work better cross-platform modulo platform specific differences, such as file system behavior. It is based on the NetBeans Mercurial module.&amp;quot; &lt;br /&gt;
(http://nbgit.org)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p class=&amp;quot;note orange&amp;quot;&amp;gt;&lt;br /&gt;
Unfortunately, the key word in that quote is &#039;&#039;&#039;should&#039;&#039;&#039;. In reality, because JGit is a rewrite from scratch of the tried-and-tested git core C code, it is still buggy, incomplete and unreliable. Therefore, the NetBeans and Eclipse git plugins are still only beta quality, and pretty sucky. Well, they mostly work for browsing the contents of the repository, but there is a small chance that if you use them for update operations, they will corrupt your repository. Hence, I am still doing git from the command-line.--[[User:Tim Hunt|Tim Hunt]] 11:11, 19 January 2010 (UTC)&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wiki page needs updating ===&lt;br /&gt;
&lt;br /&gt;
Git is now integrated into Netbeans 7&lt;br /&gt;
https://netbeans.org/kb/70/ide/git.html&lt;br /&gt;
&lt;br /&gt;
== Optimization ==&lt;br /&gt;
&lt;br /&gt;
=== Sun JDK ===&lt;br /&gt;
1. You may want to run NetBeans with the Sun JDK. NetBeans seems to work a bit better with the [http://java.sun.com/javase/downloads/index.jsp Sun JDK]. You&#039;ll have to edit NetBeans config file. Open netbeans/etc/netbeans.conf. Then uncomment and edit: &lt;br /&gt;
&lt;br /&gt;
 netbeans_jdkhome=&amp;quot;your_JDK_path&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2. To change the NetBeans look and feel run netbeans in the command line with this parameter:&lt;br /&gt;
 &amp;quot;netbeans&amp;quot;  --laf javax.swing.plaf.metal.MetalLookAndFeel &lt;br /&gt;
&lt;br /&gt;
3. If NetBeans starts to slow down, give it more memory&lt;br /&gt;
 &amp;quot;netbeans&amp;quot; -J-Xmx600m&lt;br /&gt;
See FAQ for more [http://wiki.netbeans.org/FaqSettingHeapSize details on memory optimisation].&lt;br /&gt;
&lt;br /&gt;
=== ScanOnDemand ===&lt;br /&gt;
To prevent NetBeans from scanning the whole code with every start up you can use the following plug-in: http://wiki.netbeans.org/ScanOnDemand&lt;br /&gt;
&lt;br /&gt;
== Coding faster ==&lt;br /&gt;
&lt;br /&gt;
=== Coding standards ===&lt;br /&gt;
&lt;br /&gt;
* There is NB config file available with the [https://github.com/enovation/moodle-utils/tree/master/netbeans-config Moodle coding settings]&lt;br /&gt;
&lt;br /&gt;
=== Keyboard shortcuts ===&lt;br /&gt;
(Note: Some shortcuts might not work for PHP development.)&lt;br /&gt;
* [http://www.phpmag.ru/2009/01/23/extremely-usefull-netbeans-shortcuts/ Extremely Useful NetBeans Shortcuts] &lt;br /&gt;
* [http://netbeanside61.blogspot.com/2008/04/top-10-netbeans-ide-keyboard-shortcuts.html Top 10 NetBeans IDE Keyboard Shortcuts I use the most]&lt;br /&gt;
* [http://wiki.netbeans.org/KeymapProfileFor60 NetBeans IDE 6.x Keyboard Shortcuts Specification]&lt;br /&gt;
&lt;br /&gt;
=== PHPUnit support ===&lt;br /&gt;
See [http://netbeans.org/kb/docs/php/phpunit.html Netbeans PHPUnit support].&lt;br /&gt;
&lt;br /&gt;
===JIRA support===&lt;br /&gt;
You can install the optional JIRA module in order to be able to interact with the Moodle Tracker from within NetBeans. This has the advantage of avoiding constantly switching back and forth from the browser and works quite well. Go to &#039;&#039;Tools-&amp;gt;plugins-&amp;gt;available plugins&#039;&#039; and search for JIRA. Once installed, right click &#039;issue trackers&#039; in the &#039;services&#039; pane to make a new tracker instance, then enter your details.&lt;br /&gt;
&lt;br /&gt;
== See also: ==&lt;br /&gt;
Moodle forums &lt;br /&gt;
* [http://moodle.org/mod/forum/discuss.php?d=112972 NetBeans 6.5 for moodle/PHP/debugging is a better experience v.s Eclipse]&lt;br /&gt;
&lt;br /&gt;
Online resources&lt;br /&gt;
* [http://www.netbeans.org/kb/trails/php.html NetBeans PHP Learning Trail]&lt;br /&gt;
* [http://wiki.netbeans.org/PHP NetBeans PHP Wiki]&lt;br /&gt;
* Sun&#039;s [http://blogs.sun.com/netbeansphp/ NetBeans PHP Team Blog]&lt;br /&gt;
&lt;br /&gt;
Book&lt;br /&gt;
* [http://www.packtpub.com/netbeans-platform-6-8-developers-guide/book NetBeans Platform 6.8 Developer&#039;s Guide] by Jürgen Petri (March 2010), focus on Java and Swing &lt;br /&gt;
&lt;br /&gt;
[[Category:Developer tools|NetBeans]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45368</id>
		<title>PHPUnit</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45368"/>
		<updated>2014-06-19T00:13:05Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* PHPUnit support in IDEs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
=What is PHPUnit=&lt;br /&gt;
PHPUnit by Sebastian Bergmann is an advanced unit testing framework for PHP. It is installed as Composer dependency and is not part of Moodle installation. To run PHPUnit tests, you have to manually install it on your development computer or test server.&lt;br /&gt;
&lt;br /&gt;
Read the excellent guide at&lt;br /&gt;
* [http://phpunit.de/manual/current/en/index.html PHPUnit Manual]&lt;br /&gt;
&lt;br /&gt;
=Installation of PHPUnit via Composer=&lt;br /&gt;
&lt;br /&gt;
The installation procedure depends on your operating system.&lt;br /&gt;
* Install Composer dependency manager&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 curl -s https://getcomposer.org/installer | php&lt;br /&gt;
&lt;br /&gt;
On Windows go to https://getcomposer.org/download/ and download the Composer-Setup.exe file&lt;br /&gt;
&lt;br /&gt;
* Execute Composer installer&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 php composer.phar install --dev&lt;br /&gt;
&lt;br /&gt;
(If that gives you connection problems try...)&lt;br /&gt;
&lt;br /&gt;
 php composer.phar install --dev --prefer-source&lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
* On Windows if you are behind a proxy you will need to setup an environment variable called HTTP_PROXY with a value detailing your HTTP Proxy address and port before composer will correctly download files.&lt;br /&gt;
* You may be prompted for github credentials when installing composer dependencies.&lt;br /&gt;
** This is used to generate an personal access token to avoid being rate limited by github.&lt;br /&gt;
** If you have Two Factor Authentication enabled on your github account, or do not wish to supply your own credentials you will need to generate a token manually:&lt;br /&gt;
*** Visit https://github.com/settings/applications and request personal access token&lt;br /&gt;
*** Copy this token and add it to your [https://gist.github.com/andrewnicols/c5377ed25a9df1006ce1 ~/.composer/config.json]&lt;br /&gt;
** ( See [https://github.com/composer/composer/issues/2280 composer issue #2280] for further details of this bug.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [http://getcomposer.org/doc/00-intro.md Composer documentation]&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [[PHPUnit installation in Windows]]&lt;br /&gt;
* [[PHPUnit installation in OS X]]&lt;br /&gt;
&lt;br /&gt;
== Uninstalling previous PEAR based version ==&lt;br /&gt;
&lt;br /&gt;
Before using composer, this page used to suggest to install phpunit via PEAR. If you did so, you may wish to uninstall that package now. This should work:&lt;br /&gt;
&lt;br /&gt;
   $ pear uninstall phpunit/DbUnit&lt;br /&gt;
   $ pear uninstall phpunit/PHPUnit&lt;br /&gt;
&lt;br /&gt;
=Initialisation of test environment=&lt;br /&gt;
&lt;br /&gt;
Our PHPUnit integration requires a dedicated database and dataroot.  First, add a new dataroot directory and prefix into your config.php, you can find examples in config-dist.php (scroll down to &#039;Section 9&#039;).&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;phpunit_prefix = &#039;phpu_&#039;;&lt;br /&gt;
 $CFG-&amp;gt;phpunit_dataroot = &#039;/home/example/phpu_moodledata&#039;;&lt;br /&gt;
&lt;br /&gt;
If your system does not have a direct connection to the Internet, you also need to specify your proxy in config.php - even though you normally specify it by using the admin settings user interface. (If you do not use a proxy, you can skip this step.) Check the settings on the relevant admin settings page, or from the mdl_config table in your database, if you are unsure of the correct values.&lt;br /&gt;
 &lt;br /&gt;
 // Normal proxy settings&lt;br /&gt;
 $CFG-&amp;gt;proxyhost = &#039;wwwcache.example.org&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxyport = 80;&lt;br /&gt;
 $CFG-&amp;gt;proxytype = &#039;HTTP&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxybypass = &#039;localhost, 127.0.0.1, .example.org&#039;;&lt;br /&gt;
 // Omit the next lines if your proxy doesn&#039;t need a username/password:&lt;br /&gt;
 $CFG-&amp;gt;proxyuser = &#039;systemusername&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxypassword = &#039;systempassword&#039;;&lt;br /&gt;
&lt;br /&gt;
Then you need to initialise the test environment using following command.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 php admin/tool/phpunit/cli/init.php&lt;br /&gt;
&lt;br /&gt;
This command has to be repeated after any upgrade, plugin (un)installation or if you have added tests to a plugin you are developing:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; make sure that your php cli executable (or the one you want to use) is correctly on your path as the individual init scripts will call it repeatedly.&lt;br /&gt;
&lt;br /&gt;
=Test execution=&lt;br /&gt;
&lt;br /&gt;
To execute all test suites from main configuration file execute the &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; script from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 vendor/bin/phpunit&lt;br /&gt;
&lt;br /&gt;
The rest of examples uses &amp;lt;code&amp;gt;phpunit&amp;lt;/code&amp;gt;, please substitute it with &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; or create a shortcut in your dirroot.&lt;br /&gt;
&lt;br /&gt;
In IDEs, you may need to specify the path to the PHPUnit configuration file. Use the absolute path to &amp;lt;code&amp;gt;phpunit.xml&amp;lt;/code&amp;gt; from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is an alternative script for running of tests via web interface: &amp;lt;code&amp;gt;admin/tool/phpunit/webrunner.php&amp;lt;/code&amp;gt;. Use this as the last resort only when you cannot use the command-line interface on your test server. It will most probably break due to permissions problems if you try to execute it both from command-line and from webrunner. This feature is not officially supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===How to run only some tests===&lt;br /&gt;
&lt;br /&gt;
==== Running a single test quickly ====&lt;br /&gt;
&lt;br /&gt;
The fastest way to run a single test is:&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit my_test_class_name my/tests/filename.php&lt;br /&gt;
&lt;br /&gt;
This is faster than other methods because it avoids the need to search for the test file, but you should be careful because it may be possible to run tests this way which are not included in the normal run. If you use this method, do at least one full test run (or --group run, as below) to ensure the test can be found.&lt;br /&gt;
&lt;br /&gt;
Please note the path name is optional if the testcase class and file names are standardised as described in [[Writing PHPUnit tests]].&lt;br /&gt;
&lt;br /&gt;
==== Using the @group annotation ====&lt;br /&gt;
&lt;br /&gt;
If you add annotations like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for {@link stack_cas_keyval}.&lt;br /&gt;
 * @group qtype_stack&lt;br /&gt;
 */&lt;br /&gt;
class qtype_stack_cas_keyval_exception_testcase extends basic_testcase {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to all the classes in your plugin, then you can run just the tests for your plugin by doing&lt;br /&gt;
&lt;br /&gt;
 phpunit --group qtype_stack&lt;br /&gt;
&lt;br /&gt;
Therefore, it is suggested that you annotate all your tests with the Frankenstyle name of your plugin.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple phpunit.xml files ====&lt;br /&gt;
&lt;br /&gt;
It&#039;s easy to create alternative phpunit.xml files defining which tests must be run together. For reference, take a look to the default /phpunit.xml available in your base directory once the testing environment has been initialised. After creating the custom file you will be able to run those tests with&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c path/to/your/alternative/phpunit/file.xml&lt;br /&gt;
&lt;br /&gt;
Also, for commodity, you can use this command:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/phpunit/cli/util.php --buildcomponentconfigs&lt;br /&gt;
&lt;br /&gt;
It will, automatically, create one valid phpunit.xml file within each component (plugin or subsystem) and other important directories, so later you will be able to execute tests like&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c mod/forum[/phpunit.xml]  // Note that it&#039;s not needed to specify the name of the file (if it is &#039;phpunit.xml&#039;).&lt;br /&gt;
 vendor/bin/phpunit -c question&lt;br /&gt;
 vendor/bin/phpunit -c question/type/calculated&lt;br /&gt;
 vendor/bin/phpunit -c backup&lt;br /&gt;
 vendor/bin/phpunit -c lib/dml&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
or, also&lt;br /&gt;
&lt;br /&gt;
 cd directory/with/phpunit.xml&lt;br /&gt;
 phpunit&lt;br /&gt;
&lt;br /&gt;
=External test resources=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
By default Moodle phpunit tests contact http://download.moodle.org server when testing curl related functionality. Optionally you may checkout a local copy of the test scripts and access it instead:&lt;br /&gt;
&lt;br /&gt;
# clone https://github.com/moodlehq/moodle-exttests to web directory&lt;br /&gt;
# add to your config.php or modify phpunit.xml file &amp;lt;code php&amp;gt;define(&#039;TEST_EXTERNAL_FILES_HTTP_URL&#039;, &#039;http://localhost/moodle-exttests&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Writing new tests=&lt;br /&gt;
* read [http://www.phpunit.de/manual/current/en/ official PHPUnit online documentation]&lt;br /&gt;
* see [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
=Conversion of existing SimpleTests=&lt;br /&gt;
* see [[SimpleTest conversion]]&lt;br /&gt;
&lt;br /&gt;
=PHPUnit support in IDEs=&lt;br /&gt;
&lt;br /&gt;
* [[Setting up Eclipse]]&lt;br /&gt;
* [[Setting up Netbeans]]&lt;br /&gt;
* [[Setting up PhpStorm]]&lt;br /&gt;
&lt;br /&gt;
=Common Unit Test Problems=&lt;br /&gt;
[[Common unit test problems]]&lt;br /&gt;
&lt;br /&gt;
=Performance=&lt;br /&gt;
&lt;br /&gt;
A typical run of full PHPUnit tests for Moodle 2.7 takes 10-20 minutes depending on the machine. If tests run slowly for you:&lt;br /&gt;
&lt;br /&gt;
* Ensure you are using a database and filesystem running on the same machine that is running the tests (not on a remote server).&lt;br /&gt;
* Apply developer-only performance settings to your database: [[Postgres Tuning For Developers]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45366</id>
		<title>Writing PHPUnit tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45366"/>
		<updated>2014-06-19T00:07:00Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Sample plugin testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
Moodle PHPUnit integration is designed to allow easy adding of new tests. At the start of each test the state is automatically reset to fresh new installation (unless explicitly told not to reset).&lt;br /&gt;
&lt;br /&gt;
=Testcase classes=&lt;br /&gt;
&lt;br /&gt;
There are two basic test class that are supposed to used in all Moodle unit tests - basic_testcase and advanced_testcase. &#039;&#039;&#039;Please note it is strongly recommended to put only one testcase into each class file.&#039;&#039;&#039;&lt;br /&gt;
;basic_testcase : Very simple tests that do not modify database, dataroot or any PHP globals. It can be used for example when trying examples from the official PHPUnit tutorial.&lt;br /&gt;
;advanced_testcase : Enhanced testcase class enhanced for easy testing of Moodle code.&lt;br /&gt;
&lt;br /&gt;
There is a third testcase class that is specially designed for testing of our Moodle database layer, it should not be used for other purposes.&lt;br /&gt;
&lt;br /&gt;
== Assertions ==&lt;br /&gt;
&lt;br /&gt;
The complete list of assertions can be found in the [http://www.phpunit.de/manual/3.7/en/appendixes.assertions.html phpunit manual].&lt;br /&gt;
==Sample plugin testcase==&lt;br /&gt;
&lt;br /&gt;
PHPUnit tests are located in &amp;lt;code&amp;gt;tests/*_test.php&amp;lt;/code&amp;gt; files in your plugin, for example mod/myplugin/tests/sample_test.php, the file should contain only one class that extends &amp;lt;code&amp;gt;advanced_testcase&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_sample_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_adding() {&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, 1+2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[PHPUnit integration#Class and file naming rules]] for more information.&lt;br /&gt;
&lt;br /&gt;
==Inclusion of Moodle library files==&lt;br /&gt;
&lt;br /&gt;
If you want to include some Moodle library files you should always declare &#039;&#039;&#039;global $CFG&#039;&#039;&#039;. The reason is that testcase files may be included from non-moodle code which does not make the global $CFG available automatically.&lt;br /&gt;
&lt;br /&gt;
==Automatic state reset==&lt;br /&gt;
By default after each test Moodle database and dataroot is automatically reset to the original state which was present right after installation. make sure to use $this-&amp;gt;resetAfterTest() to indicate that the database or changes of standard global variables are expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_deleting() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;resetAfterTest(true);&lt;br /&gt;
         $DB-&amp;gt;delete_records(&#039;user&#039;);&lt;br /&gt;
         $this-&amp;gt;assertEmpty($DB-&amp;gt;get_records(&#039;user&#039;));&lt;br /&gt;
     }&lt;br /&gt;
     public function test_user_table_was_reset() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, $DB-&amp;gt;count_records(&#039;user&#039;, array()));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Generators=&lt;br /&gt;
&lt;br /&gt;
Tests that need to modify default installation may use generators to create new courses, users, etc. All examples on this page should be used from test methods of a test class derived from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
Note if you are using PHPUnit @dataProvider functions to provide parameters to unit tests, you can not use the data generator or change the user etc in the data provider function.&lt;br /&gt;
&lt;br /&gt;
==Creating users==&lt;br /&gt;
At the start of each test there are only two users present - guest and administrator. If you need to add more test accounts use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also specify properties of the user account, for example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user(array(&#039;email&#039;=&amp;gt;&#039;user1@example.com&#039;, &#039;username&#039;=&amp;gt;&#039;user1&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default no user is logged-in, use setUser() method to change current $USER value:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser($user1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Guest and admin accounts have a shortcut methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setGuestUser();&lt;br /&gt;
 $this-&amp;gt;setAdminUser();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Null can be used to set current user back to not-logged-in:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser(null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating course categories==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $category1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $category2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category(array(&#039;name&#039;=&amp;gt;&#039;Some subcategory&#039;, &#039;parent&#039;=&amp;gt;$category1-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating courses==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 &lt;br /&gt;
 $category = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $course2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course(array(&#039;name&#039;=&amp;gt;&#039;Some course&#039;, &#039;category&#039;=&amp;gt;$category-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating activities==&lt;br /&gt;
&lt;br /&gt;
Some activity plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php.&lt;br /&gt;
&lt;br /&gt;
Example of creation of new course with one page resource:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $generator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator(&#039;mod_page&#039;);&lt;br /&gt;
 $generator-&amp;gt;create_instance(array(&#039;course&#039;=&amp;gt;$course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating cohorts==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Since 2.4 there the data generator supports creation of new cohorts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $cohort = $this-&amp;gt;getDataGenerator()-&amp;gt;create_cohort();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simplified user enrolments==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Instead of standard enrolment API it is possible to use simplified method in data generator. It is intended to be used with self and manual enrolment plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid, &#039;manual&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other types of plugin==&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Any other type of plugin can have a generator. The generator class should extend component_generator_base, and then you can get an instance using $mygenerator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator($frankenstylecomponentname);&lt;br /&gt;
&lt;br /&gt;
For some types of plugin, like mod documented above, there may be a more specific class than component_generator_base to extend, like testing_module_generator. That will give a consistent set of method names to use. Otherwise, you can create whatever methods you like on your generator, to create the different things you need to work whith.&lt;br /&gt;
&lt;br /&gt;
=Long tests=&lt;br /&gt;
&lt;br /&gt;
All standard test should execute as fast as possible. Tests that take a loner time to execute (&amp;gt;10s) or are otherwise expensive (such as querying external servers that might be flooded by all dev machines) should be execute only when PHPUNIT_LONGTEST is true. This constant can be set in phpunit.xml or directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=Large test data=&lt;br /&gt;
See advanced_testcase::createXMLDataSet() and advanced_testcase::createCsvDataSet() and related functions there for easier ways to manage large test data sets within files rather than arrays in code. See [[PHPUnit_integration#Extra_methods]]&lt;br /&gt;
&lt;br /&gt;
=Testing sending of messages=&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
You can temporarily redirect all messages sent via message_send() to a message sink object. This allows developers to verify that the tested code is sending expected messages.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first disable the use of transactions and then redirect the messaging into a new message sink, you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
$sink = $this-&amp;gt;redirectMessages();&lt;br /&gt;
//... code that is sending messages&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(3, count($messages));&lt;br /&gt;
//.. test messages were generated in correct order with appropriate content&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Testing sending of emails=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
You can temporarily redirect emails sent via email_to_user() to a email message sink object. This allows developers to verify that the tested code is sending expected emails.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first unset &#039;noemailever&#039; setting and then redirect the emails into a new message sink where you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
unset_config(&#039;noemailever&#039;);&lt;br /&gt;
$sink = $this-&amp;gt;redirectEmails();&lt;br /&gt;
//... code that is sending email&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(1, count($messages));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Extra test settings=&lt;br /&gt;
&lt;br /&gt;
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.&lt;br /&gt;
&lt;br /&gt;
There are several ways how to inject your custom settings:&lt;br /&gt;
* define test setting constants in your phpunit.xml file&lt;br /&gt;
* define test setting constants in your config.php&lt;br /&gt;
&lt;br /&gt;
These constants may be then used in your test or plugin code.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[PHPUnit integration]]&lt;br /&gt;
* [[PHPUnit]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45365</id>
		<title>Writing PHPUnit tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45365"/>
		<updated>2014-06-19T00:05:38Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Sample plugin testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
Moodle PHPUnit integration is designed to allow easy adding of new tests. At the start of each test the state is automatically reset to fresh new installation (unless explicitly told not to reset).&lt;br /&gt;
&lt;br /&gt;
=Testcase classes=&lt;br /&gt;
&lt;br /&gt;
There are two basic test class that are supposed to used in all Moodle unit tests - basic_testcase and advanced_testcase. &#039;&#039;&#039;Please note it is strongly recommended to put only one testcase into each class file.&#039;&#039;&#039;&lt;br /&gt;
;basic_testcase : Very simple tests that do not modify database, dataroot or any PHP globals. It can be used for example when trying examples from the official PHPUnit tutorial.&lt;br /&gt;
;advanced_testcase : Enhanced testcase class enhanced for easy testing of Moodle code.&lt;br /&gt;
&lt;br /&gt;
There is a third testcase class that is specially designed for testing of our Moodle database layer, it should not be used for other purposes.&lt;br /&gt;
&lt;br /&gt;
== Assertions ==&lt;br /&gt;
&lt;br /&gt;
The complete list of assertions can be found in the [http://www.phpunit.de/manual/3.7/en/appendixes.assertions.html phpunit manual].&lt;br /&gt;
==Sample plugin testcase==&lt;br /&gt;
&lt;br /&gt;
PHPUnit tests are located in &amp;lt;code&amp;gt;tests/*_test.php&amp;lt;/code&amp;gt; files in your plugin, for example mod/myplugin/tests/sample_test.php, the file should contain only one class that extends &amp;lt;code&amp;gt;advanced_testcase&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_sample_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_adding() {&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, 1+2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See Class and file naming rules section in [[PHPUnit integration]] for more information about naming of test case classes and files.&lt;br /&gt;
&lt;br /&gt;
==Inclusion of Moodle library files==&lt;br /&gt;
&lt;br /&gt;
If you want to include some Moodle library files you should always declare &#039;&#039;&#039;global $CFG&#039;&#039;&#039;. The reason is that testcase files may be included from non-moodle code which does not make the global $CFG available automatically.&lt;br /&gt;
&lt;br /&gt;
==Automatic state reset==&lt;br /&gt;
By default after each test Moodle database and dataroot is automatically reset to the original state which was present right after installation. make sure to use $this-&amp;gt;resetAfterTest() to indicate that the database or changes of standard global variables are expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_deleting() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;resetAfterTest(true);&lt;br /&gt;
         $DB-&amp;gt;delete_records(&#039;user&#039;);&lt;br /&gt;
         $this-&amp;gt;assertEmpty($DB-&amp;gt;get_records(&#039;user&#039;));&lt;br /&gt;
     }&lt;br /&gt;
     public function test_user_table_was_reset() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, $DB-&amp;gt;count_records(&#039;user&#039;, array()));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Generators=&lt;br /&gt;
&lt;br /&gt;
Tests that need to modify default installation may use generators to create new courses, users, etc. All examples on this page should be used from test methods of a test class derived from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
Note if you are using PHPUnit @dataProvider functions to provide parameters to unit tests, you can not use the data generator or change the user etc in the data provider function.&lt;br /&gt;
&lt;br /&gt;
==Creating users==&lt;br /&gt;
At the start of each test there are only two users present - guest and administrator. If you need to add more test accounts use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also specify properties of the user account, for example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user(array(&#039;email&#039;=&amp;gt;&#039;user1@example.com&#039;, &#039;username&#039;=&amp;gt;&#039;user1&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default no user is logged-in, use setUser() method to change current $USER value:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser($user1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Guest and admin accounts have a shortcut methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setGuestUser();&lt;br /&gt;
 $this-&amp;gt;setAdminUser();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Null can be used to set current user back to not-logged-in:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser(null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating course categories==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $category1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $category2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category(array(&#039;name&#039;=&amp;gt;&#039;Some subcategory&#039;, &#039;parent&#039;=&amp;gt;$category1-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating courses==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 &lt;br /&gt;
 $category = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $course2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course(array(&#039;name&#039;=&amp;gt;&#039;Some course&#039;, &#039;category&#039;=&amp;gt;$category-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating activities==&lt;br /&gt;
&lt;br /&gt;
Some activity plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php.&lt;br /&gt;
&lt;br /&gt;
Example of creation of new course with one page resource:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $generator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator(&#039;mod_page&#039;);&lt;br /&gt;
 $generator-&amp;gt;create_instance(array(&#039;course&#039;=&amp;gt;$course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating cohorts==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Since 2.4 there the data generator supports creation of new cohorts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $cohort = $this-&amp;gt;getDataGenerator()-&amp;gt;create_cohort();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simplified user enrolments==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Instead of standard enrolment API it is possible to use simplified method in data generator. It is intended to be used with self and manual enrolment plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid, &#039;manual&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other types of plugin==&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Any other type of plugin can have a generator. The generator class should extend component_generator_base, and then you can get an instance using $mygenerator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator($frankenstylecomponentname);&lt;br /&gt;
&lt;br /&gt;
For some types of plugin, like mod documented above, there may be a more specific class than component_generator_base to extend, like testing_module_generator. That will give a consistent set of method names to use. Otherwise, you can create whatever methods you like on your generator, to create the different things you need to work whith.&lt;br /&gt;
&lt;br /&gt;
=Long tests=&lt;br /&gt;
&lt;br /&gt;
All standard test should execute as fast as possible. Tests that take a loner time to execute (&amp;gt;10s) or are otherwise expensive (such as querying external servers that might be flooded by all dev machines) should be execute only when PHPUNIT_LONGTEST is true. This constant can be set in phpunit.xml or directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=Large test data=&lt;br /&gt;
See advanced_testcase::createXMLDataSet() and advanced_testcase::createCsvDataSet() and related functions there for easier ways to manage large test data sets within files rather than arrays in code. See [[PHPUnit_integration#Extra_methods]]&lt;br /&gt;
&lt;br /&gt;
=Testing sending of messages=&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
You can temporarily redirect all messages sent via message_send() to a message sink object. This allows developers to verify that the tested code is sending expected messages.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first disable the use of transactions and then redirect the messaging into a new message sink, you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
$sink = $this-&amp;gt;redirectMessages();&lt;br /&gt;
//... code that is sending messages&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(3, count($messages));&lt;br /&gt;
//.. test messages were generated in correct order with appropriate content&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Testing sending of emails=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
You can temporarily redirect emails sent via email_to_user() to a email message sink object. This allows developers to verify that the tested code is sending expected emails.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first unset &#039;noemailever&#039; setting and then redirect the emails into a new message sink where you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
unset_config(&#039;noemailever&#039;);&lt;br /&gt;
$sink = $this-&amp;gt;redirectEmails();&lt;br /&gt;
//... code that is sending email&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(1, count($messages));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Extra test settings=&lt;br /&gt;
&lt;br /&gt;
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.&lt;br /&gt;
&lt;br /&gt;
There are several ways how to inject your custom settings:&lt;br /&gt;
* define test setting constants in your phpunit.xml file&lt;br /&gt;
* define test setting constants in your config.php&lt;br /&gt;
&lt;br /&gt;
These constants may be then used in your test or plugin code.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[PHPUnit integration]]&lt;br /&gt;
* [[PHPUnit]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45364</id>
		<title>Writing PHPUnit tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45364"/>
		<updated>2014-06-19T00:04:51Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Sample plugin testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
Moodle PHPUnit integration is designed to allow easy adding of new tests. At the start of each test the state is automatically reset to fresh new installation (unless explicitly told not to reset).&lt;br /&gt;
&lt;br /&gt;
=Testcase classes=&lt;br /&gt;
&lt;br /&gt;
There are two basic test class that are supposed to used in all Moodle unit tests - basic_testcase and advanced_testcase. &#039;&#039;&#039;Please note it is strongly recommended to put only one testcase into each class file.&#039;&#039;&#039;&lt;br /&gt;
;basic_testcase : Very simple tests that do not modify database, dataroot or any PHP globals. It can be used for example when trying examples from the official PHPUnit tutorial.&lt;br /&gt;
;advanced_testcase : Enhanced testcase class enhanced for easy testing of Moodle code.&lt;br /&gt;
&lt;br /&gt;
There is a third testcase class that is specially designed for testing of our Moodle database layer, it should not be used for other purposes.&lt;br /&gt;
&lt;br /&gt;
== Assertions ==&lt;br /&gt;
&lt;br /&gt;
The complete list of assertions can be found in the [http://www.phpunit.de/manual/3.7/en/appendixes.assertions.html phpunit manual].&lt;br /&gt;
==Sample plugin testcase==&lt;br /&gt;
&lt;br /&gt;
PHPUnit tests are located in &amp;lt;code&amp;gt;tests/*_test.php&amp;lt;/code&amp;gt; files in your plugin, for example mod/myplugin/tests/sample_test.php, the file should contain only one class that extends &amp;lt;code&amp;gt;advanced_testcase&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_sample_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_adding() {&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, 1+2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See Class and file naming rules section in [[PHPUnit Integration]] for more information about naming of test case classes and files.&lt;br /&gt;
&lt;br /&gt;
==Inclusion of Moodle library files==&lt;br /&gt;
&lt;br /&gt;
If you want to include some Moodle library files you should always declare &#039;&#039;&#039;global $CFG&#039;&#039;&#039;. The reason is that testcase files may be included from non-moodle code which does not make the global $CFG available automatically.&lt;br /&gt;
&lt;br /&gt;
==Automatic state reset==&lt;br /&gt;
By default after each test Moodle database and dataroot is automatically reset to the original state which was present right after installation. make sure to use $this-&amp;gt;resetAfterTest() to indicate that the database or changes of standard global variables are expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_deleting() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;resetAfterTest(true);&lt;br /&gt;
         $DB-&amp;gt;delete_records(&#039;user&#039;);&lt;br /&gt;
         $this-&amp;gt;assertEmpty($DB-&amp;gt;get_records(&#039;user&#039;));&lt;br /&gt;
     }&lt;br /&gt;
     public function test_user_table_was_reset() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, $DB-&amp;gt;count_records(&#039;user&#039;, array()));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Generators=&lt;br /&gt;
&lt;br /&gt;
Tests that need to modify default installation may use generators to create new courses, users, etc. All examples on this page should be used from test methods of a test class derived from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
Note if you are using PHPUnit @dataProvider functions to provide parameters to unit tests, you can not use the data generator or change the user etc in the data provider function.&lt;br /&gt;
&lt;br /&gt;
==Creating users==&lt;br /&gt;
At the start of each test there are only two users present - guest and administrator. If you need to add more test accounts use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also specify properties of the user account, for example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user(array(&#039;email&#039;=&amp;gt;&#039;user1@example.com&#039;, &#039;username&#039;=&amp;gt;&#039;user1&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default no user is logged-in, use setUser() method to change current $USER value:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser($user1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Guest and admin accounts have a shortcut methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setGuestUser();&lt;br /&gt;
 $this-&amp;gt;setAdminUser();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Null can be used to set current user back to not-logged-in:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser(null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating course categories==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $category1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $category2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category(array(&#039;name&#039;=&amp;gt;&#039;Some subcategory&#039;, &#039;parent&#039;=&amp;gt;$category1-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating courses==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 &lt;br /&gt;
 $category = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $course2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course(array(&#039;name&#039;=&amp;gt;&#039;Some course&#039;, &#039;category&#039;=&amp;gt;$category-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating activities==&lt;br /&gt;
&lt;br /&gt;
Some activity plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php.&lt;br /&gt;
&lt;br /&gt;
Example of creation of new course with one page resource:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $generator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator(&#039;mod_page&#039;);&lt;br /&gt;
 $generator-&amp;gt;create_instance(array(&#039;course&#039;=&amp;gt;$course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating cohorts==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Since 2.4 there the data generator supports creation of new cohorts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $cohort = $this-&amp;gt;getDataGenerator()-&amp;gt;create_cohort();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simplified user enrolments==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Instead of standard enrolment API it is possible to use simplified method in data generator. It is intended to be used with self and manual enrolment plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid, &#039;manual&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other types of plugin==&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Any other type of plugin can have a generator. The generator class should extend component_generator_base, and then you can get an instance using $mygenerator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator($frankenstylecomponentname);&lt;br /&gt;
&lt;br /&gt;
For some types of plugin, like mod documented above, there may be a more specific class than component_generator_base to extend, like testing_module_generator. That will give a consistent set of method names to use. Otherwise, you can create whatever methods you like on your generator, to create the different things you need to work whith.&lt;br /&gt;
&lt;br /&gt;
=Long tests=&lt;br /&gt;
&lt;br /&gt;
All standard test should execute as fast as possible. Tests that take a loner time to execute (&amp;gt;10s) or are otherwise expensive (such as querying external servers that might be flooded by all dev machines) should be execute only when PHPUNIT_LONGTEST is true. This constant can be set in phpunit.xml or directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=Large test data=&lt;br /&gt;
See advanced_testcase::createXMLDataSet() and advanced_testcase::createCsvDataSet() and related functions there for easier ways to manage large test data sets within files rather than arrays in code. See [[PHPUnit_integration#Extra_methods]]&lt;br /&gt;
&lt;br /&gt;
=Testing sending of messages=&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
You can temporarily redirect all messages sent via message_send() to a message sink object. This allows developers to verify that the tested code is sending expected messages.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first disable the use of transactions and then redirect the messaging into a new message sink, you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
$sink = $this-&amp;gt;redirectMessages();&lt;br /&gt;
//... code that is sending messages&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(3, count($messages));&lt;br /&gt;
//.. test messages were generated in correct order with appropriate content&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Testing sending of emails=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
You can temporarily redirect emails sent via email_to_user() to a email message sink object. This allows developers to verify that the tested code is sending expected emails.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first unset &#039;noemailever&#039; setting and then redirect the emails into a new message sink where you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
unset_config(&#039;noemailever&#039;);&lt;br /&gt;
$sink = $this-&amp;gt;redirectEmails();&lt;br /&gt;
//... code that is sending email&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(1, count($messages));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Extra test settings=&lt;br /&gt;
&lt;br /&gt;
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.&lt;br /&gt;
&lt;br /&gt;
There are several ways how to inject your custom settings:&lt;br /&gt;
* define test setting constants in your phpunit.xml file&lt;br /&gt;
* define test setting constants in your config.php&lt;br /&gt;
&lt;br /&gt;
These constants may be then used in your test or plugin code.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[PHPUnit integration]]&lt;br /&gt;
* [[PHPUnit]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45363</id>
		<title>Writing PHPUnit tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45363"/>
		<updated>2014-06-19T00:03:48Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Sample plugin testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
Moodle PHPUnit integration is designed to allow easy adding of new tests. At the start of each test the state is automatically reset to fresh new installation (unless explicitly told not to reset).&lt;br /&gt;
&lt;br /&gt;
=Testcase classes=&lt;br /&gt;
&lt;br /&gt;
There are two basic test class that are supposed to used in all Moodle unit tests - basic_testcase and advanced_testcase. &#039;&#039;&#039;Please note it is strongly recommended to put only one testcase into each class file.&#039;&#039;&#039;&lt;br /&gt;
;basic_testcase : Very simple tests that do not modify database, dataroot or any PHP globals. It can be used for example when trying examples from the official PHPUnit tutorial.&lt;br /&gt;
;advanced_testcase : Enhanced testcase class enhanced for easy testing of Moodle code.&lt;br /&gt;
&lt;br /&gt;
There is a third testcase class that is specially designed for testing of our Moodle database layer, it should not be used for other purposes.&lt;br /&gt;
&lt;br /&gt;
== Assertions ==&lt;br /&gt;
&lt;br /&gt;
The complete list of assertions can be found in the [http://www.phpunit.de/manual/3.7/en/appendixes.assertions.html phpunit manual].&lt;br /&gt;
==Sample plugin testcase==&lt;br /&gt;
&lt;br /&gt;
PHPUnit tests are located in &amp;lt;code&amp;gt;tests/*_test.php&amp;lt;/code&amp;gt; files in your plugin, for example mod/myplugin/tests/sample_test.php, the file should contain only one class that extends &amp;lt;code&amp;gt;advanced_testcase&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_sample_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_adding() {&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, 1+2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[#Class and file naming rules|PHPUnit Integration]] for more information about naming of test case classes and files.&lt;br /&gt;
&lt;br /&gt;
==Inclusion of Moodle library files==&lt;br /&gt;
&lt;br /&gt;
If you want to include some Moodle library files you should always declare &#039;&#039;&#039;global $CFG&#039;&#039;&#039;. The reason is that testcase files may be included from non-moodle code which does not make the global $CFG available automatically.&lt;br /&gt;
&lt;br /&gt;
==Automatic state reset==&lt;br /&gt;
By default after each test Moodle database and dataroot is automatically reset to the original state which was present right after installation. make sure to use $this-&amp;gt;resetAfterTest() to indicate that the database or changes of standard global variables are expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_deleting() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;resetAfterTest(true);&lt;br /&gt;
         $DB-&amp;gt;delete_records(&#039;user&#039;);&lt;br /&gt;
         $this-&amp;gt;assertEmpty($DB-&amp;gt;get_records(&#039;user&#039;));&lt;br /&gt;
     }&lt;br /&gt;
     public function test_user_table_was_reset() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, $DB-&amp;gt;count_records(&#039;user&#039;, array()));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Generators=&lt;br /&gt;
&lt;br /&gt;
Tests that need to modify default installation may use generators to create new courses, users, etc. All examples on this page should be used from test methods of a test class derived from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
Note if you are using PHPUnit @dataProvider functions to provide parameters to unit tests, you can not use the data generator or change the user etc in the data provider function.&lt;br /&gt;
&lt;br /&gt;
==Creating users==&lt;br /&gt;
At the start of each test there are only two users present - guest and administrator. If you need to add more test accounts use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also specify properties of the user account, for example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user(array(&#039;email&#039;=&amp;gt;&#039;user1@example.com&#039;, &#039;username&#039;=&amp;gt;&#039;user1&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default no user is logged-in, use setUser() method to change current $USER value:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser($user1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Guest and admin accounts have a shortcut methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setGuestUser();&lt;br /&gt;
 $this-&amp;gt;setAdminUser();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Null can be used to set current user back to not-logged-in:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser(null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating course categories==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $category1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $category2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category(array(&#039;name&#039;=&amp;gt;&#039;Some subcategory&#039;, &#039;parent&#039;=&amp;gt;$category1-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating courses==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 &lt;br /&gt;
 $category = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $course2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course(array(&#039;name&#039;=&amp;gt;&#039;Some course&#039;, &#039;category&#039;=&amp;gt;$category-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating activities==&lt;br /&gt;
&lt;br /&gt;
Some activity plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php.&lt;br /&gt;
&lt;br /&gt;
Example of creation of new course with one page resource:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $generator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator(&#039;mod_page&#039;);&lt;br /&gt;
 $generator-&amp;gt;create_instance(array(&#039;course&#039;=&amp;gt;$course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating cohorts==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Since 2.4 there the data generator supports creation of new cohorts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $cohort = $this-&amp;gt;getDataGenerator()-&amp;gt;create_cohort();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simplified user enrolments==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Instead of standard enrolment API it is possible to use simplified method in data generator. It is intended to be used with self and manual enrolment plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid, &#039;manual&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other types of plugin==&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Any other type of plugin can have a generator. The generator class should extend component_generator_base, and then you can get an instance using $mygenerator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator($frankenstylecomponentname);&lt;br /&gt;
&lt;br /&gt;
For some types of plugin, like mod documented above, there may be a more specific class than component_generator_base to extend, like testing_module_generator. That will give a consistent set of method names to use. Otherwise, you can create whatever methods you like on your generator, to create the different things you need to work whith.&lt;br /&gt;
&lt;br /&gt;
=Long tests=&lt;br /&gt;
&lt;br /&gt;
All standard test should execute as fast as possible. Tests that take a loner time to execute (&amp;gt;10s) or are otherwise expensive (such as querying external servers that might be flooded by all dev machines) should be execute only when PHPUNIT_LONGTEST is true. This constant can be set in phpunit.xml or directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=Large test data=&lt;br /&gt;
See advanced_testcase::createXMLDataSet() and advanced_testcase::createCsvDataSet() and related functions there for easier ways to manage large test data sets within files rather than arrays in code. See [[PHPUnit_integration#Extra_methods]]&lt;br /&gt;
&lt;br /&gt;
=Testing sending of messages=&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
You can temporarily redirect all messages sent via message_send() to a message sink object. This allows developers to verify that the tested code is sending expected messages.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first disable the use of transactions and then redirect the messaging into a new message sink, you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
$sink = $this-&amp;gt;redirectMessages();&lt;br /&gt;
//... code that is sending messages&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(3, count($messages));&lt;br /&gt;
//.. test messages were generated in correct order with appropriate content&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Testing sending of emails=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
You can temporarily redirect emails sent via email_to_user() to a email message sink object. This allows developers to verify that the tested code is sending expected emails.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first unset &#039;noemailever&#039; setting and then redirect the emails into a new message sink where you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
unset_config(&#039;noemailever&#039;);&lt;br /&gt;
$sink = $this-&amp;gt;redirectEmails();&lt;br /&gt;
//... code that is sending email&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(1, count($messages));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Extra test settings=&lt;br /&gt;
&lt;br /&gt;
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.&lt;br /&gt;
&lt;br /&gt;
There are several ways how to inject your custom settings:&lt;br /&gt;
* define test setting constants in your phpunit.xml file&lt;br /&gt;
* define test setting constants in your config.php&lt;br /&gt;
&lt;br /&gt;
These constants may be then used in your test or plugin code.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[PHPUnit integration]]&lt;br /&gt;
* [[PHPUnit]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45362</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45362"/>
		<updated>2014-06-18T23:59:58Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Class and file naming rules */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
==Class and file naming rules==&lt;br /&gt;
The class names of all testcases need to be unique, Frankenstyle prefix is used to guarantee this. Since 2.6 it is possible to use automatic class loader when executing individual unit tests.&lt;br /&gt;
&lt;br /&gt;
* All test case classes start with Frankenstyle prefix, for example: &#039;&#039;&#039;mod_forum_&#039;&#039;&#039;, &#039;&#039;&#039;block_html_&#039;&#039;&#039;, &#039;&#039;&#039;core_&#039;&#039;&#039;.&lt;br /&gt;
* All test case classes end with &#039;&#039;&#039;_testcase&#039;&#039;&#039; suffix.&lt;br /&gt;
* File names are constructed from the class names - the Frankenstyle prefix is removed, suffix &#039;&#039;&#039;_testcase&#039;&#039;&#039; is replaced with &#039;&#039;&#039;_test&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
* class &#039;&#039;&#039;mod_forum_lib_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/mod/forum/tests/lib_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit mod_forum_lib_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
* class &#039;&#039;&#039;core_text_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/lib/texts/text_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit core_text_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests. The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/sample_basic_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/some_permission_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45361</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45361"/>
		<updated>2014-06-18T23:59:35Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Organisation of test files */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
==Class and file naming rules==&lt;br /&gt;
The class names of all testcases need to be unique, Frankenstyle prefix is used to guarantee this. Since 2.6 it is possible to use automatic class loader when executing individual unit tests.&lt;br /&gt;
&lt;br /&gt;
* All test case classes start with Frankenstyle prefix, for example: &#039;&#039;&#039;mod_forum_&#039;&#039;&#039;, &#039;&#039;&#039;block_html_&#039;&#039;&#039;, &#039;&#039;&#039;core_&#039;&#039;&#039;.&lt;br /&gt;
* All test case classes end with &#039;&#039;&#039;_testcase&#039; suffix.&lt;br /&gt;
* File names are constructed from the class names - the Frankenstyle prefix is removed, suffix &#039;&#039;&#039;_testcase&#039;&#039;&#039; is replaced with &#039;&#039;&#039;_test&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
* class &#039;&#039;&#039;mod_forum_lib_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/mod/forum/tests/lib_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit mod_forum_lib_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
* class &#039;&#039;&#039;core_text_testcase&#039;&#039;&#039; is expected in file &#039;&#039;&#039;/lib/texts/text_test.php&#039;&#039;&#039;, executed as &amp;lt;code&amp;gt;vendor/bin/phpunit core_text_testcase&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests. The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/sample_basic_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/some_permission_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45360</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45360"/>
		<updated>2014-06-18T23:51:26Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* advanced_testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests. The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/sample_basic_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/some_permission_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45359</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45359"/>
		<updated>2014-06-18T23:50:52Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* basic_testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests. The expected file name for this test case is &#039;&#039;&#039;/mod/myplugin/tests/sample_basic_test.php&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45358</id>
		<title>PHPUnit</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45358"/>
		<updated>2014-06-18T23:49:20Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Running a single test quickly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
=What is PHPUnit=&lt;br /&gt;
PHPUnit by Sebastian Bergmann is an advanced unit testing framework for PHP. It is installed as Composer dependency and is not part of Moodle installation. To run PHPUnit tests, you have to manually install it on your development computer or test server.&lt;br /&gt;
&lt;br /&gt;
Read the excellent guide at&lt;br /&gt;
* [http://phpunit.de/manual/current/en/index.html PHPUnit Manual]&lt;br /&gt;
&lt;br /&gt;
=Installation of PHPUnit via Composer=&lt;br /&gt;
&lt;br /&gt;
The installation procedure depends on your operating system.&lt;br /&gt;
* Install Composer dependency manager&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 curl -s https://getcomposer.org/installer | php&lt;br /&gt;
&lt;br /&gt;
On Windows go to https://getcomposer.org/download/ and download the Composer-Setup.exe file&lt;br /&gt;
&lt;br /&gt;
* Execute Composer installer&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 php composer.phar install --dev&lt;br /&gt;
&lt;br /&gt;
(If that gives you connection problems try...)&lt;br /&gt;
&lt;br /&gt;
 php composer.phar install --dev --prefer-source&lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
* On Windows if you are behind a proxy you will need to setup an environment variable called HTTP_PROXY with a value detailing your HTTP Proxy address and port before composer will correctly download files.&lt;br /&gt;
* You may be prompted for github credentials when installing composer dependencies.&lt;br /&gt;
** This is used to generate an personal access token to avoid being rate limited by github.&lt;br /&gt;
** If you have Two Factor Authentication enabled on your github account, or do not wish to supply your own credentials you will need to generate a token manually:&lt;br /&gt;
*** Visit https://github.com/settings/applications and request personal access token&lt;br /&gt;
*** Copy this token and add it to your [https://gist.github.com/andrewnicols/c5377ed25a9df1006ce1 ~/.composer/config.json]&lt;br /&gt;
** ( See [https://github.com/composer/composer/issues/2280 composer issue #2280] for further details of this bug.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [http://getcomposer.org/doc/00-intro.md Composer documentation]&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [[PHPUnit installation in Windows]]&lt;br /&gt;
* [[PHPUnit installation in OS X]]&lt;br /&gt;
&lt;br /&gt;
== Uninstalling previous PEAR based version ==&lt;br /&gt;
&lt;br /&gt;
Before using composer, this page used to suggest to install phpunit via PEAR. If you did so, you may wish to uninstall that package now. This should work:&lt;br /&gt;
&lt;br /&gt;
   $ pear uninstall phpunit/DbUnit&lt;br /&gt;
   $ pear uninstall phpunit/PHPUnit&lt;br /&gt;
&lt;br /&gt;
=Initialisation of test environment=&lt;br /&gt;
&lt;br /&gt;
Our PHPUnit integration requires a dedicated database and dataroot.  First, add a new dataroot directory and prefix into your config.php, you can find examples in config-dist.php (scroll down to &#039;Section 9&#039;).&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;phpunit_prefix = &#039;phpu_&#039;;&lt;br /&gt;
 $CFG-&amp;gt;phpunit_dataroot = &#039;/home/example/phpu_moodledata&#039;;&lt;br /&gt;
&lt;br /&gt;
If your system does not have a direct connection to the Internet, you also need to specify your proxy in config.php - even though you normally specify it by using the admin settings user interface. (If you do not use a proxy, you can skip this step.) Check the settings on the relevant admin settings page, or from the mdl_config table in your database, if you are unsure of the correct values.&lt;br /&gt;
 &lt;br /&gt;
 // Normal proxy settings&lt;br /&gt;
 $CFG-&amp;gt;proxyhost = &#039;wwwcache.example.org&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxyport = 80;&lt;br /&gt;
 $CFG-&amp;gt;proxytype = &#039;HTTP&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxybypass = &#039;localhost, 127.0.0.1, .example.org&#039;;&lt;br /&gt;
 // Omit the next lines if your proxy doesn&#039;t need a username/password:&lt;br /&gt;
 $CFG-&amp;gt;proxyuser = &#039;systemusername&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxypassword = &#039;systempassword&#039;;&lt;br /&gt;
&lt;br /&gt;
Then you need to initialise the test environment using following command.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 php admin/tool/phpunit/cli/init.php&lt;br /&gt;
&lt;br /&gt;
This command has to be repeated after any upgrade, plugin (un)installation or if you have added tests to a plugin you are developing:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; make sure that your php cli executable (or the one you want to use) is correctly on your path as the individual init scripts will call it repeatedly.&lt;br /&gt;
&lt;br /&gt;
=Test execution=&lt;br /&gt;
&lt;br /&gt;
To execute all test suites from main configuration file execute the &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; script from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 vendor/bin/phpunit&lt;br /&gt;
&lt;br /&gt;
The rest of examples uses &amp;lt;code&amp;gt;phpunit&amp;lt;/code&amp;gt;, please substitute it with &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; or create a shortcut in your dirroot.&lt;br /&gt;
&lt;br /&gt;
In IDEs, you may need to specify the path to the PHPUnit configuration file. Use the absolute path to &amp;lt;code&amp;gt;phpunit.xml&amp;lt;/code&amp;gt; from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is an alternative script for running of tests via web interface: &amp;lt;code&amp;gt;admin/tool/phpunit/webrunner.php&amp;lt;/code&amp;gt;. Use this as the last resort only when you cannot use the command-line interface on your test server. It will most probably break due to permissions problems if you try to execute it both from command-line and from webrunner. This feature is not officially supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===How to run only some tests===&lt;br /&gt;
&lt;br /&gt;
==== Running a single test quickly ====&lt;br /&gt;
&lt;br /&gt;
The fastest way to run a single test is:&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit my_test_class_name my/tests/filename.php&lt;br /&gt;
&lt;br /&gt;
This is faster than other methods because it avoids the need to search for the test file, but you should be careful because it may be possible to run tests this way which are not included in the normal run. If you use this method, do at least one full test run (or --group run, as below) to ensure the test can be found.&lt;br /&gt;
&lt;br /&gt;
Please note the path name is optional if the testcase class and file names are standardised as described in [[Writing PHPUnit tests]].&lt;br /&gt;
&lt;br /&gt;
==== Using the @group annotation ====&lt;br /&gt;
&lt;br /&gt;
If you add annotations like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for {@link stack_cas_keyval}.&lt;br /&gt;
 * @group qtype_stack&lt;br /&gt;
 */&lt;br /&gt;
class qtype_stack_cas_keyval_exception_testcase extends basic_testcase {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to all the classes in your plugin, then you can run just the tests for your plugin by doing&lt;br /&gt;
&lt;br /&gt;
 phpunit --group qtype_stack&lt;br /&gt;
&lt;br /&gt;
Therefore, it is suggested that you annotate all your tests with the Frankenstyle name of your plugin.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple phpunit.xml files ====&lt;br /&gt;
&lt;br /&gt;
It&#039;s easy to create alternative phpunit.xml files defining which tests must be run together. For reference, take a look to the default /phpunit.xml available in your base directory once the testing environment has been initialised. After creating the custom file you will be able to run those tests with&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c path/to/your/alternative/phpunit/file.xml&lt;br /&gt;
&lt;br /&gt;
Also, for commodity, you can use this command:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/phpunit/cli/util.php --buildcomponentconfigs&lt;br /&gt;
&lt;br /&gt;
It will, automatically, create one valid phpunit.xml file within each component (plugin or subsystem) and other important directories, so later you will be able to execute tests like&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c mod/forum[/phpunit.xml]  // Note that it&#039;s not needed to specify the name of the file (if it is &#039;phpunit.xml&#039;).&lt;br /&gt;
 vendor/bin/phpunit -c question&lt;br /&gt;
 vendor/bin/phpunit -c question/type/calculated&lt;br /&gt;
 vendor/bin/phpunit -c backup&lt;br /&gt;
 vendor/bin/phpunit -c lib/dml&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
or, also&lt;br /&gt;
&lt;br /&gt;
 cd directory/with/phpunit.xml&lt;br /&gt;
 phpunit&lt;br /&gt;
&lt;br /&gt;
=External test resources=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
By default Moodle phpunit tests contact http://download.moodle.org server when testing curl related functionality. Optionally you may checkout a local copy of the test scripts and access it instead:&lt;br /&gt;
&lt;br /&gt;
# clone https://github.com/moodlehq/moodle-exttests to web directory&lt;br /&gt;
# add to your config.php or modify phpunit.xml file &amp;lt;code php&amp;gt;define(&#039;TEST_EXTERNAL_FILES_HTTP_URL&#039;, &#039;http://localhost/moodle-exttests&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Writing new tests=&lt;br /&gt;
* read [http://www.phpunit.de/manual/current/en/ official PHPUnit online documentation]&lt;br /&gt;
* see [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
=Conversion of existing SimpleTests=&lt;br /&gt;
* see [[SimpleTest conversion]]&lt;br /&gt;
&lt;br /&gt;
=PHPUnit support in IDEs=&lt;br /&gt;
&lt;br /&gt;
* [http://www.phpsrc.org/projects/pti-phpunit/wiki/ Eclipse PHP Tool Integration]&lt;br /&gt;
* [http://blog.jetbrains.com/webide/2009/12/phpunit-support/ PHPStorm IDE]&lt;br /&gt;
* [http://netbeans.org/kb/docs/php/phpunit.html Netbeans]&lt;br /&gt;
&lt;br /&gt;
=Common Unit Test Problems=&lt;br /&gt;
[[Common unit test problems]]&lt;br /&gt;
&lt;br /&gt;
=Performance=&lt;br /&gt;
&lt;br /&gt;
A typical run of full PHPUnit tests for Moodle 2.7 takes 10-20 minutes depending on the machine. If tests run slowly for you:&lt;br /&gt;
&lt;br /&gt;
* Ensure you are using a database and filesystem running on the same machine that is running the tests (not on a remote server).&lt;br /&gt;
* Apply developer-only performance settings to your database: [[Postgres Tuning For Developers]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45357</id>
		<title>PHPUnit</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45357"/>
		<updated>2014-06-18T23:48:39Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Running a single test quickly */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
=What is PHPUnit=&lt;br /&gt;
PHPUnit by Sebastian Bergmann is an advanced unit testing framework for PHP. It is installed as Composer dependency and is not part of Moodle installation. To run PHPUnit tests, you have to manually install it on your development computer or test server.&lt;br /&gt;
&lt;br /&gt;
Read the excellent guide at&lt;br /&gt;
* [http://phpunit.de/manual/current/en/index.html PHPUnit Manual]&lt;br /&gt;
&lt;br /&gt;
=Installation of PHPUnit via Composer=&lt;br /&gt;
&lt;br /&gt;
The installation procedure depends on your operating system.&lt;br /&gt;
* Install Composer dependency manager&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 curl -s https://getcomposer.org/installer | php&lt;br /&gt;
&lt;br /&gt;
On Windows go to https://getcomposer.org/download/ and download the Composer-Setup.exe file&lt;br /&gt;
&lt;br /&gt;
* Execute Composer installer&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 php composer.phar install --dev&lt;br /&gt;
&lt;br /&gt;
(If that gives you connection problems try...)&lt;br /&gt;
&lt;br /&gt;
 php composer.phar install --dev --prefer-source&lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
* On Windows if you are behind a proxy you will need to setup an environment variable called HTTP_PROXY with a value detailing your HTTP Proxy address and port before composer will correctly download files.&lt;br /&gt;
* You may be prompted for github credentials when installing composer dependencies.&lt;br /&gt;
** This is used to generate an personal access token to avoid being rate limited by github.&lt;br /&gt;
** If you have Two Factor Authentication enabled on your github account, or do not wish to supply your own credentials you will need to generate a token manually:&lt;br /&gt;
*** Visit https://github.com/settings/applications and request personal access token&lt;br /&gt;
*** Copy this token and add it to your [https://gist.github.com/andrewnicols/c5377ed25a9df1006ce1 ~/.composer/config.json]&lt;br /&gt;
** ( See [https://github.com/composer/composer/issues/2280 composer issue #2280] for further details of this bug.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [http://getcomposer.org/doc/00-intro.md Composer documentation]&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [[PHPUnit installation in Windows]]&lt;br /&gt;
* [[PHPUnit installation in OS X]]&lt;br /&gt;
&lt;br /&gt;
== Uninstalling previous PEAR based version ==&lt;br /&gt;
&lt;br /&gt;
Before using composer, this page used to suggest to install phpunit via PEAR. If you did so, you may wish to uninstall that package now. This should work:&lt;br /&gt;
&lt;br /&gt;
   $ pear uninstall phpunit/DbUnit&lt;br /&gt;
   $ pear uninstall phpunit/PHPUnit&lt;br /&gt;
&lt;br /&gt;
=Initialisation of test environment=&lt;br /&gt;
&lt;br /&gt;
Our PHPUnit integration requires a dedicated database and dataroot.  First, add a new dataroot directory and prefix into your config.php, you can find examples in config-dist.php (scroll down to &#039;Section 9&#039;).&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;phpunit_prefix = &#039;phpu_&#039;;&lt;br /&gt;
 $CFG-&amp;gt;phpunit_dataroot = &#039;/home/example/phpu_moodledata&#039;;&lt;br /&gt;
&lt;br /&gt;
If your system does not have a direct connection to the Internet, you also need to specify your proxy in config.php - even though you normally specify it by using the admin settings user interface. (If you do not use a proxy, you can skip this step.) Check the settings on the relevant admin settings page, or from the mdl_config table in your database, if you are unsure of the correct values.&lt;br /&gt;
 &lt;br /&gt;
 // Normal proxy settings&lt;br /&gt;
 $CFG-&amp;gt;proxyhost = &#039;wwwcache.example.org&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxyport = 80;&lt;br /&gt;
 $CFG-&amp;gt;proxytype = &#039;HTTP&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxybypass = &#039;localhost, 127.0.0.1, .example.org&#039;;&lt;br /&gt;
 // Omit the next lines if your proxy doesn&#039;t need a username/password:&lt;br /&gt;
 $CFG-&amp;gt;proxyuser = &#039;systemusername&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxypassword = &#039;systempassword&#039;;&lt;br /&gt;
&lt;br /&gt;
Then you need to initialise the test environment using following command.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 php admin/tool/phpunit/cli/init.php&lt;br /&gt;
&lt;br /&gt;
This command has to be repeated after any upgrade, plugin (un)installation or if you have added tests to a plugin you are developing:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; make sure that your php cli executable (or the one you want to use) is correctly on your path as the individual init scripts will call it repeatedly.&lt;br /&gt;
&lt;br /&gt;
=Test execution=&lt;br /&gt;
&lt;br /&gt;
To execute all test suites from main configuration file execute the &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; script from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 vendor/bin/phpunit&lt;br /&gt;
&lt;br /&gt;
The rest of examples uses &amp;lt;code&amp;gt;phpunit&amp;lt;/code&amp;gt;, please substitute it with &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; or create a shortcut in your dirroot.&lt;br /&gt;
&lt;br /&gt;
In IDEs, you may need to specify the path to the PHPUnit configuration file. Use the absolute path to &amp;lt;code&amp;gt;phpunit.xml&amp;lt;/code&amp;gt; from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is an alternative script for running of tests via web interface: &amp;lt;code&amp;gt;admin/tool/phpunit/webrunner.php&amp;lt;/code&amp;gt;. Use this as the last resort only when you cannot use the command-line interface on your test server. It will most probably break due to permissions problems if you try to execute it both from command-line and from webrunner. This feature is not officially supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===How to run only some tests===&lt;br /&gt;
&lt;br /&gt;
==== Running a single test quickly ====&lt;br /&gt;
&lt;br /&gt;
The fastest way to run a single test is:&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit my_test_class_name my/tests/filename.php&lt;br /&gt;
&lt;br /&gt;
This is faster than other methods because it avoids the need to search for the test file, but you should be careful because it may be possible to run tests this way which are not included in the normal run. If you use this method, do at least one full test run (or --group run, as below) to ensure the test can be found.&lt;br /&gt;
&lt;br /&gt;
Please note the path name is optional if the testcase class and file names are standardised as described in [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
==== Using the @group annotation ====&lt;br /&gt;
&lt;br /&gt;
If you add annotations like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for {@link stack_cas_keyval}.&lt;br /&gt;
 * @group qtype_stack&lt;br /&gt;
 */&lt;br /&gt;
class qtype_stack_cas_keyval_exception_testcase extends basic_testcase {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to all the classes in your plugin, then you can run just the tests for your plugin by doing&lt;br /&gt;
&lt;br /&gt;
 phpunit --group qtype_stack&lt;br /&gt;
&lt;br /&gt;
Therefore, it is suggested that you annotate all your tests with the Frankenstyle name of your plugin.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple phpunit.xml files ====&lt;br /&gt;
&lt;br /&gt;
It&#039;s easy to create alternative phpunit.xml files defining which tests must be run together. For reference, take a look to the default /phpunit.xml available in your base directory once the testing environment has been initialised. After creating the custom file you will be able to run those tests with&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c path/to/your/alternative/phpunit/file.xml&lt;br /&gt;
&lt;br /&gt;
Also, for commodity, you can use this command:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/phpunit/cli/util.php --buildcomponentconfigs&lt;br /&gt;
&lt;br /&gt;
It will, automatically, create one valid phpunit.xml file within each component (plugin or subsystem) and other important directories, so later you will be able to execute tests like&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c mod/forum[/phpunit.xml]  // Note that it&#039;s not needed to specify the name of the file (if it is &#039;phpunit.xml&#039;).&lt;br /&gt;
 vendor/bin/phpunit -c question&lt;br /&gt;
 vendor/bin/phpunit -c question/type/calculated&lt;br /&gt;
 vendor/bin/phpunit -c backup&lt;br /&gt;
 vendor/bin/phpunit -c lib/dml&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
or, also&lt;br /&gt;
&lt;br /&gt;
 cd directory/with/phpunit.xml&lt;br /&gt;
 phpunit&lt;br /&gt;
&lt;br /&gt;
=External test resources=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
By default Moodle phpunit tests contact http://download.moodle.org server when testing curl related functionality. Optionally you may checkout a local copy of the test scripts and access it instead:&lt;br /&gt;
&lt;br /&gt;
# clone https://github.com/moodlehq/moodle-exttests to web directory&lt;br /&gt;
# add to your config.php or modify phpunit.xml file &amp;lt;code php&amp;gt;define(&#039;TEST_EXTERNAL_FILES_HTTP_URL&#039;, &#039;http://localhost/moodle-exttests&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Writing new tests=&lt;br /&gt;
* read [http://www.phpunit.de/manual/current/en/ official PHPUnit online documentation]&lt;br /&gt;
* see [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
=Conversion of existing SimpleTests=&lt;br /&gt;
* see [[SimpleTest conversion]]&lt;br /&gt;
&lt;br /&gt;
=PHPUnit support in IDEs=&lt;br /&gt;
&lt;br /&gt;
* [http://www.phpsrc.org/projects/pti-phpunit/wiki/ Eclipse PHP Tool Integration]&lt;br /&gt;
* [http://blog.jetbrains.com/webide/2009/12/phpunit-support/ PHPStorm IDE]&lt;br /&gt;
* [http://netbeans.org/kb/docs/php/phpunit.html Netbeans]&lt;br /&gt;
&lt;br /&gt;
=Common Unit Test Problems=&lt;br /&gt;
[[Common unit test problems]]&lt;br /&gt;
&lt;br /&gt;
=Performance=&lt;br /&gt;
&lt;br /&gt;
A typical run of full PHPUnit tests for Moodle 2.7 takes 10-20 minutes depending on the machine. If tests run slowly for you:&lt;br /&gt;
&lt;br /&gt;
* Ensure you are using a database and filesystem running on the same machine that is running the tests (not on a remote server).&lt;br /&gt;
* Apply developer-only performance settings to your database: [[Postgres Tuning For Developers]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45356</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45356"/>
		<updated>2014-06-18T23:48:07Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* advanced_testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45355</id>
		<title>PHPUnit integration</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit_integration&amp;diff=45355"/>
		<updated>2014-06-18T23:47:42Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* basic_testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Moodle PHPUnit integration was created to simplify using of PHPUnit framework in Moodle. It consists of specialised bootstrap script, utility scripts that initialise testing environment and highly optimised custom test case classes that handle automatic global state resetting after test that includes global variables, database rollback and purging of dataroot. We also try to bridge the gap between the design and coding style of Moodle and PHPUnit.&lt;br /&gt;
&lt;br /&gt;
Most of the documentation at http://www.phpunit.de/manual/3.6/en/index.html is relevant to Moodle PHPUnit integration, exceptions and additions are described bellow.&lt;br /&gt;
&lt;br /&gt;
=Definitions=&lt;br /&gt;
These definitions may differ in each testing framework or programming language. The definitions here should be valid for PHPUnit framework with our Moodle tweaks.&lt;br /&gt;
&lt;br /&gt;
;Test suite: is a collection of test cases or other suites usually related to one area of the product. It is defined in PHPUnit configuration files (phpunit.xml by default).&lt;br /&gt;
&lt;br /&gt;
;Test file: is a file with *_test.php name which contains a test case. (*_Test.php in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test case: is a class with test methods. Moodle tests extend basic_testcase or advanced_testcase. (PHPUnit_Framework_TestCase in PHPUnit)&lt;br /&gt;
&lt;br /&gt;
;Test: is a public method starting with &amp;quot;test_&amp;quot; prefix defined in test case class. It is the implementation of the test procedure.&lt;br /&gt;
&lt;br /&gt;
;Assertion: is the actual comparison of expected and actual behaviour of the tested code.&lt;br /&gt;
&lt;br /&gt;
=Organisation of test files=&lt;br /&gt;
All testing related files are stored in &amp;lt;code&amp;gt;/tests/&amp;lt;/code&amp;gt; subdirectories:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/*_test.php&amp;lt;/code&amp;gt; are PHPUnit test files&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/fixtures/&amp;lt;/code&amp;gt; contains auxiliary files used in tests&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/performance/&amp;lt;/code&amp;gt; is reserved for performance testing scripts&lt;br /&gt;
* &amp;lt;code&amp;gt;.../tests/other/&amp;lt;/code&amp;gt; is used for everything else that does not fit&lt;br /&gt;
&lt;br /&gt;
=basic_testcase=&lt;br /&gt;
&#039;&#039;basic_testcase&#039;&#039; is useful for simple tests that do not modify database or global variables. If something accidentally changes global state the test fails. This test case class is nearly identical to PHPUnit_Framework_TestCase used in PHPUnit documentation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class mod_myplugin_sample_basic_testcase extends basic_testcase {&lt;br /&gt;
    public function test_equals() {&lt;br /&gt;
        $a = 1 + 2;&lt;br /&gt;
        $this-&amp;gt;assertEquals(3, $a);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are no extra methods that could be used in tests&lt;br /&gt;
&lt;br /&gt;
=advanced_testcase=&lt;br /&gt;
By default each test starts with fresh new moodle installation. Test may modify database content, files or global variables. It is possible to use data generators to create new course, categories, module instances and other objects, alternatively table data can be preloaded from XML or CSV files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
&amp;lt;?php&lt;br /&gt;
&lt;br /&gt;
class some_permission_testcase extends advanced_testcase {&lt;br /&gt;
    public function test_isadmin() {&lt;br /&gt;
        global $DB;&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAfterTest(true);          // reset all changes automatically after this test&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());   // by default no user is logged-in&lt;br /&gt;
        $this-&amp;gt;setUser(2);                    // switch $USER&lt;br /&gt;
        $this-&amp;gt;assertTrue(is_siteadmin());    // admin is logged-in now&lt;br /&gt;
&lt;br /&gt;
        $DB-&amp;gt;delete_records(&#039;user&#039;, array()); // lets do something crazy&lt;br /&gt;
&lt;br /&gt;
        $this-&amp;gt;resetAllData();                // that was not a good idea, let&#039;s go back&lt;br /&gt;
        $this-&amp;gt;assertTrue($admin = $DB-&amp;gt;record_exists(&#039;user&#039;, array(&#039;id&#039;=&amp;gt;2)));&lt;br /&gt;
        $this-&amp;gt;assertFalse(is_siteadmin());&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Extra methods==&lt;br /&gt;
; resetAfterTest(bool) : true means reset automatically after test, false means keep changes to next test method, default null means detect changes&lt;br /&gt;
; resetAllData() : reset global state in the middle of a test&lt;br /&gt;
; setAdminUser() : set current $USER as admin&lt;br /&gt;
; setGuestUser() : set current $USER as guest&lt;br /&gt;
; setUser() : set current $USER to a specific user - use getDataGenerator() to create one&lt;br /&gt;
; getDataGenerator() : returns data generator instance - use if you need to add new courses, users, etc.&lt;br /&gt;
; preventResetByRollback() : terminates active transactions, useful only when test contains own database transaction handling&lt;br /&gt;
; createXXXDataSet() : creates in memory structure of database table contents, used in loadDataSet() (eg: createXMLDataSet(), createCsvDataSet(), createFlatXMLDataSet())&lt;br /&gt;
; loadDataSet() : bulk loading of table contents&lt;br /&gt;
; getDebuggingMessages() : Return debugging messages from the current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; resetDebugging() : Clear all previous debugging messages in current test. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingCalled() : Assert that exactly debugging was just called once. (Moodle 2.4 and upwards)&lt;br /&gt;
; assertDebuggingNotCalled() : Assert no debugging happened. (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing sending of messages|redirectMessages()]]: Captures ongoing messages for later testing (Moodle 2.4 and upwards)&lt;br /&gt;
; [[Writing PHPUnit tests#Testing_sending_of_emails|redirectEmails()]]: Captures ongoing emails for later testing (Moodle 2.6 and upwards)&lt;br /&gt;
&lt;br /&gt;
==Restrictions==&lt;br /&gt;
* it is not possible to modify database structure such as create new table or drop columns from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
=Moodle specific features=&lt;br /&gt;
* detection of global state changes - helps with detection of unintended changes in database&lt;br /&gt;
* highly optimised global state reset&lt;br /&gt;
* dataset loading - this feature is copied from PHPUnit database testcases&lt;br /&gt;
* automatic generation of phpunit.xml - init script builds list of plugin testcases&lt;br /&gt;
* database driver testing class - used for functional DB tests&lt;br /&gt;
* SimpleTest emulation class - helps with migration of old tests&lt;br /&gt;
* debugging() interception - enables to control and test any expected debug output. (Moodle 2.4 and upwards)&lt;br /&gt;
&lt;br /&gt;
=Limitations=&lt;br /&gt;
* no Selenium support&lt;br /&gt;
* no support for PHPUnit_Extensions_Database_TestCase - it is possible to use data set loader only&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45354</id>
		<title>Writing PHPUnit tests</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Writing_PHPUnit_tests&amp;diff=45354"/>
		<updated>2014-06-18T23:45:04Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Sample plugin testcase */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
Moodle PHPUnit integration is designed to allow easy adding of new tests. At the start of each test the state is automatically reset to fresh new installation (unless explicitly told not to reset).&lt;br /&gt;
&lt;br /&gt;
=Testcase classes=&lt;br /&gt;
&lt;br /&gt;
There are two basic test class that are supposed to used in all Moodle unit tests - basic_testcase and advanced_testcase. &#039;&#039;&#039;Please note it is strongly recommended to put only one testcase into each class file.&#039;&#039;&#039;&lt;br /&gt;
;basic_testcase : Very simple tests that do not modify database, dataroot or any PHP globals. It can be used for example when trying examples from the official PHPUnit tutorial.&lt;br /&gt;
;advanced_testcase : Enhanced testcase class enhanced for easy testing of Moodle code.&lt;br /&gt;
&lt;br /&gt;
There is a third testcase class that is specially designed for testing of our Moodle database layer, it should not be used for other purposes.&lt;br /&gt;
&lt;br /&gt;
== Assertions ==&lt;br /&gt;
&lt;br /&gt;
The complete list of assertions can be found in the [http://www.phpunit.de/manual/3.7/en/appendixes.assertions.html phpunit manual].&lt;br /&gt;
==Sample plugin testcase==&lt;br /&gt;
&lt;br /&gt;
PHPUnit tests are located in &amp;lt;code&amp;gt;tests/*_test.php&amp;lt;/code&amp;gt; files in your plugin, for example mod/myplugin/tests/sample_test.php, the file should contain only one class that extends &amp;lt;code&amp;gt;advanced_testcase&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_sample_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_adding() {&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, 1+2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Inclusion of Moodle library files==&lt;br /&gt;
&lt;br /&gt;
If you want to include some Moodle library files you should always declare &#039;&#039;&#039;global $CFG&#039;&#039;&#039;. The reason is that testcase files may be included from non-moodle code which does not make the global $CFG available automatically.&lt;br /&gt;
&lt;br /&gt;
==Automatic state reset==&lt;br /&gt;
By default after each test Moodle database and dataroot is automatically reset to the original state which was present right after installation. make sure to use $this-&amp;gt;resetAfterTest() to indicate that the database or changes of standard global variables are expected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 class mod_myplugin_testcase extends advanced_testcase {&lt;br /&gt;
     public function test_deleting() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;resetAfterTest(true);&lt;br /&gt;
         $DB-&amp;gt;delete_records(&#039;user&#039;);&lt;br /&gt;
         $this-&amp;gt;assertEmpty($DB-&amp;gt;get_records(&#039;user&#039;));&lt;br /&gt;
     }&lt;br /&gt;
     public function test_user_table_was_reset() {&lt;br /&gt;
         global $DB;&lt;br /&gt;
         $this-&amp;gt;assertEquals(2, $DB-&amp;gt;count_records(&#039;user&#039;, array()));&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Generators=&lt;br /&gt;
&lt;br /&gt;
Tests that need to modify default installation may use generators to create new courses, users, etc. All examples on this page should be used from test methods of a test class derived from advanced_testcase.&lt;br /&gt;
&lt;br /&gt;
Note if you are using PHPUnit @dataProvider functions to provide parameters to unit tests, you can not use the data generator or change the user etc in the data provider function.&lt;br /&gt;
&lt;br /&gt;
==Creating users==&lt;br /&gt;
At the start of each test there are only two users present - guest and administrator. If you need to add more test accounts use:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also specify properties of the user account, for example:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $user1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_user(array(&#039;email&#039;=&amp;gt;&#039;user1@example.com&#039;, &#039;username&#039;=&amp;gt;&#039;user1&#039;));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
By default no user is logged-in, use setUser() method to change current $USER value:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser($user1);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Guest and admin accounts have a shortcut methods:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setGuestUser();&lt;br /&gt;
 $this-&amp;gt;setAdminUser();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Null can be used to set current user back to not-logged-in:&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $this-&amp;gt;setUser(null);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating course categories==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $category1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $category2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category(array(&#039;name&#039;=&amp;gt;&#039;Some subcategory&#039;, &#039;parent&#039;=&amp;gt;$category1-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating courses==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course1 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 &lt;br /&gt;
 $category = $this-&amp;gt;getDataGenerator()-&amp;gt;create_category();&lt;br /&gt;
 $course2 = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course(array(&#039;name&#039;=&amp;gt;&#039;Some course&#039;, &#039;category&#039;=&amp;gt;$category-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating activities==&lt;br /&gt;
&lt;br /&gt;
Some activity plugins include instance generators. The generator class are defined in plugindirectory/tests/generator/lib.php.&lt;br /&gt;
&lt;br /&gt;
Example of creation of new course with one page resource:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $course = $this-&amp;gt;getDataGenerator()-&amp;gt;create_course();&lt;br /&gt;
 $generator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator(&#039;mod_page&#039;);&lt;br /&gt;
 $generator-&amp;gt;create_instance(array(&#039;course&#039;=&amp;gt;$course-&amp;gt;id));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Creating cohorts==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Since 2.4 there the data generator supports creation of new cohorts.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
 $cohort = $this-&amp;gt;getDataGenerator()-&amp;gt;create_cohort();&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Simplified user enrolments==&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
Instead of standard enrolment API it is possible to use simplified method in data generator. It is intended to be used with self and manual enrolment plugins.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid);&lt;br /&gt;
$this-&amp;gt;getDataGenerator()-&amp;gt;enrol_user($userid, $courseid, $teacherroleid, &#039;manual&#039;);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Other types of plugin==&lt;br /&gt;
{{Moodle 2.5}}&lt;br /&gt;
Any other type of plugin can have a generator. The generator class should extend component_generator_base, and then you can get an instance using $mygenerator = $this-&amp;gt;getDataGenerator()-&amp;gt;get_plugin_generator($frankenstylecomponentname);&lt;br /&gt;
&lt;br /&gt;
For some types of plugin, like mod documented above, there may be a more specific class than component_generator_base to extend, like testing_module_generator. That will give a consistent set of method names to use. Otherwise, you can create whatever methods you like on your generator, to create the different things you need to work whith.&lt;br /&gt;
&lt;br /&gt;
=Long tests=&lt;br /&gt;
&lt;br /&gt;
All standard test should execute as fast as possible. Tests that take a loner time to execute (&amp;gt;10s) or are otherwise expensive (such as querying external servers that might be flooded by all dev machines) should be execute only when PHPUNIT_LONGTEST is true. This constant can be set in phpunit.xml or directly in config.php.&lt;br /&gt;
&lt;br /&gt;
=Large test data=&lt;br /&gt;
See advanced_testcase::createXMLDataSet() and advanced_testcase::createCsvDataSet() and related functions there for easier ways to manage large test data sets within files rather than arrays in code. See [[PHPUnit_integration#Extra_methods]]&lt;br /&gt;
&lt;br /&gt;
=Testing sending of messages=&lt;br /&gt;
{{Moodle 2.4}}&lt;br /&gt;
You can temporarily redirect all messages sent via message_send() to a message sink object. This allows developers to verify that the tested code is sending expected messages.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first disable the use of transactions and then redirect the messaging into a new message sink, you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
$this-&amp;gt;preventResetByRollback();&lt;br /&gt;
$sink = $this-&amp;gt;redirectMessages();&lt;br /&gt;
//... code that is sending messages&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(3, count($messages));&lt;br /&gt;
//.. test messages were generated in correct order with appropriate content&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Testing sending of emails=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
You can temporarily redirect emails sent via email_to_user() to a email message sink object. This allows developers to verify that the tested code is sending expected emails.&lt;br /&gt;
&lt;br /&gt;
To test code using messaging first unset &#039;noemailever&#039; setting and then redirect the emails into a new message sink where you can inspect the results later.&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
unset_config(&#039;noemailever&#039;);&lt;br /&gt;
$sink = $this-&amp;gt;redirectEmails();&lt;br /&gt;
//... code that is sending email&lt;br /&gt;
$messages = $sink-&amp;gt;get_messages();&lt;br /&gt;
$this-&amp;gt;assertEquals(1, count($messages));&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Extra test settings=&lt;br /&gt;
&lt;br /&gt;
Usually the test should not interact with any external systems and it should work the same on all systems. But sometimes you need to specify some option for connection to external systems or system configuration. It is intentionally not possible to use $CFG settings from config.php.&lt;br /&gt;
&lt;br /&gt;
There are several ways how to inject your custom settings:&lt;br /&gt;
* define test setting constants in your phpunit.xml file&lt;br /&gt;
* define test setting constants in your config.php&lt;br /&gt;
&lt;br /&gt;
These constants may be then used in your test or plugin code.&lt;br /&gt;
&lt;br /&gt;
=See also=&lt;br /&gt;
* [[PHPUnit integration]]&lt;br /&gt;
* [[PHPUnit]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45353</id>
		<title>PHPUnit</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45353"/>
		<updated>2014-06-18T23:42:05Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Using the @group annotation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
=What is PHPUnit=&lt;br /&gt;
PHPUnit by Sebastian Bergmann is an advanced unit testing framework for PHP. It is installed as Composer dependency and is not part of Moodle installation. To run PHPUnit tests, you have to manually install it on your development computer or test server.&lt;br /&gt;
&lt;br /&gt;
Read the excellent guide at&lt;br /&gt;
* [http://phpunit.de/manual/current/en/index.html PHPUnit Manual]&lt;br /&gt;
&lt;br /&gt;
=Installation of PHPUnit via Composer=&lt;br /&gt;
&lt;br /&gt;
The installation procedure depends on your operating system.&lt;br /&gt;
* Install Composer dependency manager&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 curl -s https://getcomposer.org/installer | php&lt;br /&gt;
&lt;br /&gt;
On Windows go to https://getcomposer.org/download/ and download the Composer-Setup.exe file&lt;br /&gt;
&lt;br /&gt;
* Execute Composer installer&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 php composer.phar install --dev&lt;br /&gt;
&lt;br /&gt;
(If that gives you connection problems try...)&lt;br /&gt;
&lt;br /&gt;
 php composer.phar install --dev --prefer-source&lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
* On Windows if you are behind a proxy you will need to setup an environment variable called HTTP_PROXY with a value detailing your HTTP Proxy address and port before composer will correctly download files.&lt;br /&gt;
* You may be prompted for github credentials when installing composer dependencies.&lt;br /&gt;
** This is used to generate an personal access token to avoid being rate limited by github.&lt;br /&gt;
** If you have Two Factor Authentication enabled on your github account, or do not wish to supply your own credentials you will need to generate a token manually:&lt;br /&gt;
*** Visit https://github.com/settings/applications and request personal access token&lt;br /&gt;
*** Copy this token and add it to your [https://gist.github.com/andrewnicols/c5377ed25a9df1006ce1 ~/.composer/config.json]&lt;br /&gt;
** ( See [https://github.com/composer/composer/issues/2280 composer issue #2280] for further details of this bug.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [http://getcomposer.org/doc/00-intro.md Composer documentation]&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [[PHPUnit installation in Windows]]&lt;br /&gt;
* [[PHPUnit installation in OS X]]&lt;br /&gt;
&lt;br /&gt;
== Uninstalling previous PEAR based version ==&lt;br /&gt;
&lt;br /&gt;
Before using composer, this page used to suggest to install phpunit via PEAR. If you did so, you may wish to uninstall that package now. This should work:&lt;br /&gt;
&lt;br /&gt;
   $ pear uninstall phpunit/DbUnit&lt;br /&gt;
   $ pear uninstall phpunit/PHPUnit&lt;br /&gt;
&lt;br /&gt;
=Initialisation of test environment=&lt;br /&gt;
&lt;br /&gt;
Our PHPUnit integration requires a dedicated database and dataroot.  First, add a new dataroot directory and prefix into your config.php, you can find examples in config-dist.php (scroll down to &#039;Section 9&#039;).&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;phpunit_prefix = &#039;phpu_&#039;;&lt;br /&gt;
 $CFG-&amp;gt;phpunit_dataroot = &#039;/home/example/phpu_moodledata&#039;;&lt;br /&gt;
&lt;br /&gt;
If your system does not have a direct connection to the Internet, you also need to specify your proxy in config.php - even though you normally specify it by using the admin settings user interface. (If you do not use a proxy, you can skip this step.) Check the settings on the relevant admin settings page, or from the mdl_config table in your database, if you are unsure of the correct values.&lt;br /&gt;
 &lt;br /&gt;
 // Normal proxy settings&lt;br /&gt;
 $CFG-&amp;gt;proxyhost = &#039;wwwcache.example.org&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxyport = 80;&lt;br /&gt;
 $CFG-&amp;gt;proxytype = &#039;HTTP&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxybypass = &#039;localhost, 127.0.0.1, .example.org&#039;;&lt;br /&gt;
 // Omit the next lines if your proxy doesn&#039;t need a username/password:&lt;br /&gt;
 $CFG-&amp;gt;proxyuser = &#039;systemusername&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxypassword = &#039;systempassword&#039;;&lt;br /&gt;
&lt;br /&gt;
Then you need to initialise the test environment using following command.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 php admin/tool/phpunit/cli/init.php&lt;br /&gt;
&lt;br /&gt;
This command has to be repeated after any upgrade, plugin (un)installation or if you have added tests to a plugin you are developing:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; make sure that your php cli executable (or the one you want to use) is correctly on your path as the individual init scripts will call it repeatedly.&lt;br /&gt;
&lt;br /&gt;
=Test execution=&lt;br /&gt;
&lt;br /&gt;
To execute all test suites from main configuration file execute the &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; script from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 vendor/bin/phpunit&lt;br /&gt;
&lt;br /&gt;
The rest of examples uses &amp;lt;code&amp;gt;phpunit&amp;lt;/code&amp;gt;, please substitute it with &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; or create a shortcut in your dirroot.&lt;br /&gt;
&lt;br /&gt;
In IDEs, you may need to specify the path to the PHPUnit configuration file. Use the absolute path to &amp;lt;code&amp;gt;phpunit.xml&amp;lt;/code&amp;gt; from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is an alternative script for running of tests via web interface: &amp;lt;code&amp;gt;admin/tool/phpunit/webrunner.php&amp;lt;/code&amp;gt;. Use this as the last resort only when you cannot use the command-line interface on your test server. It will most probably break due to permissions problems if you try to execute it both from command-line and from webrunner. This feature is not officially supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===How to run only some tests===&lt;br /&gt;
&lt;br /&gt;
==== Running a single test quickly ====&lt;br /&gt;
&lt;br /&gt;
The fastest way to run a single test is:&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit my_test_class_name my/tests/filename.php&lt;br /&gt;
&lt;br /&gt;
This is faster than other methods because it avoids the need to search for the test file, but you should be careful because it may be possible to run tests this way which are not included in the normal run. If you use this method, do at least one full test run (or --group run, as below) to ensure the test can be found.&lt;br /&gt;
&lt;br /&gt;
==== Using the @group annotation ====&lt;br /&gt;
&lt;br /&gt;
If you add annotations like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for {@link stack_cas_keyval}.&lt;br /&gt;
 * @group qtype_stack&lt;br /&gt;
 */&lt;br /&gt;
class qtype_stack_cas_keyval_exception_testcase extends basic_testcase {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to all the classes in your plugin, then you can run just the tests for your plugin by doing&lt;br /&gt;
&lt;br /&gt;
 phpunit --group qtype_stack&lt;br /&gt;
&lt;br /&gt;
Therefore, it is suggested that you annotate all your tests with the Frankenstyle name of your plugin.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple phpunit.xml files ====&lt;br /&gt;
&lt;br /&gt;
It&#039;s easy to create alternative phpunit.xml files defining which tests must be run together. For reference, take a look to the default /phpunit.xml available in your base directory once the testing environment has been initialised. After creating the custom file you will be able to run those tests with&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c path/to/your/alternative/phpunit/file.xml&lt;br /&gt;
&lt;br /&gt;
Also, for commodity, you can use this command:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/phpunit/cli/util.php --buildcomponentconfigs&lt;br /&gt;
&lt;br /&gt;
It will, automatically, create one valid phpunit.xml file within each component (plugin or subsystem) and other important directories, so later you will be able to execute tests like&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c mod/forum[/phpunit.xml]  // Note that it&#039;s not needed to specify the name of the file (if it is &#039;phpunit.xml&#039;).&lt;br /&gt;
 vendor/bin/phpunit -c question&lt;br /&gt;
 vendor/bin/phpunit -c question/type/calculated&lt;br /&gt;
 vendor/bin/phpunit -c backup&lt;br /&gt;
 vendor/bin/phpunit -c lib/dml&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
or, also&lt;br /&gt;
&lt;br /&gt;
 cd directory/with/phpunit.xml&lt;br /&gt;
 phpunit&lt;br /&gt;
&lt;br /&gt;
=External test resources=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
By default Moodle phpunit tests contact http://download.moodle.org server when testing curl related functionality. Optionally you may checkout a local copy of the test scripts and access it instead:&lt;br /&gt;
&lt;br /&gt;
# clone https://github.com/moodlehq/moodle-exttests to web directory&lt;br /&gt;
# add to your config.php or modify phpunit.xml file &amp;lt;code php&amp;gt;define(&#039;TEST_EXTERNAL_FILES_HTTP_URL&#039;, &#039;http://localhost/moodle-exttests&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Writing new tests=&lt;br /&gt;
* read [http://www.phpunit.de/manual/current/en/ official PHPUnit online documentation]&lt;br /&gt;
* see [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
=Conversion of existing SimpleTests=&lt;br /&gt;
* see [[SimpleTest conversion]]&lt;br /&gt;
&lt;br /&gt;
=PHPUnit support in IDEs=&lt;br /&gt;
&lt;br /&gt;
* [http://www.phpsrc.org/projects/pti-phpunit/wiki/ Eclipse PHP Tool Integration]&lt;br /&gt;
* [http://blog.jetbrains.com/webide/2009/12/phpunit-support/ PHPStorm IDE]&lt;br /&gt;
* [http://netbeans.org/kb/docs/php/phpunit.html Netbeans]&lt;br /&gt;
&lt;br /&gt;
=Common Unit Test Problems=&lt;br /&gt;
[[Common unit test problems]]&lt;br /&gt;
&lt;br /&gt;
=Performance=&lt;br /&gt;
&lt;br /&gt;
A typical run of full PHPUnit tests for Moodle 2.7 takes 10-20 minutes depending on the machine. If tests run slowly for you:&lt;br /&gt;
&lt;br /&gt;
* Ensure you are using a database and filesystem running on the same machine that is running the tests (not on a remote server).&lt;br /&gt;
* Apply developer-only performance settings to your database: [[Postgres Tuning For Developers]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45352</id>
		<title>PHPUnit</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=PHPUnit&amp;diff=45352"/>
		<updated>2014-06-18T23:41:22Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Using the @group annotation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Moodle 2.3}}&lt;br /&gt;
&lt;br /&gt;
=What is PHPUnit=&lt;br /&gt;
PHPUnit by Sebastian Bergmann is an advanced unit testing framework for PHP. It is installed as Composer dependency and is not part of Moodle installation. To run PHPUnit tests, you have to manually install it on your development computer or test server.&lt;br /&gt;
&lt;br /&gt;
Read the excellent guide at&lt;br /&gt;
* [http://phpunit.de/manual/current/en/index.html PHPUnit Manual]&lt;br /&gt;
&lt;br /&gt;
=Installation of PHPUnit via Composer=&lt;br /&gt;
&lt;br /&gt;
The installation procedure depends on your operating system.&lt;br /&gt;
* Install Composer dependency manager&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 curl -s https://getcomposer.org/installer | php&lt;br /&gt;
&lt;br /&gt;
On Windows go to https://getcomposer.org/download/ and download the Composer-Setup.exe file&lt;br /&gt;
&lt;br /&gt;
* Execute Composer installer&lt;br /&gt;
&lt;br /&gt;
 cd /your/moodle/dirroot&lt;br /&gt;
 php composer.phar install --dev&lt;br /&gt;
&lt;br /&gt;
(If that gives you connection problems try...)&lt;br /&gt;
&lt;br /&gt;
 php composer.phar install --dev --prefer-source&lt;br /&gt;
&lt;br /&gt;
Troubleshooting:&lt;br /&gt;
* On Windows if you are behind a proxy you will need to setup an environment variable called HTTP_PROXY with a value detailing your HTTP Proxy address and port before composer will correctly download files.&lt;br /&gt;
* You may be prompted for github credentials when installing composer dependencies.&lt;br /&gt;
** This is used to generate an personal access token to avoid being rate limited by github.&lt;br /&gt;
** If you have Two Factor Authentication enabled on your github account, or do not wish to supply your own credentials you will need to generate a token manually:&lt;br /&gt;
*** Visit https://github.com/settings/applications and request personal access token&lt;br /&gt;
*** Copy this token and add it to your [https://gist.github.com/andrewnicols/c5377ed25a9df1006ce1 ~/.composer/config.json]&lt;br /&gt;
** ( See [https://github.com/composer/composer/issues/2280 composer issue #2280] for further details of this bug.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [http://getcomposer.org/doc/00-intro.md Composer documentation]&lt;br /&gt;
&lt;br /&gt;
Detailed instructions:&lt;br /&gt;
* [[PHPUnit installation in Windows]]&lt;br /&gt;
* [[PHPUnit installation in OS X]]&lt;br /&gt;
&lt;br /&gt;
== Uninstalling previous PEAR based version ==&lt;br /&gt;
&lt;br /&gt;
Before using composer, this page used to suggest to install phpunit via PEAR. If you did so, you may wish to uninstall that package now. This should work:&lt;br /&gt;
&lt;br /&gt;
   $ pear uninstall phpunit/DbUnit&lt;br /&gt;
   $ pear uninstall phpunit/PHPUnit&lt;br /&gt;
&lt;br /&gt;
=Initialisation of test environment=&lt;br /&gt;
&lt;br /&gt;
Our PHPUnit integration requires a dedicated database and dataroot.  First, add a new dataroot directory and prefix into your config.php, you can find examples in config-dist.php (scroll down to &#039;Section 9&#039;).&lt;br /&gt;
&lt;br /&gt;
 $CFG-&amp;gt;phpunit_prefix = &#039;phpu_&#039;;&lt;br /&gt;
 $CFG-&amp;gt;phpunit_dataroot = &#039;/home/example/phpu_moodledata&#039;;&lt;br /&gt;
&lt;br /&gt;
If your system does not have a direct connection to the Internet, you also need to specify your proxy in config.php - even though you normally specify it by using the admin settings user interface. (If you do not use a proxy, you can skip this step.) Check the settings on the relevant admin settings page, or from the mdl_config table in your database, if you are unsure of the correct values.&lt;br /&gt;
 &lt;br /&gt;
 // Normal proxy settings&lt;br /&gt;
 $CFG-&amp;gt;proxyhost = &#039;wwwcache.example.org&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxyport = 80;&lt;br /&gt;
 $CFG-&amp;gt;proxytype = &#039;HTTP&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxybypass = &#039;localhost, 127.0.0.1, .example.org&#039;;&lt;br /&gt;
 // Omit the next lines if your proxy doesn&#039;t need a username/password:&lt;br /&gt;
 $CFG-&amp;gt;proxyuser = &#039;systemusername&#039;;&lt;br /&gt;
 $CFG-&amp;gt;proxypassword = &#039;systempassword&#039;;&lt;br /&gt;
&lt;br /&gt;
Then you need to initialise the test environment using following command.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 php admin/tool/phpunit/cli/init.php&lt;br /&gt;
&lt;br /&gt;
This command has to be repeated after any upgrade, plugin (un)installation or if you have added tests to a plugin you are developing:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NOTE:&#039;&#039;&#039; make sure that your php cli executable (or the one you want to use) is correctly on your path as the individual init scripts will call it repeatedly.&lt;br /&gt;
&lt;br /&gt;
=Test execution=&lt;br /&gt;
&lt;br /&gt;
To execute all test suites from main configuration file execute the &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; script from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt; directory.&lt;br /&gt;
&lt;br /&gt;
 cd /home/example/moodle&lt;br /&gt;
 vendor/bin/phpunit&lt;br /&gt;
&lt;br /&gt;
The rest of examples uses &amp;lt;code&amp;gt;phpunit&amp;lt;/code&amp;gt;, please substitute it with &amp;lt;code&amp;gt;vendor/bin/phpunit&amp;lt;/code&amp;gt; or create a shortcut in your dirroot.&lt;br /&gt;
&lt;br /&gt;
In IDEs, you may need to specify the path to the PHPUnit configuration file. Use the absolute path to &amp;lt;code&amp;gt;phpunit.xml&amp;lt;/code&amp;gt; from your &amp;lt;code&amp;gt;$CFG-&amp;gt;dirroot&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There is an alternative script for running of tests via web interface: &amp;lt;code&amp;gt;admin/tool/phpunit/webrunner.php&amp;lt;/code&amp;gt;. Use this as the last resort only when you cannot use the command-line interface on your test server. It will most probably break due to permissions problems if you try to execute it both from command-line and from webrunner. This feature is not officially supported.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===How to run only some tests===&lt;br /&gt;
&lt;br /&gt;
==== Running a single test quickly ====&lt;br /&gt;
&lt;br /&gt;
The fastest way to run a single test is:&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit my_test_class_name my/tests/filename.php&lt;br /&gt;
&lt;br /&gt;
This is faster than other methods because it avoids the need to search for the test file, but you should be careful because it may be possible to run tests this way which are not included in the normal run. If you use this method, do at least one full test run (or --group run, as below) to ensure the test can be found.&lt;br /&gt;
&lt;br /&gt;
==== Using the @group annotation ====&lt;br /&gt;
&lt;br /&gt;
If you add annotations like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code php&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * Unit tests for {@link stack_cas_keyval}.&lt;br /&gt;
 * @group qtype_stack&lt;br /&gt;
 */&lt;br /&gt;
class stack_cas_keyval_exception_testcase extends basic_testcase {&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
to all the classes in your plugin, then you can run just the tests for your plugin by doing&lt;br /&gt;
&lt;br /&gt;
 phpunit --group qtype_stack&lt;br /&gt;
&lt;br /&gt;
Therefore, it is suggested that you annotate all your tests with the Frankenstyle name of your plugin.&lt;br /&gt;
&lt;br /&gt;
==== Using multiple phpunit.xml files ====&lt;br /&gt;
&lt;br /&gt;
It&#039;s easy to create alternative phpunit.xml files defining which tests must be run together. For reference, take a look to the default /phpunit.xml available in your base directory once the testing environment has been initialised. After creating the custom file you will be able to run those tests with&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c path/to/your/alternative/phpunit/file.xml&lt;br /&gt;
&lt;br /&gt;
Also, for commodity, you can use this command:&lt;br /&gt;
&lt;br /&gt;
 php admin/tool/phpunit/cli/util.php --buildcomponentconfigs&lt;br /&gt;
&lt;br /&gt;
It will, automatically, create one valid phpunit.xml file within each component (plugin or subsystem) and other important directories, so later you will be able to execute tests like&lt;br /&gt;
&lt;br /&gt;
 vendor/bin/phpunit -c mod/forum[/phpunit.xml]  // Note that it&#039;s not needed to specify the name of the file (if it is &#039;phpunit.xml&#039;).&lt;br /&gt;
 vendor/bin/phpunit -c question&lt;br /&gt;
 vendor/bin/phpunit -c question/type/calculated&lt;br /&gt;
 vendor/bin/phpunit -c backup&lt;br /&gt;
 vendor/bin/phpunit -c lib/dml&lt;br /&gt;
 ...&lt;br /&gt;
&lt;br /&gt;
or, also&lt;br /&gt;
&lt;br /&gt;
 cd directory/with/phpunit.xml&lt;br /&gt;
 phpunit&lt;br /&gt;
&lt;br /&gt;
=External test resources=&lt;br /&gt;
{{Moodle 2.6}}&lt;br /&gt;
By default Moodle phpunit tests contact http://download.moodle.org server when testing curl related functionality. Optionally you may checkout a local copy of the test scripts and access it instead:&lt;br /&gt;
&lt;br /&gt;
# clone https://github.com/moodlehq/moodle-exttests to web directory&lt;br /&gt;
# add to your config.php or modify phpunit.xml file &amp;lt;code php&amp;gt;define(&#039;TEST_EXTERNAL_FILES_HTTP_URL&#039;, &#039;http://localhost/moodle-exttests&#039;);&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Writing new tests=&lt;br /&gt;
* read [http://www.phpunit.de/manual/current/en/ official PHPUnit online documentation]&lt;br /&gt;
* see [[Writing PHPUnit tests]]&lt;br /&gt;
&lt;br /&gt;
=Conversion of existing SimpleTests=&lt;br /&gt;
* see [[SimpleTest conversion]]&lt;br /&gt;
&lt;br /&gt;
=PHPUnit support in IDEs=&lt;br /&gt;
&lt;br /&gt;
* [http://www.phpsrc.org/projects/pti-phpunit/wiki/ Eclipse PHP Tool Integration]&lt;br /&gt;
* [http://blog.jetbrains.com/webide/2009/12/phpunit-support/ PHPStorm IDE]&lt;br /&gt;
* [http://netbeans.org/kb/docs/php/phpunit.html Netbeans]&lt;br /&gt;
&lt;br /&gt;
=Common Unit Test Problems=&lt;br /&gt;
[[Common unit test problems]]&lt;br /&gt;
&lt;br /&gt;
=Performance=&lt;br /&gt;
&lt;br /&gt;
A typical run of full PHPUnit tests for Moodle 2.7 takes 10-20 minutes depending on the machine. If tests run slowly for you:&lt;br /&gt;
&lt;br /&gt;
* Ensure you are using a database and filesystem running on the same machine that is running the tests (not on a remote server).&lt;br /&gt;
* Apply developer-only performance settings to your database: [[Postgres Tuning For Developers]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Unit testing]]&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45351</id>
		<title>Setting up PhpStorm</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45351"/>
		<updated>2014-06-18T23:35:56Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* Database editor */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.jetbrains.com/phpstorm/ PhpStorm] is a commercial IDE, it is arguably the best IDE for PHP developers with features such as code completion, code inspection, phpunit support, Behat support, database editor, debugger, etc.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===OS X===&lt;br /&gt;
Install latest Java JDK 1.7.x from [http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html Oracle] (Java 1.6 from Apple is not maintained much).&lt;br /&gt;
&lt;br /&gt;
You can hack older PhpStorm 7 to be compatible with Java 1.7 by editing the &amp;quot;PhpStorm.app/Contents/Info.plist&amp;quot; file, set JVMOptions - JVMVersion = 1.7*&lt;br /&gt;
&lt;br /&gt;
==General settings==&lt;br /&gt;
&lt;br /&gt;
* Disable missing @throws tag warning in &amp;quot;Preferences / Project Settings / Inspections / PHP / PHPDoc&amp;quot;&lt;br /&gt;
* Strip trailing whitespace from &amp;quot;Modified Lines&amp;quot; in &amp;quot;Preferences / IDE Settings / Editor&amp;quot;&lt;br /&gt;
* Show line numbers in &amp;quot;Preferences / IDE Settings / Editor / Appearance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Code formatting==&lt;br /&gt;
&lt;br /&gt;
* Setup coding style to use all rules from [Coding style] in &amp;quot;Preferences / Project Settings / Code Style / PHP&amp;quot;.&lt;br /&gt;
* Set line separator to Unix in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
* Set right margin to 132 or 180 in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Moodle code checker==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PHPUnit integration==&lt;br /&gt;
# Install [[PHPUnit]] via Composer &lt;br /&gt;
# Tell PHPStorm where is composer - go to &amp;quot;Preferences / PHP / Composer&amp;quot;, fill in &amp;quot;Path to PHP executable&amp;quot;, &amp;quot;Path to composer.phar&amp;quot;, &amp;quot;Path to composer.json&amp;quot; and make sure the option &amp;quot;Add packages as libraries&amp;quot; is enabled.&lt;br /&gt;
# Go to &amp;quot;Run / Edit configurations&amp;quot;&lt;br /&gt;
# Add PHPUnit configuration by clicking on &amp;quot;+&amp;quot;&lt;br /&gt;
# Click &amp;quot;Use alternative configuration file&amp;quot; and select your phpunit.xml file&lt;br /&gt;
# Go to &amp;quot;Run / Run ...&amp;quot; and select your new PHPUnit configuration to run&lt;br /&gt;
&lt;br /&gt;
==Database editor==&lt;br /&gt;
# Click on the &amp;quot;Database&amp;quot; tab to see the database window&lt;br /&gt;
# Click &amp;quot;+&amp;quot; in the top left and add &amp;quot;Database source&amp;quot; for your database&lt;br /&gt;
# Note: click on the link to download the necessary drivers directly from IDE&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
	<entry>
		<id>https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45350</id>
		<title>Setting up PhpStorm</title>
		<link rel="alternate" type="text/html" href="https://docs.moodle.org/dev/index.php?title=Setting_up_PhpStorm&amp;diff=45350"/>
		<updated>2014-06-18T23:16:42Z</updated>

		<summary type="html">&lt;p&gt;Skodak: /* PHPUnit integration */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.jetbrains.com/phpstorm/ PhpStorm] is a commercial IDE, it is arguably the best IDE for PHP developers with features such as code completion, code inspection, phpunit support, Behat support, database editor, debugger, etc.&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
&lt;br /&gt;
===OS X===&lt;br /&gt;
Install latest Java JDK 1.7.x from [http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html Oracle] (Java 1.6 from Apple is not maintained much).&lt;br /&gt;
&lt;br /&gt;
You can hack older PhpStorm 7 to be compatible with Java 1.7 by editing the &amp;quot;PhpStorm.app/Contents/Info.plist&amp;quot; file, set JVMOptions - JVMVersion = 1.7*&lt;br /&gt;
&lt;br /&gt;
==General settings==&lt;br /&gt;
&lt;br /&gt;
* Disable missing @throws tag warning in &amp;quot;Preferences / Project Settings / Inspections / PHP / PHPDoc&amp;quot;&lt;br /&gt;
* Strip trailing whitespace from &amp;quot;Modified Lines&amp;quot; in &amp;quot;Preferences / IDE Settings / Editor&amp;quot;&lt;br /&gt;
* Show line numbers in &amp;quot;Preferences / IDE Settings / Editor / Appearance&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==Code formatting==&lt;br /&gt;
&lt;br /&gt;
* Setup coding style to use all rules from [Coding style] in &amp;quot;Preferences / Project Settings / Code Style / PHP&amp;quot;.&lt;br /&gt;
* Set line separator to Unix in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
* Set right margin to 132 or 180 in &amp;quot;Preferences / Project Settings / Code Style / General&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
==Moodle code checker==&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
==PHPUnit integration==&lt;br /&gt;
# Install [[PHPUnit]] via Composer &lt;br /&gt;
# Tell PHPStorm where is composer - go to &amp;quot;Preferences / PHP / Composer&amp;quot;, fill in &amp;quot;Path to PHP executable&amp;quot;, &amp;quot;Path to composer.phar&amp;quot;, &amp;quot;Path to composer.json&amp;quot; and make sure the option &amp;quot;Add packages as libraries&amp;quot; is enabled.&lt;br /&gt;
# Go to &amp;quot;Run / Edit configurations&amp;quot;&lt;br /&gt;
# Add PHPUnit configuration by clicking on &amp;quot;+&amp;quot;&lt;br /&gt;
# Click &amp;quot;Use alternative configuration file&amp;quot; and select your phpunit.xml file&lt;br /&gt;
# Go to &amp;quot;Run / Run ...&amp;quot; and select your new PHPUnit configuration to run&lt;br /&gt;
&lt;br /&gt;
==Database editor==&lt;br /&gt;
TODO&lt;/div&gt;</summary>
		<author><name>Skodak</name></author>
	</entry>
</feed>