diff --git a/.travis.yml b/.travis.yml
index 0d63fe8ad9acc79ddf3f27ef62a86f59792f2d49..d1aa3a456600edab6f682f42709bf75df94e1ea0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,7 +1,47 @@
 language: php
+
+sudo: false
+
+cache:
+    directories:
+        - $HOME/.composer/cache
+
 php:
-    - 5.5
     - 5.6
     - 7.0
-install: composer install --no-interaction
-script: ./vendor/bin/phpunit
+    - 7.1
+
+env:
+    global:
+        - MOODLE_BRANCH=MOODLE_32_STABLE
+    matrix:
+        - DB=pgsql
+#       - DB=mysqli
+
+before_install:
+    - composer install --no-interaction
+    - phpenv config-rm xdebug.ini
+    - nvm install node
+    - cd ../..
+    - composer selfupdate
+    - composer create-project -n --no-dev --prefer-dist moodlerooms/moodle-plugin-ci ci ^2
+    - export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
+
+install:
+    - moodle-plugin-ci install
+
+script:
+#   - moodle-plugin-ci phplint
+#   - moodle-plugin-ci phpcpd
+#   - moodle-plugin-ci phpmd
+#   - moodle-plugin-ci codechecker
+    - moodle-plugin-ci validate
+    - moodle-plugin-ci savepoints
+#   - moodle-plugin-ci mustache
+#   - moodle-plugin-ci grunt
+    - moodle-plugin-ci phpunit
+#   - moodle-plugin-ci behat
+
+    # run codechecker without the vendor/ directory
+    - rm -rf "$(find -type d -name xapi)/vendor"
+    - moodle-plugin-ci codechecker
diff --git a/README.md b/README.md
index 1ebd7891da7e0e44c6782474a4c635c45844df43..cb604556c2270dc8fc6e7bee8b40bd2bd7bebcce 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
 > Emits events from the [Moodle](https://moodle.org/) Logstore as [xAPI](https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md) statements.
 
 [![Build Status](https://travis-ci.org/xAPI-vle/moodle-logstore_xapi.svg?branch=master)](https://travis-ci.org/xAPI-vle/moodle-logstore_xapi)
-[![Code Climate](https://codeclimate.com/github/xAPI-vle/moodle-logstore_xapi.png)](https://codeclimate.com/github/xAPI-vle/moodle-logstore_xapi)
 [![Moodle Plugin Directory](http://img.shields.io/badge/moodle-plugin-orange.svg)](https://moodle.org/plugins/view/logstore_xapi)
 [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/LearningLocker/learninglocker?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 
diff --git a/classes/log/store.php b/classes/log/store.php
index cf0e8726e17e6d57cd2458322e4742843f454c0f..039b55cf49110336cae7c3484c690b91045693b8 100644
--- a/classes/log/store.php
+++ b/classes/log/store.php
@@ -98,7 +98,7 @@ class store extends php_obj implements log_writer {
     protected function insert_event_entries(array $events) {
         global $DB;
 
-        // If in background mode, just save them in the database
+        // If in background mode, just save them in the database.
         if (get_config('logstore_xapi', 'backgroundmode')) {
             $DB->insert_records('logstore_xapi_log', $events);
         } else {
@@ -109,9 +109,9 @@ class store extends php_obj implements log_writer {
     public function process_events(array $events) {
 
         // Initializes required services.
-        $xapiController = new xapi_controller($this->connect_xapi_repository());
-        $moodleController = new moodle_controller($this->connect_moodle_repository());
-        $translatorController = new translator_controller();
+        $xapicontroller = new xapi_controller($this->connect_xapi_repository());
+        $moodlecontroller = new moodle_controller($this->connect_moodle_repository());
+        $translatorcontroller = new translator_controller();
 
         // Emits events to other APIs.
         foreach ($events as $index => $event) {
@@ -120,45 +120,46 @@ class store extends php_obj implements log_writer {
 
         $this->error_log('');
         $this->error_log_value('events', $events);
-        $moodleEvents = $moodleController->createEvents($events);
+        $moodleevents = $moodlecontroller->create_events($events);
 
-        // Clear the user email if mbox setting is not set to mbox
+        // Clear the user email if mbox setting is not set to mbox.
         $mbox = get_config('logstore_xapi', 'mbox');
-        foreach(array_keys($moodleEvents) as $event_key) {
-            $moodleEvents[$event_key]['sendmbox'] = $mbox;
+        foreach (array_keys($moodleevents) as $eventkey) {
+            $moodleevents[$eventkey]['sendmbox'] = $mbox;
         }
 
-        $this->error_log_value('moodleevent', $moodleEvents);
-        $translatorEvents = $translatorController->createEvents($moodleEvents);
-        $this->error_log_value('translatorevents', $translatorEvents);
+        $this->error_log_value('moodleevent', $moodleevents);
+        $translatorevents = $translatorcontroller->create_events($moodleevents);
+        $this->error_log_value('translatorevents', $translatorevents);
 
-        if (empty($translatorEvents)) {
+        if (empty($translatorevents)) {
             return [];
         }
 
         // Split statements into batches.
-        $eventBatches = array($translatorEvents);
-        $maxBatchSize = get_config('logstore_xapi', 'maxbatchsize');
+        $eventbatches = array($translatorevents);
+        $maxbatchsize = get_config('logstore_xapi', 'maxbatchsize');
 
-        if (!empty($maxBatchSize) && $maxBatchSize < count($translatorEvents)) {
-            $eventBatches = array_chunk($translatorEvents, $maxBatchSize);
+        if (!empty($maxbatchsize) && $maxbatchsize < count($translatorevents)) {
+            $eventbatches = array_chunk($translatorevents, $maxbatchsize);
         }
 
-        $translatorEvent = new Event();
-        $translatorEventReadReturn = @$translatorEvent->read([]);
+        $translatorevent = new Event();
+        $translatoreventreadreturn = @$translatorevent->read([]);
 
-        $sentEvents = [];
-        foreach ($eventBatches as $translatorEventsBatch) {
-            $xapiEvents = $xapiController->createEvents($translatorEventsBatch);
-            foreach(array_keys($xapiEvents) as $key) {
+        $sentevents = [];
+        foreach ($eventbatches as $translatoreventsbatch) {
+            $xapievents = $xapicontroller->create_events($translatoreventsbatch);
+            foreach (array_keys($xapievents) as $key) {
                 if (is_numeric($key)) {
-                    $sentEvents[$xapiEvents[$key]['context']['extensions'][$translatorEventReadReturn[0]['context_ext_key']]['id']] = $xapiEvents['last_action_result'];
+                    $k = $xapievents[$key]['context']['extensions'][$translatoreventreadreturn[0]['context_ext_key']]['id'];
+                    $sentevents[$k] = $xapievents['last_action_result'];
                 }
             }
-            $this->error_log_value('xapievents', $xapiEvents);
+            $this->error_log_value('xapievents', $xapievents);
         }
 
-        return $sentEvents;
+        return $sentevents;
     }
 
     private function error_log_value($key, $value) {
@@ -167,6 +168,7 @@ class store extends php_obj implements log_writer {
 
     private function error_log($message) {
         if ($this->loggingenabled) {
+            // @codingStandardsIgnoreLine
             error_log($message."\r\n", 3, __DIR__.'/error_log.txt');
         }
     }
@@ -191,16 +193,16 @@ class store extends php_obj implements log_writer {
      */
     private function connect_xapi_repository() {
         global $CFG;
-        $remote_lrs = new tincan_remote_lrs(
+        $remotelrs = new tincan_remote_lrs(
             $this->get_config('endpoint', ''),
             '1.0.1',
             $this->get_config('username', ''),
             $this->get_config('password', '')
         );
         if (!empty($CFG->proxyhost)) {
-          $remote_lrs->setProxy($CFG->proxyhost.':'.$CFG->proxyport);
+            $remotelrs->setProxy($CFG->proxyhost.':'.$CFG->proxyport);
         }
-        return new xapi_repository($remote_lrs);
+        return new xapi_repository($remotelrs);
     }
 
     /**
diff --git a/classes/task/emit_task.php b/classes/task/emit_task.php
index 8946bfc3fd5cca3844cda24ab7c1e4473ac9cd65..893c819eaead3630d91b725137eb62ccabb9b806 100644
--- a/classes/task/emit_task.php
+++ b/classes/task/emit_task.php
@@ -49,10 +49,10 @@ class emit_task extends \core\task\scheduled_task {
         $manager = get_log_manager();
         $store = new store($manager);
         $events = $DB->get_records('logstore_xapi_log');
-        $store_return = $store->process_events($events);
-        foreach(array_keys($store_return) as $event_id) {
-            if ($store_return[$event_id] == 'success') {
-                $DB->delete_records_list('logstore_xapi_log', 'id', array($event_id));
+        $storereturn = $store->process_events($events);
+        foreach (array_keys($storereturn) as $eventid) {
+            if ($storereturn[$eventid] == 'success') {
+                $DB->delete_records_list('logstore_xapi_log', 'id', array($eventid));
             }
         }
 
diff --git a/composer.json b/composer.json
index a44b939ca73e94ac58da20ebff4240f20a306510..03210054697c2bb504a425f570cab79d14d44ac5 100644
--- a/composer.json
+++ b/composer.json
@@ -6,15 +6,14 @@
           "logstore_xapi\\": "classes/",
           "Tests\\": "tests/",
           "XREmitter\\": "lib/emitter/src/",
-          "XREmitter\\Tests\\": "lib/emitter/tests/",
+          "XREmitter\\Tests\\": "tests/lib/emitter/",
           "LogExpander\\": "lib/expander/src/",
-          "LogExpander\\Tests\\": "lib/expander/tests/",
+          "LogExpander\\Tests\\": "tests/lib/expander/",
           "MXTranslator\\": "lib/translator/src/",
-          "MXTranslator\\Tests\\": "lib/translator/tests/"
+          "MXTranslator\\Tests\\": "tests/lib/translator/"
         }
     },
     "require-dev": {
-        "phpunit/phpunit": "~4.6",
         "learninglocker/statementfactory": "~0.0"
     },
     "require": {
diff --git a/composer.lock b/composer.lock
index 6f617fa2d5d9ea4c3578fbcae8a1e9606ca395cf..7c6fa26d73ed90b0c2ad98c4117658764eb19c58 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "ec99a19150b6dcfc55ef03770d477faf",
+    "content-hash": "91a3c0a87448099a554668d86683c333",
     "packages": [
         {
             "name": "namshi/jose",
@@ -284,60 +284,6 @@
         }
     ],
     "packages-dev": [
-        {
-            "name": "doctrine/instantiator",
-            "version": "1.0.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/doctrine/instantiator.git",
-                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d",
-                "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3,<8.0-DEV"
-            },
-            "require-dev": {
-                "athletic/athletic": "~0.1.8",
-                "ext-pdo": "*",
-                "ext-phar": "*",
-                "phpunit/phpunit": "~4.0",
-                "squizlabs/php_codesniffer": "~2.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Marco Pivetta",
-                    "email": "ocramius@gmail.com",
-                    "homepage": "http://ocramius.github.com/"
-                }
-            ],
-            "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
-            "homepage": "https://github.com/doctrine/instantiator",
-            "keywords": [
-                "constructor",
-                "instantiate"
-            ],
-            "time": "2015-06-14T21:17:01+00:00"
-        },
         {
             "name": "learninglocker/statementfactory",
             "version": "v0.0.10",
@@ -370,1068 +316,6 @@
             ],
             "description": "Learning Locker's classes for xAPI.",
             "time": "2016-08-25T14:02:22+00:00"
-        },
-        {
-            "name": "phpdocumentor/reflection-common",
-            "version": "1.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
-                "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
-                "reference": "144c307535e82c8fdcaacbcfc1d6d8eeb896687c",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.6"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "phpDocumentor\\Reflection\\": [
-                        "src"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Jaap van Otterdijk",
-                    "email": "opensource@ijaap.nl"
-                }
-            ],
-            "description": "Common reflection classes used by phpdocumentor to reflect the code structure",
-            "homepage": "http://www.phpdoc.org",
-            "keywords": [
-                "FQSEN",
-                "phpDocumentor",
-                "phpdoc",
-                "reflection",
-                "static analysis"
-            ],
-            "time": "2015-12-27T11:43:31+00:00"
-        },
-        {
-            "name": "phpdocumentor/reflection-docblock",
-            "version": "3.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
-                "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/8331b5efe816ae05461b7ca1e721c01b46bafb3e",
-                "reference": "8331b5efe816ae05461b7ca1e721c01b46bafb3e",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5",
-                "phpdocumentor/reflection-common": "^1.0@dev",
-                "phpdocumentor/type-resolver": "^0.2.0",
-                "webmozart/assert": "^1.0"
-            },
-            "require-dev": {
-                "mockery/mockery": "^0.9.4",
-                "phpunit/phpunit": "^4.4"
-            },
-            "type": "library",
-            "autoload": {
-                "psr-4": {
-                    "phpDocumentor\\Reflection\\": [
-                        "src/"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Mike van Riel",
-                    "email": "me@mikevanriel.com"
-                }
-            ],
-            "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
-            "time": "2016-09-30T07:12:33+00:00"
-        },
-        {
-            "name": "phpdocumentor/type-resolver",
-            "version": "0.2.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpDocumentor/TypeResolver.git",
-                "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
-                "reference": "e224fb2ea2fba6d3ad6fdaef91cd09a172155ccb",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5",
-                "phpdocumentor/reflection-common": "^1.0"
-            },
-            "require-dev": {
-                "mockery/mockery": "^0.9.4",
-                "phpunit/phpunit": "^5.2||^4.8.24"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "phpDocumentor\\Reflection\\": [
-                        "src/"
-                    ]
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Mike van Riel",
-                    "email": "me@mikevanriel.com"
-                }
-            ],
-            "time": "2016-11-25T06:54:22+00:00"
-        },
-        {
-            "name": "phpspec/prophecy",
-            "version": "v1.7.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/phpspec/prophecy.git",
-                "reference": "93d39f1f7f9326d746203c7c056f300f7f126073"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/phpspec/prophecy/zipball/93d39f1f7f9326d746203c7c056f300f7f126073",
-                "reference": "93d39f1f7f9326d746203c7c056f300f7f126073",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/instantiator": "^1.0.2",
-                "php": "^5.3|^7.0",
-                "phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
-                "sebastian/comparator": "^1.1|^2.0",
-                "sebastian/recursion-context": "^1.0|^2.0|^3.0"
-            },
-            "require-dev": {
-                "phpspec/phpspec": "^2.5|^3.2",
-                "phpunit/phpunit": "^4.8 || ^5.6.5"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.6.x-dev"
-                }
-            },
-            "autoload": {
-                "psr-0": {
-                    "Prophecy\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Konstantin Kudryashov",
-                    "email": "ever.zet@gmail.com",
-                    "homepage": "http://everzet.com"
-                },
-                {
-                    "name": "Marcello Duarte",
-                    "email": "marcello.duarte@gmail.com"
-                }
-            ],
-            "description": "Highly opinionated mocking framework for PHP 5.3+",
-            "homepage": "https://github.com/phpspec/prophecy",
-            "keywords": [
-                "Double",
-                "Dummy",
-                "fake",
-                "mock",
-                "spy",
-                "stub"
-            ],
-            "time": "2017-03-02T20:05:34+00:00"
-        },
-        {
-            "name": "phpunit/php-code-coverage",
-            "version": "2.2.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979",
-                "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "phpunit/php-file-iterator": "~1.3",
-                "phpunit/php-text-template": "~1.2",
-                "phpunit/php-token-stream": "~1.3",
-                "sebastian/environment": "^1.3.2",
-                "sebastian/version": "~1.0"
-            },
-            "require-dev": {
-                "ext-xdebug": ">=2.1.4",
-                "phpunit/phpunit": "~4"
-            },
-            "suggest": {
-                "ext-dom": "*",
-                "ext-xdebug": ">=2.2.1",
-                "ext-xmlwriter": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.2.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
-            "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
-            "keywords": [
-                "coverage",
-                "testing",
-                "xunit"
-            ],
-            "time": "2015-10-06T15:47:00+00:00"
-        },
-        {
-            "name": "phpunit/php-file-iterator",
-            "version": "1.4.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
-                "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
-                "reference": "3cc8f69b3028d0f96a9078e6295d86e9bf019be5",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "FilterIterator implementation that filters files based on a list of suffixes.",
-            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
-            "keywords": [
-                "filesystem",
-                "iterator"
-            ],
-            "time": "2016-10-03T07:40:28+00:00"
-        },
-        {
-            "name": "phpunit/php-text-template",
-            "version": "1.2.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-text-template.git",
-                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-                "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Simple template engine.",
-            "homepage": "https://github.com/sebastianbergmann/php-text-template/",
-            "keywords": [
-                "template"
-            ],
-            "time": "2015-06-21T13:50:34+00:00"
-        },
-        {
-            "name": "phpunit/php-timer",
-            "version": "1.0.9",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-timer.git",
-                "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
-                "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.3 || ^7.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Utility class for timing",
-            "homepage": "https://github.com/sebastianbergmann/php-timer/",
-            "keywords": [
-                "timer"
-            ],
-            "time": "2017-02-26T11:10:40+00:00"
-        },
-        {
-            "name": "phpunit/php-token-stream",
-            "version": "1.4.11",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/e03f8f67534427a787e21a385a67ec3ca6978ea7",
-                "reference": "e03f8f67534427a787e21a385a67ec3ca6978ea7",
-                "shasum": ""
-            },
-            "require": {
-                "ext-tokenizer": "*",
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Wrapper around PHP's tokenizer extension.",
-            "homepage": "https://github.com/sebastianbergmann/php-token-stream/",
-            "keywords": [
-                "tokenizer"
-            ],
-            "time": "2017-02-27T10:12:30+00:00"
-        },
-        {
-            "name": "phpunit/phpunit",
-            "version": "4.8.35",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/791b1a67c25af50e230f841ee7a9c6eba507dc87",
-                "reference": "791b1a67c25af50e230f841ee7a9c6eba507dc87",
-                "shasum": ""
-            },
-            "require": {
-                "ext-dom": "*",
-                "ext-json": "*",
-                "ext-pcre": "*",
-                "ext-reflection": "*",
-                "ext-spl": "*",
-                "php": ">=5.3.3",
-                "phpspec/prophecy": "^1.3.1",
-                "phpunit/php-code-coverage": "~2.1",
-                "phpunit/php-file-iterator": "~1.4",
-                "phpunit/php-text-template": "~1.2",
-                "phpunit/php-timer": "^1.0.6",
-                "phpunit/phpunit-mock-objects": "~2.3",
-                "sebastian/comparator": "~1.2.2",
-                "sebastian/diff": "~1.2",
-                "sebastian/environment": "~1.3",
-                "sebastian/exporter": "~1.2",
-                "sebastian/global-state": "~1.0",
-                "sebastian/version": "~1.0",
-                "symfony/yaml": "~2.1|~3.0"
-            },
-            "suggest": {
-                "phpunit/php-invoker": "~1.1"
-            },
-            "bin": [
-                "phpunit"
-            ],
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "4.8.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "The PHP Unit Testing framework.",
-            "homepage": "https://phpunit.de/",
-            "keywords": [
-                "phpunit",
-                "testing",
-                "xunit"
-            ],
-            "time": "2017-02-06T05:18:07+00:00"
-        },
-        {
-            "name": "phpunit/phpunit-mock-objects",
-            "version": "2.3.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git",
-                "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983",
-                "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983",
-                "shasum": ""
-            },
-            "require": {
-                "doctrine/instantiator": "^1.0.2",
-                "php": ">=5.3.3",
-                "phpunit/php-text-template": "~1.2",
-                "sebastian/exporter": "~1.2"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "suggest": {
-                "ext-soap": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "2.3.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sb@sebastian-bergmann.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Mock Object library for PHPUnit",
-            "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/",
-            "keywords": [
-                "mock",
-                "xunit"
-            ],
-            "time": "2015-10-02T06:51:40+00:00"
-        },
-        {
-            "name": "sebastian/comparator",
-            "version": "1.2.4",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/comparator.git",
-                "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
-                "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "sebastian/diff": "~1.2",
-                "sebastian/exporter": "~1.2 || ~2.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.2.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Volker Dusch",
-                    "email": "github@wallbash.com"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@2bepublished.at"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides the functionality to compare PHP values for equality",
-            "homepage": "http://www.github.com/sebastianbergmann/comparator",
-            "keywords": [
-                "comparator",
-                "compare",
-                "equality"
-            ],
-            "time": "2017-01-29T09:50:25+00:00"
-        },
-        {
-            "name": "sebastian/diff",
-            "version": "1.4.3",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/diff.git",
-                "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4",
-                "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.3 || ^7.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.4-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Kore Nordmann",
-                    "email": "mail@kore-nordmann.de"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Diff implementation",
-            "homepage": "https://github.com/sebastianbergmann/diff",
-            "keywords": [
-                "diff"
-            ],
-            "time": "2017-05-22T07:24:03+00:00"
-        },
-        {
-            "name": "sebastian/environment",
-            "version": "1.3.8",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/environment.git",
-                "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
-                "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.3 || ^7.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.8 || ^5.0"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Provides functionality to handle HHVM/PHP environments",
-            "homepage": "http://www.github.com/sebastianbergmann/environment",
-            "keywords": [
-                "Xdebug",
-                "environment",
-                "hhvm"
-            ],
-            "time": "2016-08-18T05:49:44+00:00"
-        },
-        {
-            "name": "sebastian/exporter",
-            "version": "1.2.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/exporter.git",
-                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4",
-                "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3",
-                "sebastian/recursion-context": "~1.0"
-            },
-            "require-dev": {
-                "ext-mbstring": "*",
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Volker Dusch",
-                    "email": "github@wallbash.com"
-                },
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@2bepublished.at"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                },
-                {
-                    "name": "Adam Harvey",
-                    "email": "aharvey@php.net"
-                }
-            ],
-            "description": "Provides the functionality to export PHP variables for visualization",
-            "homepage": "http://www.github.com/sebastianbergmann/exporter",
-            "keywords": [
-                "export",
-                "exporter"
-            ],
-            "time": "2016-06-17T09:04:28+00:00"
-        },
-        {
-            "name": "sebastian/global-state",
-            "version": "1.1.1",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/global-state.git",
-                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4",
-                "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.2"
-            },
-            "suggest": {
-                "ext-uopz": "*"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                }
-            ],
-            "description": "Snapshotting of global state",
-            "homepage": "http://www.github.com/sebastianbergmann/global-state",
-            "keywords": [
-                "global state"
-            ],
-            "time": "2015-10-12T03:26:01+00:00"
-        },
-        {
-            "name": "sebastian/recursion-context",
-            "version": "1.0.5",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/recursion-context.git",
-                "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
-                "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.3.3"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "~4.4"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.0.x-dev"
-                }
-            },
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Jeff Welch",
-                    "email": "whatthejeff@gmail.com"
-                },
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de"
-                },
-                {
-                    "name": "Adam Harvey",
-                    "email": "aharvey@php.net"
-                }
-            ],
-            "description": "Provides functionality to recursively process PHP variables",
-            "homepage": "http://www.github.com/sebastianbergmann/recursion-context",
-            "time": "2016-10-03T07:41:43+00:00"
-        },
-        {
-            "name": "sebastian/version",
-            "version": "1.0.6",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/sebastianbergmann/version.git",
-                "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
-                "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6",
-                "shasum": ""
-            },
-            "type": "library",
-            "autoload": {
-                "classmap": [
-                    "src/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "BSD-3-Clause"
-            ],
-            "authors": [
-                {
-                    "name": "Sebastian Bergmann",
-                    "email": "sebastian@phpunit.de",
-                    "role": "lead"
-                }
-            ],
-            "description": "Library that helps with managing the version number of Git-hosted PHP projects",
-            "homepage": "https://github.com/sebastianbergmann/version",
-            "time": "2015-06-21T13:59:46+00:00"
-        },
-        {
-            "name": "symfony/yaml",
-            "version": "v3.3.2",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/symfony/yaml.git",
-                "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/symfony/yaml/zipball/9752a30000a8ca9f4b34b5227d15d0101b96b063",
-                "reference": "9752a30000a8ca9f4b34b5227d15d0101b96b063",
-                "shasum": ""
-            },
-            "require": {
-                "php": ">=5.5.9"
-            },
-            "require-dev": {
-                "symfony/console": "~2.8|~3.0"
-            },
-            "suggest": {
-                "symfony/console": "For validating YAML files using the lint command"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "3.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Symfony\\Component\\Yaml\\": ""
-                },
-                "exclude-from-classmap": [
-                    "/Tests/"
-                ]
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Fabien Potencier",
-                    "email": "fabien@symfony.com"
-                },
-                {
-                    "name": "Symfony Community",
-                    "homepage": "https://symfony.com/contributors"
-                }
-            ],
-            "description": "Symfony Yaml Component",
-            "homepage": "https://symfony.com",
-            "time": "2017-06-02T22:05:06+00:00"
-        },
-        {
-            "name": "webmozart/assert",
-            "version": "1.2.0",
-            "source": {
-                "type": "git",
-                "url": "https://github.com/webmozart/assert.git",
-                "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f"
-            },
-            "dist": {
-                "type": "zip",
-                "url": "https://api.github.com/repos/webmozart/assert/zipball/2db61e59ff05fe5126d152bd0655c9ea113e550f",
-                "reference": "2db61e59ff05fe5126d152bd0655c9ea113e550f",
-                "shasum": ""
-            },
-            "require": {
-                "php": "^5.3.3 || ^7.0"
-            },
-            "require-dev": {
-                "phpunit/phpunit": "^4.6",
-                "sebastian/version": "^1.0.1"
-            },
-            "type": "library",
-            "extra": {
-                "branch-alias": {
-                    "dev-master": "1.3-dev"
-                }
-            },
-            "autoload": {
-                "psr-4": {
-                    "Webmozart\\Assert\\": "src/"
-                }
-            },
-            "notification-url": "https://packagist.org/downloads/",
-            "license": [
-                "MIT"
-            ],
-            "authors": [
-                {
-                    "name": "Bernhard Schussek",
-                    "email": "bschussek@gmail.com"
-                }
-            ],
-            "description": "Assertions to validate method input/output with nice error messages.",
-            "keywords": [
-                "assert",
-                "check",
-                "validate"
-            ],
-            "time": "2016-11-23T20:04:58+00:00"
         }
     ],
     "aliases": [],
diff --git a/db/upgrade.php b/db/upgrade.php
index abb333f65b1d7a7a88299ade56f9a6fdf964ef89..f402a36122f254ecc78e07635c3a759a16f828b6 100644
--- a/db/upgrade.php
+++ b/db/upgrade.php
@@ -14,6 +14,8 @@
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
+defined('MOODLE_INTERNAL') || die();
+
 /**
  * xAPI log store upgrade.
  *
@@ -61,7 +63,14 @@ function xmldb_logstore_xapi_upgrade($oldversion) {
         // Adding indexes to table logstore_xapi_log.
         $table->add_index('timecreated', XMLDB_INDEX_NOTUNIQUE, array('timecreated'));
         $table->add_index('course-time', XMLDB_INDEX_NOTUNIQUE, array('courseid', 'anonymous', 'timecreated'));
-        $table->add_index('user-module', XMLDB_INDEX_NOTUNIQUE, array('userid', 'contextlevel', 'contextinstanceid', 'crud', 'edulevel', 'timecreated'));
+        $table->add_index('user-module', XMLDB_INDEX_NOTUNIQUE, array(
+            'userid',
+            'contextlevel',
+            'contextinstanceid',
+            'crud',
+            'edulevel',
+            'timecreated'
+        ));
 
         // Conditionally launch create table for logstore_xapi_log.
         if (!$dbman->table_exists($table)) {
diff --git a/docs/developers.md b/docs/developers.md
index 25e91e5b2fe0714939799789eca09d8af57e5d3e..ed8412467d3ed52aff9d20d25fefa64bc4e73434 100644
--- a/docs/developers.md
+++ b/docs/developers.md
@@ -26,10 +26,23 @@ If you've read the [plugin design](design.md) you should understand what each of
 - [Moodle to xAPI Translator](https://github.com/LearningLocker/Moodle-xAPI-Translator/blob/master/docs/readme.md#adding-events)
 - [xAPI Recipe Emitter](https://github.com/LearningLocker/xAPI-Recipe-Emitter/blob/master/docs/readme.md#adding-events)
 
-##PHPUnit Test Filter
-All PHPUnit tests should pass, but if you'd like to only run the tests for specific events, add the 'filter' option.
+## PHPUnit
+Run these with the [Moodle PHPUnit test framework](https://docs.moodle.org/dev/PHPUnit):
+
+```
+vendor/bin/phpunit --testsuite logstore_xapi_testsuite
+```
+
+### Test Filter
+All PHPUnit tests should pass, but if you'd like to only run the tests for specific events, add the `--filter` option:
+
+```
+vendor/bin/phpunit --testsuite logstore_xapi_testsuite --filter <Test_Name>
+```
+
+e.g.:
 ```
-vendor/bin/phpunit --filter <Test_Name>
+vendor/bin/phpunit --testsuite logstore_xapi_testsuite --filter course_completed_test
 ```
 
 ## Release Process
diff --git a/lib/emitter/docs/examples/AssignmentGraded.json b/lib/emitter/docs/examples/assignment_graded.json
similarity index 100%
rename from lib/emitter/docs/examples/AssignmentGraded.json
rename to lib/emitter/docs/examples/assignment_graded.json
diff --git a/lib/emitter/docs/examples/AssignmentSubmitted.json b/lib/emitter/docs/examples/assignment_submitted.json
similarity index 100%
rename from lib/emitter/docs/examples/AssignmentSubmitted.json
rename to lib/emitter/docs/examples/assignment_submitted.json
diff --git a/lib/emitter/docs/examples/AttemptCompleted.json b/lib/emitter/docs/examples/attempt_completed.json
similarity index 100%
rename from lib/emitter/docs/examples/AttemptCompleted.json
rename to lib/emitter/docs/examples/attempt_completed.json
diff --git a/lib/emitter/docs/examples/AttemptStarted.json b/lib/emitter/docs/examples/attempt_started.json
similarity index 100%
rename from lib/emitter/docs/examples/AttemptStarted.json
rename to lib/emitter/docs/examples/attempt_started.json
diff --git a/lib/emitter/docs/examples/Attended.json b/lib/emitter/docs/examples/attended.json
similarity index 100%
rename from lib/emitter/docs/examples/Attended.json
rename to lib/emitter/docs/examples/attended.json
diff --git a/lib/emitter/docs/examples/CourseCompleted.json b/lib/emitter/docs/examples/course_completed.json
similarity index 100%
rename from lib/emitter/docs/examples/CourseCompleted.json
rename to lib/emitter/docs/examples/course_completed.json
diff --git a/lib/emitter/docs/examples/CourseViewed.json b/lib/emitter/docs/examples/course_viewed.json
similarity index 100%
rename from lib/emitter/docs/examples/CourseViewed.json
rename to lib/emitter/docs/examples/course_viewed.json
diff --git a/lib/emitter/docs/examples/DiscussionViewed.json b/lib/emitter/docs/examples/discussion_viewed.json
similarity index 100%
rename from lib/emitter/docs/examples/DiscussionViewed.json
rename to lib/emitter/docs/examples/discussion_viewed.json
diff --git a/lib/emitter/docs/examples/EnrolmentCreated.json b/lib/emitter/docs/examples/enrolment_created.json
similarity index 100%
rename from lib/emitter/docs/examples/EnrolmentCreated.json
rename to lib/emitter/docs/examples/enrolment_created.json
diff --git a/lib/emitter/docs/examples/EventEnrol.json b/lib/emitter/docs/examples/event_enrol.json
similarity index 100%
rename from lib/emitter/docs/examples/EventEnrol.json
rename to lib/emitter/docs/examples/event_enrol.json
diff --git a/lib/emitter/docs/examples/EventUnenrol.json b/lib/emitter/docs/examples/event_unenrol.json
similarity index 100%
rename from lib/emitter/docs/examples/EventUnenrol.json
rename to lib/emitter/docs/examples/event_unenrol.json
diff --git a/lib/emitter/docs/examples/ModuleViewed.json b/lib/emitter/docs/examples/module_viewed.json
similarity index 100%
rename from lib/emitter/docs/examples/ModuleViewed.json
rename to lib/emitter/docs/examples/module_viewed.json
diff --git a/lib/emitter/docs/examples/QuestionAnswered.json b/lib/emitter/docs/examples/question_answered.json
similarity index 100%
rename from lib/emitter/docs/examples/QuestionAnswered.json
rename to lib/emitter/docs/examples/question_answered.json
diff --git a/lib/emitter/docs/examples/ScormEvent.json b/lib/emitter/docs/examples/scorm_event.json
similarity index 100%
rename from lib/emitter/docs/examples/ScormEvent.json
rename to lib/emitter/docs/examples/scorm_event.json
diff --git a/lib/emitter/docs/examples/ScormLaunched.json b/lib/emitter/docs/examples/scorm_launched.json
similarity index 100%
rename from lib/emitter/docs/examples/ScormLaunched.json
rename to lib/emitter/docs/examples/scorm_launched.json
diff --git a/lib/emitter/docs/examples/ScormScorerawSubmitted.json b/lib/emitter/docs/examples/scorm_score_raw_submitted.json
similarity index 100%
rename from lib/emitter/docs/examples/ScormScorerawSubmitted.json
rename to lib/emitter/docs/examples/scorm_score_raw_submitted.json
diff --git a/lib/emitter/docs/examples/ScormStatusSubmitted.json b/lib/emitter/docs/examples/scorm_status_submitted.json
similarity index 100%
rename from lib/emitter/docs/examples/ScormStatusSubmitted.json
rename to lib/emitter/docs/examples/scorm_status_submitted.json
diff --git a/lib/emitter/docs/examples/UserLoggedin.json b/lib/emitter/docs/examples/user_loggedin.json
similarity index 100%
rename from lib/emitter/docs/examples/UserLoggedin.json
rename to lib/emitter/docs/examples/user_loggedin.json
diff --git a/lib/emitter/docs/examples/UserLoggedout.json b/lib/emitter/docs/examples/user_loggedout.json
similarity index 100%
rename from lib/emitter/docs/examples/UserLoggedout.json
rename to lib/emitter/docs/examples/user_loggedout.json
diff --git a/lib/emitter/docs/examples/UserRegistered.json b/lib/emitter/docs/examples/user_registered.json
similarity index 100%
rename from lib/emitter/docs/examples/UserRegistered.json
rename to lib/emitter/docs/examples/user_registered.json
diff --git a/lib/emitter/src/Controller.php b/lib/emitter/src/Controller.php
index 3246a00acd72a0d1dad2303b9616205acef4f3eb..93b6271606d899b37563b684014e1fe02b2dfa1f 100755
--- a/lib/emitter/src/Controller.php
+++ b/lib/emitter/src/Controller.php
@@ -1,4 +1,23 @@
-<?php namespace XREmitter;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \stdClass as PhpObj;
 
 class Controller extends PhpObj {
@@ -39,7 +58,7 @@ class Controller extends PhpObj {
      * @param [String => Mixed] $events
      * @return [String => Mixed]
      */
-    public function createEvents(array $events) {
+    public function create_events(array $events) {
         $statements = [];
         foreach ($events as $index => $opts) {
             $route = isset($opts['recipe']) ? $opts['recipe'] : '';
@@ -50,6 +69,6 @@ class Controller extends PhpObj {
                 array_push($statements, $service->read($opts));
             }
         }
-        return $this->repo->createEvents($statements);
+        return $this->repo->create_events($statements);
     }
 }
diff --git a/lib/emitter/src/Events/AssignmentGraded.php b/lib/emitter/src/Events/AssignmentGraded.php
index 7f62545a5f76b58df5ae38c6bed2b0730cf22cac..fccdfe51f0934b1e3b435817f1d53c25f44d19cf 100644
--- a/lib/emitter/src/Events/AssignmentGraded.php
+++ b/lib/emitter/src/Events/AssignmentGraded.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AssignmentGraded extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'received grade for'
     ];
 
@@ -13,10 +31,10 @@ class AssignmentGraded extends Event {
      */
     public function read(array $opts) {
         $instructor = parent::read($opts)['actor'];
-        $statement =  array_merge_recursive(parent::read($opts), [
+        $statement = array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/scored',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
             'result' => [
                 'score' => [
@@ -28,18 +46,18 @@ class AssignmentGraded extends Event {
                 'completion' => $opts['grade_completed'],
                 'response' => $opts['grade_comment']
             ],
-            'object' => $this->readModule($opts),
+            'object' => $this->read_module($opts),
             'context' => [
                 'contextActivities' => [
                     'parent' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                     ],
                 ],
                 'instructor' => $instructor
             ],
         ]);
 
-        //Excluded from array merge to make sure that the actor is overwritten e.g. if a different IFI is used. 
+        // Excluded from array merge to make sure that the actor is overwritten e.g. if a different IFI is used.
         $statement['actor'] = [
             'objectType' => 'Agent',
             'name' => $opts['graded_user_name'],
@@ -55,4 +73,4 @@ class AssignmentGraded extends Event {
 
         return $statement;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/AssignmentSubmitted.php b/lib/emitter/src/Events/AssignmentSubmitted.php
index 3c3bff7e5f4cc67a71fb0f2999160fdaed47bf3f..9d6af212d72d9b4a1c7a2b769a5b89414bcb7f5a 100644
--- a/lib/emitter/src/Events/AssignmentSubmitted.php
+++ b/lib/emitter/src/Events/AssignmentSubmitted.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AssignmentSubmitted extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'completed'
     ];
 
@@ -15,16 +33,16 @@ class AssignmentSubmitted extends Event {
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/completed',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readModule($opts),
+            'object' => $this->read_module($opts),
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                     ],
                 ],
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/AttemptCompleted.php b/lib/emitter/src/Events/AttemptCompleted.php
index 4fc9efb9539d3fc46dfd5ce96ce42c781068ab9d..d04ef880a1089fd21263eb4a97abeb9e4ad0d10a 100644
--- a/lib/emitter/src/Events/AttemptCompleted.php
+++ b/lib/emitter/src/Events/AttemptCompleted.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AttemptCompleted extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'completed'
     ];
 
@@ -16,7 +34,7 @@ class AttemptCompleted extends Event {
         $statement = [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/completed',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
             'result' => [
                 'score' => [
@@ -43,7 +61,7 @@ class AttemptCompleted extends Event {
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                         [
                             'id' => $opts['attempt_url'],
                             'definition' => [
@@ -67,4 +85,4 @@ class AttemptCompleted extends Event {
 
         return array_merge_recursive(parent::read($opts), $statement);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/AttemptStarted.php b/lib/emitter/src/Events/AttemptStarted.php
index 6c1d5ca23d82bf8ee9448137d2b6f365401a2daf..be33ca63d148754fa59cdd74906fb3a0f3f9d818 100644
--- a/lib/emitter/src/Events/AttemptStarted.php
+++ b/lib/emitter/src/Events/AttemptStarted.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AttemptStarted extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'started'
     ];
 
@@ -15,7 +33,7 @@ class AttemptStarted extends Event {
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://activitystrea.ms/schema/1.0/start',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
             'object' => [
                 'id' => $opts['attempt_url'],
@@ -32,11 +50,11 @@ class AttemptStarted extends Event {
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
-                        $this->readModule($opts),
+                        $this->read_course($opts),
+                        $this->read_module($opts),
                     ],
                 ],
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/Attended.php b/lib/emitter/src/Events/Attended.php
index 1b524c1b4edc5db51c9c56dfe96884fb5b795e05..7ecb5274609d3985dfde3c3116cce2cc41a04635 100755
--- a/lib/emitter/src/Events/Attended.php
+++ b/lib/emitter/src/Events/Attended.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class Attended extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'attended'
     ];
 
@@ -15,7 +33,7 @@ class Attended extends Event {
         $statement = array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/attended',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
             'object' => [
                 'id' => $opts['session_url'],
@@ -34,13 +52,13 @@ class Attended extends Event {
                 'completion' => $opts['attempt_completion']
             ],
             'context' => [
-                'instructor' => $this->readUser($opts, 'user'),
+                'instructor' => $this->read_user($opts, 'user'),
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                     ],
                     'parent' => [
-                        $this->readModule($opts),
+                        $this->read_module($opts),
                     ],
                     'category' => [
                         [
@@ -54,9 +72,9 @@ class Attended extends Event {
             ],
         ]);
 
-        // Overwrite actor, don't merge it. 
-        $statement['actor'] = $this->readUser($opts, 'attendee');
+        // Overwrite actor, don't merge it.
+        $statement['actor'] = $this->read_user($opts, 'attendee');
 
         return $statement;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/CourseCompleted.php b/lib/emitter/src/Events/CourseCompleted.php
index 456a7a7bf7a8240699fb9716682306fac873670e..bb8358926b5a9caccaeec24116e88219f4a7c947 100644
--- a/lib/emitter/src/Events/CourseCompleted.php
+++ b/lib/emitter/src/Events/CourseCompleted.php
@@ -1,27 +1,36 @@
 <?php
-/**
- * Created by PhpStorm.
- * User: lee.kirkland
- * Date: 5/2/2016
- * Time: 5:15 PM
- */
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 namespace XREmitter\Events;
 
+defined('MOODLE_INTERNAL') || die();
 
 /**
  * Class CourseCompleted
  * @package XREmitter\Events
  */
-class CourseCompleted extends Event
-{
+class CourseCompleted extends Event {
     /**
-     * Sets the language equivalent for completed. 
+     * Sets the language equivalent for completed.
      * @var array
      */
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'completed'
     ];
+
     /**
      * Reads data for an event.
      * @param [String => Mixed] $opts
@@ -32,9 +41,9 @@ class CourseCompleted extends Event
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/completed',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readCourse($opts),
+            'object' => $this->read_course($opts),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/CourseViewed.php b/lib/emitter/src/Events/CourseViewed.php
index 9cb5f1e25f0152d401e4bc29184c007428c247b2..bc67d79667de8f227f70a7a26e7079fce0b87cbc 100644
--- a/lib/emitter/src/Events/CourseViewed.php
+++ b/lib/emitter/src/Events/CourseViewed.php
@@ -1,4 +1,22 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class CourseViewed extends Viewed {
     /**
@@ -9,7 +27,7 @@ class CourseViewed extends Viewed {
      */
     public function read(array $opts) {
         return array_merge(parent::read($opts), [
-            'object' => $this->readCourse($opts),
+            'object' => $this->read_course($opts),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/DiscussionViewed.php b/lib/emitter/src/Events/DiscussionViewed.php
index 01478aadbcc795836ce2c0d4345666616393c156..36e43b2b29a74560ec8825aaa0ad56d1bece5f26 100644
--- a/lib/emitter/src/Events/DiscussionViewed.php
+++ b/lib/emitter/src/Events/DiscussionViewed.php
@@ -1,4 +1,22 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class DiscussionViewed extends Viewed {
     /**
@@ -9,15 +27,15 @@ class DiscussionViewed extends Viewed {
      */
     public function read(array $opts) {
         return array_merge_recursive(parent::read($opts), [
-            'object' => $this->readDiscussion($opts, 'discussion', 'http://id.tincanapi.com/activitytype/discussion'),
+            'object' => $this->read_discussion($opts, 'discussion', 'http://id.tincanapi.com/activitytype/discussion'),
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts, 'course', 'http://adlnet.gov/expapi/activities/course'),
-                        $this->readModule($opts),
+                        $this->read_course($opts, 'course', 'http://adlnet.gov/expapi/activities/course'),
+                        $this->read_module($opts),
                     ],
                 ],
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/EnrolmentCreated.php b/lib/emitter/src/Events/EnrolmentCreated.php
index 5382deaee653cfeb50ae831aaa8ff37a969e5d99..5228a64fc4912a6045aea636dc179015809eafe0 100644
--- a/lib/emitter/src/Events/EnrolmentCreated.php
+++ b/lib/emitter/src/Events/EnrolmentCreated.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class EnrolmentCreated extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'enrolled onto'
     ];
 
@@ -15,12 +33,12 @@ class EnrolmentCreated extends Event {
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://www.tincanapi.co.uk/verbs/enrolled_onto_learning_plan',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readCourse($opts),
+            'object' => $this->read_course($opts),
             'context' => [
-                'instructor' => $this->readUser($opts, 'instructor'),
+                'instructor' => $this->read_user($opts, 'instructor'),
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/Event.php b/lib/emitter/src/Events/Event.php
index f3c78acb367026baeffd8fcd84b200c6b69f8a7d..9fc100332591823f599148f0978a2cd992a3a7bd 100644
--- a/lib/emitter/src/Events/Event.php
+++ b/lib/emitter/src/Events/Event.php
@@ -1,8 +1,27 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \stdClass as PhpObj;
 
 abstract class Event extends PhpObj {
-    protected static $verbDisplay;
+    protected static $verbdisplay;
 
     /**
      * Reads data for an event.
@@ -11,7 +30,7 @@ abstract class Event extends PhpObj {
      */
     public function read(array $opts) {
         return [
-            'actor' => $this->readUser($opts, 'user'),
+            'actor' => $this->read_user($opts, 'user'),
             'context' => [
                 'platform' => $opts['context_platform'],
                 'language' => $opts['context_lang'],
@@ -21,10 +40,10 @@ abstract class Event extends PhpObj {
                 ],
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readApp($opts)
+                        $this->read_app($opts)
                     ],
                     'category' => [
-                        $this->readSource($opts)
+                        $this->read_source($opts)
                     ]
                 ],
             ],
@@ -32,7 +51,7 @@ abstract class Event extends PhpObj {
         ];
     }
 
-    protected function readUser(array $opts, $key) {
+    protected function read_user(array $opts, $key) {
         if (isset($opts['sendmbox']) && $opts['sendmbox'] == true) {
             return [
                 'name' => $opts[$key.'_name'],
@@ -49,7 +68,7 @@ abstract class Event extends PhpObj {
         }
     }
 
-    protected function readActivity(array $opts, $key) {
+    protected function read_activity(array $opts, $key) {
         $activity = [
             'id' => $opts[$key.'_url'],
             'definition' => [
@@ -71,34 +90,34 @@ abstract class Event extends PhpObj {
         return $activity;
     }
 
-    protected function readCourse($opts) {
-        return $this->readActivity($opts, 'course');
+    protected function read_course($opts) {
+        return $this->read_activity($opts, 'course');
     }
 
-    protected function readApp($opts) {
-        return $this->readActivity($opts, 'app');
+    protected function read_app($opts) {
+        return $this->read_activity($opts, 'app');
     }
 
-    protected function readSource($opts) {
-        return $this->readActivity($opts, 'source');
+    protected function read_source($opts) {
+        return $this->read_activity($opts, 'source');
     }
 
-    protected function readModule($opts) {
-        return $this->readActivity($opts, 'module');
+    protected function read_module($opts) {
+        return $this->read_activity($opts, 'module');
     }
 
-    protected function readDiscussion($opts) {
-        return $this->readActivity($opts, 'discussion');
+    protected function read_discussion($opts) {
+        return $this->read_activity($opts, 'discussion');
     }
 
-    protected function readQuestion($opts) {
+    protected function read_question($opts) {
         $opts['question_type'] = 'http://adlnet.gov/expapi/activities/cmi.interaction';
-        $question = $this->readActivity($opts, 'question');
+        $question = $this->read_activity($opts, 'question');
 
         $question['definition']['interactionType'] = $opts['interaction_type'];
         $question['definition']['correctResponsesPattern'] = $opts['interaction_correct_responses'];
 
-        $supportedComponentLists = [
+        $supportedcomponentlists = [
             'choice' => ['choices'],
             'sequencing' => ['choices'],
             'likert' => ['scale'],
@@ -111,27 +130,27 @@ abstract class Event extends PhpObj {
             'other' => []
         ];
 
-        foreach ($supportedComponentLists[$opts['interaction_type']] as $index => $listType) {
-            if (isset($opts['interaction_'.$listType]) && !is_null($opts['interaction_'.$listType])) {
-                $componentList = [];
-                foreach ($opts['interaction_'.$listType] as $id => $description) {
-                    array_push($componentList, (object)[
+        foreach ($supportedcomponentlists[$opts['interaction_type']] as $index => $listtype) {
+            if (isset($opts['interaction_' . $listtype]) && !is_null($opts['interaction_' . $listtype])) {
+                $componentlist = [];
+                foreach ($opts['interaction_' . $listtype] as $id => $description) {
+                    array_push($componentlist, (object)[
                         'id' => (string) $id,
                         'description' => [
                             $opts['context_lang'] => $description,
                         ]
                     ]);
                 }
-                $question['definition'][$listType] = $componentList;
+                $question['definition'][$listtype] = $componentlist;
             }
         }
         return $question;
     }
 
-    protected function readVerbDisplay($opts) {
+    protected function read_verb_display($opts) {
         $lang = $opts['context_lang'];
-        $lang = isset(static::$verbDisplay[$lang]) ? $lang : array_keys(static::$verbDisplay)[0];
-        return [$lang => static::$verbDisplay[$lang]];
+        $lang = isset(static::$verbdisplay[$lang]) ? $lang : array_keys(static::$verbdisplay)[0];
+        return [$lang => static::$verbdisplay[$lang]];
     }
 
 }
diff --git a/lib/emitter/src/Events/EventEnrol.php b/lib/emitter/src/Events/EventEnrol.php
index 949f2d5b142372e0664e7d7b6b7a5f57c7cf60b4..f1486a6ff6f903bc406b191bc0c00aed5af8be36 100755
--- a/lib/emitter/src/Events/EventEnrol.php
+++ b/lib/emitter/src/Events/EventEnrol.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class EventEnrol extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'registered for'
     ];
 
@@ -15,7 +33,7 @@ class EventEnrol extends Event {
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/registered',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
             'object' => [
                 'id' => $opts['session_url'],
@@ -32,21 +50,22 @@ class EventEnrol extends Event {
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                     ],
                     'parent' => [
-                        $this->readModule($opts),
+                        $this->read_module($opts),
                     ],
                     'category' => [
                             [
-                            'id' => 'http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#detailed',
-                            'definition' => [
-                                'type' => 'http://id.tincanapi.com/activitytype/recipe'
+                                'id' => 'http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#detailed',
+                                'definition' => [
+                                    'type' => 'http://id.tincanapi.com/activitytype/recipe'
+                                ]
                             ]
-                        ]
+                        ],
                     ],
                 ],
-            ],
-        ]);
+            ]
+        );
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/EventUnenrol.php b/lib/emitter/src/Events/EventUnenrol.php
index a4e63935da49ac9e94717e556025926c252d6b4d..64b47ecec57ff365c87b74ed2277a6ed473cd6b9 100755
--- a/lib/emitter/src/Events/EventUnenrol.php
+++ b/lib/emitter/src/Events/EventUnenrol.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class EventUnenrol extends EventEnrol {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'unregistered from'
     ];
 
@@ -15,8 +33,8 @@ class EventUnenrol extends EventEnrol {
         $statement = parent::read($opts);
         $statement['verb'] = [
             'id' => 'http://id.tincanapi.com/verb/unregistered',
-            'display' => $this->readVerbDisplay($opts),
+            'display' => $this->read_verb_display($opts),
         ];
         return $statement;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/ModuleViewed.php b/lib/emitter/src/Events/ModuleViewed.php
index b1abbafe59189528dae57076f43951ec5ed36677..ddab44e05141e7aee93f29ca15703aa8c1fbbd58 100644
--- a/lib/emitter/src/Events/ModuleViewed.php
+++ b/lib/emitter/src/Events/ModuleViewed.php
@@ -1,4 +1,22 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ModuleViewed extends Viewed {
     /**
@@ -9,14 +27,14 @@ class ModuleViewed extends Viewed {
      */
     public function read(array $opts) {
         return array_merge_recursive(parent::read($opts), [
-            'object' => $this->readModule($opts),
+            'object' => $this->read_module($opts),
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                     ],
                 ],
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/QuestionAnswered.php b/lib/emitter/src/Events/QuestionAnswered.php
index cffed7ae5eef417937746c9ec57bef1804605618..ef6d2d1c5c13122388a03ee52e5fcf68c269e6c6 100644
--- a/lib/emitter/src/Events/QuestionAnswered.php
+++ b/lib/emitter/src/Events/QuestionAnswered.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class QuestionAnswered extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'answered'
     ];
 
@@ -16,7 +34,7 @@ class QuestionAnswered extends Event {
         $statement = [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/answered',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
             'result' => [
                 'score' => [
@@ -28,14 +46,14 @@ class QuestionAnswered extends Event {
                 'completion' => $opts['attempt_completed'],
                 'response' => $opts['attempt_response']
             ],
-            'object' => $this->readQuestion($opts),
+            'object' => $this->read_question($opts),
             'context' => [
                 'contextActivities' => [
                     'parent' => [
-                        $this->readModule($opts)
+                        $this->read_module($opts)
                     ],
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                         [
                             'id' => $opts['attempt_url']
                         ],
@@ -50,4 +68,4 @@ class QuestionAnswered extends Event {
 
         return array_merge_recursive(parent::read($opts), $statement);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/ScormEvent.php b/lib/emitter/src/Events/ScormEvent.php
index 2181f755cb84cb2d3ebfde6705098aa3ae7e3ae6..2c93663ce254f2fdcf8982f649507c43c4d45169 100644
--- a/lib/emitter/src/Events/ScormEvent.php
+++ b/lib/emitter/src/Events/ScormEvent.php
@@ -1,4 +1,22 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormEvent extends Event {
     /**
@@ -9,48 +27,48 @@ class ScormEvent extends Event {
      */
     public function read(array $opts) {
         return array_merge(parent::read($opts), [
-            'object' => $this->readModule($opts),
+            'object' => $this->read_module($opts),
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
-                        $this->readScormScoes($opts),
+                        $this->read_course($opts),
+                        $this->read_scorm_scoes($opts),
                     ],
                 ],
             ],
         ]);
     }
 
-    protected function readScormVerb($opts) {
-        $scormStatus = $opts['scorm_status'];
-        $verbBaseUrl = 'http://adlnet.gov/expapi/verbs/';
+    protected function read_scorm_verb($opts) {
+        $scormstatus = $opts['scorm_status'];
+        $verbbaseurl = 'http://adlnet.gov/expapi/verbs/';
         $verb = array();
 
-        switch ($scormStatus) {
+        switch ($scormstatus) {
             case 'failed':
-                $verbUrl = $verbBaseUrl . $scormStatus;
-                $verb = $scormStatus;
+                $verburl = $verbbaseurl . $scormstatus;
+                $verb = $scormstatus;
                 break;
             case 'passed':
-                $verbUrl = $verbBaseUrl . $scormStatus;
-                $verb = $scormStatus;
+                $verburl = $verbbaseurl . $scormstatus;
+                $verb = $scormstatus;
                 break;
             default:
-                $verbUrl = $verbBaseUrl . 'completed';
+                $verburl = $verbbaseurl . 'completed';
                 $verb = 'completed';
         }
 
-        static::$verbDisplay = ['en' => $verb];
+        static::$verbdisplay = ['en' => $verb];
 
         $lang = [
-            'id' => $verbUrl,
-            'display' => $this->readVerbDisplay($opts),
+            'id' => $verburl,
+            'display' => $this->read_verb_display($opts),
         ];
 
         return $lang;
     }
 
-    protected function readScormScoes($opts) {
+    protected function read_scorm_scoes($opts) {
         return [
             'id' => $opts['module_url'],
             'definition' => [
diff --git a/lib/emitter/src/Events/ScormLaunched.php b/lib/emitter/src/Events/ScormLaunched.php
index a43d584a8bd0dbbd09354e1d9cfa5b1aaf971d4f..3028172a507071ed1a8ffafaec94e72de65983c3 100644
--- a/lib/emitter/src/Events/ScormLaunched.php
+++ b/lib/emitter/src/Events/ScormLaunched.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormLaunched extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'launched'
     ];
 
@@ -15,16 +33,16 @@ class ScormLaunched extends Event {
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/launched',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readModule($opts),
+            'object' => $this->read_module($opts),
             'context' => [
                 'contextActivities' => [
                     'grouping' => [
-                        $this->readCourse($opts),
+                        $this->read_course($opts),
                     ],
                 ],
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/ScormScoreRawSubmitted.php b/lib/emitter/src/Events/ScormScoreRawSubmitted.php
index e32142de2461070ee44c1be86db0f77c6bd2e4e1..898a0f9b1f0af9be91bd3af66546340bd6d30b4d 100644
--- a/lib/emitter/src/Events/ScormScoreRawSubmitted.php
+++ b/lib/emitter/src/Events/ScormScoreRawSubmitted.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormScoreRawSubmitted extends ScormEvent {
-    protected static $verbDisplay;
+    protected static $verbdisplay;
 
     /**
      * Reads data for an event.
@@ -11,7 +29,7 @@ class ScormScoreRawSubmitted extends ScormEvent {
      */
     public function read(array $opts) {
         return array_merge_recursive(parent::read($opts), [
-            'verb' => $this->readScormVerb($opts),
+            'verb' => $this->read_scorm_verb($opts),
             'result' => [
                 'score' => [
                     'raw' => $opts['scorm_score_raw'],
diff --git a/lib/emitter/src/Events/ScormStatusSubmitted.php b/lib/emitter/src/Events/ScormStatusSubmitted.php
index 9837023c69aa2463e76a5b54333ce977eda5a983..85e52089c9ec3db19c23deb0b677071f3b5e95a9 100644
--- a/lib/emitter/src/Events/ScormStatusSubmitted.php
+++ b/lib/emitter/src/Events/ScormStatusSubmitted.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormStatusSubmitted extends ScormEvent {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'completed'
     ];
 
@@ -15,7 +33,7 @@ class ScormStatusSubmitted extends ScormEvent {
         return array_merge_recursive(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/completed',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
         ]);
     }
diff --git a/lib/emitter/src/Events/UserLoggedin.php b/lib/emitter/src/Events/UserLoggedin.php
index e6bf20daf1d421c4e50f62e217aaffba7ff9422c..4a28d4e96f91db813ff4ebed648042653f2ed748 100644
--- a/lib/emitter/src/Events/UserLoggedin.php
+++ b/lib/emitter/src/Events/UserLoggedin.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UserLoggedin extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'logged in to'
     ];
 
@@ -15,9 +33,9 @@ class UserLoggedin extends Event {
         return array_merge(parent::read($opts), [
             'verb' => [
                 'id' => 'https://brindlewaye.com/xAPITerms/verbs/loggedin/',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readApp($opts),
+            'object' => $this->read_app($opts),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/UserLoggedout.php b/lib/emitter/src/Events/UserLoggedout.php
index 33f6aaf76a41c77b738684956007a8e88a70656e..4859d6f03703e70137e5c2403e11fcd0f8f45c2a 100644
--- a/lib/emitter/src/Events/UserLoggedout.php
+++ b/lib/emitter/src/Events/UserLoggedout.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UserLoggedout extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'logged out of'
     ];
 
@@ -15,9 +33,9 @@ class UserLoggedout extends Event {
         return array_merge(parent::read($opts), [
             'verb' => [
                 'id' => 'https://brindlewaye.com/xAPITerms/verbs/loggedout/',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readApp($opts),
+            'object' => $this->read_app($opts),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/UserRegistered.php b/lib/emitter/src/Events/UserRegistered.php
index 0b43d260873b5b0b5893b156f153b06c7e32c55e..6371a0c2217567be044c0b9a84f4aca27dba0248 100644
--- a/lib/emitter/src/Events/UserRegistered.php
+++ b/lib/emitter/src/Events/UserRegistered.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UserRegistered extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'registered to'
     ];
 
@@ -15,9 +33,9 @@ class UserRegistered extends Event {
         return array_merge(parent::read($opts), [
             'verb' => [
                 'id' => 'http://adlnet.gov/expapi/verbs/registered',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
-            'object' => $this->readApp($opts),
+            'object' => $this->read_app($opts),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Events/Viewed.php b/lib/emitter/src/Events/Viewed.php
index 9e218d44bb53620c7b1d8428b6595b36e8d170c1..84bdafd93628f16d359afa35b47239ce2767afcd 100644
--- a/lib/emitter/src/Events/Viewed.php
+++ b/lib/emitter/src/Events/Viewed.php
@@ -1,7 +1,25 @@
-<?php namespace XREmitter\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 abstract class Viewed extends Event {
-    protected static $verbDisplay = [
+    protected static $verbdisplay = [
         'en' => 'viewed'
     ];
 
@@ -15,8 +33,8 @@ abstract class Viewed extends Event {
         return array_merge(parent::read($opts), [
             'verb' => [
                 'id' => 'http://id.tincanapi.com/verb/viewed',
-                'display' => $this->readVerbDisplay($opts),
+                'display' => $this->read_verb_display($opts),
             ],
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/emitter/src/Repository.php b/lib/emitter/src/Repository.php
index 8b97756d58b367785e9476c612635f5b9c5df453..a6539062b08d6cb7ccefb77b29137bd58fb44d1c 100644
--- a/lib/emitter/src/Repository.php
+++ b/lib/emitter/src/Repository.php
@@ -1,4 +1,23 @@
-<?php namespace XREmitter;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \TinCan\RemoteLRS as TinCanRemoteLrs;
 use \TinCan\Statement as TinCanStatement;
 use \stdClass as PhpObj;
@@ -20,7 +39,7 @@ class Repository extends PhpObj {
      * @param [string => mixed] $statements
      * @return [string => mixed]
      */
-    public function createEvents(array $statements) {
+    public function create_events(array $statements) {
         $response = $this->store->saveStatements($statements);
         return [
             "statements" => $statements,
diff --git a/lib/emitter/tests/AssignmentGradedTest.php b/lib/emitter/tests/AssignmentGradedTest.php
deleted file mode 100644
index 2456c152b653801eee606f69f90135b16c2b78da..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/AssignmentGradedTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\AssignmentGraded as Event;
-
-class AssignmentGradedTest extends EventTest {
-    protected static $recipeName = 'assignment_graded';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->constructUser('graded_user'),
-            [
-                'grade_score_raw' => 47,
-                'grade_score_min' => 0,
-                'grade_score_max' => 100,
-                'grade_score_scaled' => 0.47,
-                'grade_success' => true,
-                'grade_completed' => true,
-                'grade_comment' => 'test comment from instructor'
-            ]
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        $this->assertUser($input, $output['actor'], 'graded_user');
-        $this->assertObject('app', $input, $output['context']['contextActivities']['grouping'][0]);
-        $this->assertObject('source', $input, $output['context']['contextActivities']['category'][0]);
-        $this->assertLog($input, $output);
-        $this->assertInfo(
-            $input['context_info'],
-            $output['context']['extensions']['http://lrs.learninglocker.net/define/extensions/info']
-        );
-        $this->assertValidXapiStatement($output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/scored', 'received grade for', $output['verb']);
-        $this->assertObject('module', $input, $output['object']);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['parent'][0]);
-        $this->assertEquals($input['grade_score_raw'], $output['result']['score']['raw']);
-        $this->assertEquals($input['grade_score_min'], $output['result']['score']['min']);
-        $this->assertEquals($input['grade_score_max'], $output['result']['score']['max']);
-        $this->assertEquals($input['grade_score_scaled'], $output['result']['score']['scaled']);
-        $this->assertEquals($input['grade_success'], $output['result']['success']);
-        $this->assertEquals($input['grade_completed'], $output['result']['completion']);
-        $this->assertEquals($input['grade_comment'], $output['result']['response']);
-        $this->assertUser($input, $output['context']['instructor'], 'user');
-    }
-}
diff --git a/lib/emitter/tests/AssignmentSubmittedTest.php b/lib/emitter/tests/AssignmentSubmittedTest.php
deleted file mode 100644
index 8e88fef8e85d42bc998b62acd8a52f8236755cd4..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/AssignmentSubmittedTest.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\AssignmentSubmitted as Event;
-
-class AssignmentSubmittedTest extends EventTest {
-    protected static $recipeName = 'assignment_submitted';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
-        $this->assertObject('module', $input, $output['object']);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-    }
-}
diff --git a/lib/emitter/tests/AttemptCompletedTest.php b/lib/emitter/tests/AttemptCompletedTest.php
deleted file mode 100644
index 388ed37208bed8c7c7e9f0e6fd5294d48c317ba3..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/AttemptCompletedTest.php
+++ /dev/null
@@ -1,50 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\AttemptCompleted as Event;
-
-class AttemptCompletedTest extends EventTest {
-    protected static $recipeName = 'attempt_completed';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->constructAttempt()
-        );
-    }
-
-    protected function constructAttempt() {
-        return array_merge(parent::constructAttempt(), [
-            'attempt_score_raw' => 1,
-            'attempt_score_min' => 0,
-            'attempt_score_max' => 5,
-            'attempt_score_scaled' => 0.2,
-            'attempt_success' => false,
-            'attempt_completed' => true,
-            'attempt_duration' => 'P01DT',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
-        $this->assertAttempt($input, $output['context']['contextActivities']['grouping'][2]);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertObject('module', $input, $output['object']);
-        $this->assertEquals($input['attempt_score_raw'], $output['result']['score']['raw']);
-        $this->assertEquals($input['attempt_score_min'], $output['result']['score']['min']);
-        $this->assertEquals($input['attempt_score_max'], $output['result']['score']['max']);
-        $this->assertEquals($input['attempt_score_scaled'], $output['result']['score']['scaled']);
-        $this->assertEquals($input['attempt_success'], $output['result']['success']);
-        $this->assertEquals($input['attempt_completed'], $output['result']['completion']);
-        $this->assertEquals($input['attempt_duration'], $output['result']['duration']);
-    }
-}
diff --git a/lib/emitter/tests/AttemptStartedTest.php b/lib/emitter/tests/AttemptStartedTest.php
deleted file mode 100644
index ca9cdecc568ad826888f81858d4ac25e0d0fb73b..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/AttemptStartedTest.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\AttemptStarted as Event;
-
-class AttemptStartedTest extends EventTest {
-    protected static $recipeName = 'attempt_started';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->constructAttempt()
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://activitystrea.ms/schema/1.0/start', 'started', $output['verb']);
-        $this->assertObject('module', $input, $output['context']['contextActivities']['grouping'][2]);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertAttempt($input, $output['object']);
-    }
-}
diff --git a/lib/emitter/tests/AttendedTest.php b/lib/emitter/tests/AttendedTest.php
deleted file mode 100644
index fe4bdc2c4f13238d0bfb6c20f8704b865a716e1b..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/AttendedTest.php
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\Attended as Event;
-
-class AttendedTest extends EventTest {
-    protected static $recipeName = 'training_session_attend';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->contructObject('session', 'http://activitystrea.ms/schema/1.0/event'),
-            $this->constructUser('attendee'),
-            [
-                "attempt_duration" => "PT150S",
-                "attempt_completion" => true
-            ]
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        $this->assertObject('app', $input, $output['context']['contextActivities']['grouping'][0]);
-        $this->assertObject('source', $input, $output['context']['contextActivities']['category'][0]);
-        $this->assertLog($input, $output);
-        $this->assertInfo(
-            $input['context_info'],
-            $output['context']['extensions']['http://lrs.learninglocker.net/define/extensions/info']
-        );
-        $this->assertValidXapiStatement($output);
-        $this->assertUser($input, $output['actor'], 'attendee');
-        $this->assertUser($input, $output['context']['instructor'], 'user');
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/attended', 'attended', $output['verb']);
-        $this->assertObject('session', $input, $output['object']);
-        $this->assertObject('module', $input, $output['context']['contextActivities']['parent'][0]);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertEquals($input['attempt_duration'], $output['result']['duration']);
-        $this->assertEquals($input['attempt_completion'], $output['result']['completion']);
-        $this->assertEquals('http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#simple', $output['context']['contextActivities']['category'][1]['id']);
-    }
-}
diff --git a/lib/emitter/tests/CourseCompletedTest.php b/lib/emitter/tests/CourseCompletedTest.php
deleted file mode 100644
index 916434f0ef59b7e0d9db850360f6a01653033d7a..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/CourseCompletedTest.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-/**
- * Created by PhpStorm.
- * User: lee.kirkland
- * Date: 5/2/2016
- * Time: 4:52 PM
- */
-namespace XREmitter\Tests;
-use \XREmitter\Events\CourseCompleted as Event;
-
-/**
- * Class CourseCompletedTest
- * @package XREmitter\Tests
- */
-class CourseCompletedTest extends EventTest
-{
-    /**
-     * @var string
-     */
-    protected static $recipeName = 'course_completed';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    /**
-     * Construct the input for the test.
-     * @return array
-     */
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course')
-        );
-    }
-
-    /**
-     * Asserts the output is the same as the input.
-     * @param $input
-     * @param $output
-     */
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
-        $this->assertObject('course', $input, $output['object']);
-    }
-}
diff --git a/lib/emitter/tests/CourseViewedTest.php b/lib/emitter/tests/CourseViewedTest.php
deleted file mode 100644
index 892127e1854e1dc7c78c63cb089efe0c6aef8412..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/CourseViewedTest.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\CourseViewed as Event;
-
-class CourseViewedTest extends EventTest {
-    protected static $recipeName = 'course_viewed';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://id.tincanapi.com/verb/viewed', 'viewed', $output['verb']);
-        $this->assertObject('course', $input, $output['object']);
-    }
-}
diff --git a/lib/emitter/tests/DiscussionViewedTest.php b/lib/emitter/tests/DiscussionViewedTest.php
deleted file mode 100644
index 88bbd1b4cb19b046594d269792a4189781d96df5..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/DiscussionViewedTest.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\DiscussionViewed as Event;
-
-class DiscussionViewedTest extends EventTest {
-    protected static $recipeName = 'discussion_viewed';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->constructDiscussion()
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://id.tincanapi.com/verb/viewed', 'viewed', $output['verb']);
-        $this->assertObject('discussion', $input, $output['object']);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertObject('module', $input, $output['context']['contextActivities']['grouping'][2]);
-    }
-}
diff --git a/lib/emitter/tests/EnrolmentCreatedTest.php b/lib/emitter/tests/EnrolmentCreatedTest.php
deleted file mode 100644
index d6116ba795fd9b97e4baf7042e8e2e4981006dd7..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/EnrolmentCreatedTest.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\EnrolmentCreated as Event;
-
-class EnrolmentCreatedTest extends EventTest {
-    protected static $recipeName = 'enrolment_created';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->constructUser('instructor'),
-            $this->contructObject('course')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://www.tincanapi.co.uk/verbs/enrolled_onto_learning_plan', 'enrolled onto', $output['verb']);
-        $this->assertObject('course', $input, $output['object']);
-        $this->assertUser($input, $output['context']['instructor'], 'instructor');
-    }
-}
diff --git a/lib/emitter/tests/EventEnrolTest.php b/lib/emitter/tests/EventEnrolTest.php
deleted file mode 100644
index c8c19de7e6395e5d41bb956b2a43d0dcb77999f1..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/EventEnrolTest.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\EventEnrol as Event;
-
-class EventEnrolTest extends EventTest {
-    protected static $recipeName = 'training_session_enrol';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->contructObject('session', 'http://activitystrea.ms/schema/1.0/event')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertUser($input, $output['actor'], 'user');
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/registered', 'registered for', $output['verb']);
-        $this->assertObject('session', $input, $output['object']);
-        $this->assertObject('module', $input, $output['context']['contextActivities']['parent'][0]);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertEquals('http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#detailed', $output['context']['contextActivities']['category'][1]['id']);
-    }
-}
diff --git a/lib/emitter/tests/EventUnenrolTest.php b/lib/emitter/tests/EventUnenrolTest.php
deleted file mode 100644
index f475e5d3dfbfbe92c9aabacfa126df1fe2f44894..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/EventUnenrolTest.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\EventUnenrol as Event;
-
-class EventUnenrolTest extends EventTest {
-    protected static $recipeName = 'training_session_unenrol';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->contructObject('session', 'http://activitystrea.ms/schema/1.0/event')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertUser($input, $output['actor'], 'user');
-        $this->assertVerb('http://id.tincanapi.com/verb/unregistered', 'unregistered from', $output['verb']);
-        $this->assertObject('session', $input, $output['object']);
-        $this->assertObject('module', $input, $output['context']['contextActivities']['parent'][0]);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertEquals('http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#detailed', $output['context']['contextActivities']['category'][1]['id']);
-    }
-}
diff --git a/lib/emitter/tests/ModuleViewedTest.php b/lib/emitter/tests/ModuleViewedTest.php
deleted file mode 100644
index 3a530ecedb5933d1ac04a75c2c7666abc6a7fc1d..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/ModuleViewedTest.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\ModuleViewed as Event;
-
-class ModuleViewedTest extends EventTest {
-    protected static $recipeName = 'module_viewed';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://id.tincanapi.com/verb/viewed', 'viewed', $output['verb']);
-        $this->assertObject('module', $input, $output['object']);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-    }
-}
diff --git a/lib/emitter/tests/QuestionAnsweredTest.php b/lib/emitter/tests/QuestionAnsweredTest.php
deleted file mode 100644
index c58ad08842d31c16496453dba8032484a8787f8b..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/QuestionAnsweredTest.php
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\QuestionAnswered as Event;
-
-class QuestionAnsweredTest extends EventTest {
-    protected static $recipeName = 'attempt_question_completed';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->constructQuestion(),
-            $this->constructAttempt()
-        );
-    }
-
-    protected function constructAttempt() {
-        return array_merge(parent::constructAttempt(), [
-            'attempt_score_raw' => 1,
-            'attempt_score_min' => 0,
-            'attempt_score_max' => 5,
-            'attempt_score_scaled' => 0.2,
-            'attempt_success' => false,
-            'attempt_completed' => true,
-            'attempt_response' => 'test response',
-        ]);
-    }
-
-    protected function constructQuestion() {
-        return array_merge(
-            parent::contructObject('question', 'http://adlnet.gov/expapi/activities/cmi.interaction'),
-            [
-                'interaction_type' => 'choice',
-                'interaction_correct_responses' => ['[9,10]'],
-                'interaction_choices' => [
-                    '8' => 'test incorrect choice',
-                    '9' => 'test correct choice 1',
-                    '10' => 'test correct choice 2'
-                ]
-            ]
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/answered', 'answered', $output['verb']);
-        $this->assertEquals($input['attempt_url'], $output['context']['contextActivities']['grouping'][2]['id']);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-        $this->assertObject('module', $input, $output['context']['contextActivities']['parent'][0]);
-        $this->assertObject('question', $input, $output['object']);
-        $this->assertEquals($input['interaction_type'], $output['object']['definition']['interactionType']);
-        $this->assertEquals($input['interaction_correct_responses'], $output['object']['definition']['correctResponsesPattern']);
-        $this->assertComponentList($input['interaction_choices'], $output['object']['definition']['choices'], $input['context_lang']);
-        $this->assertEquals($input['attempt_score_raw'], $output['result']['score']['raw']);
-        $this->assertEquals($input['attempt_score_min'], $output['result']['score']['min']);
-        $this->assertEquals($input['attempt_score_max'], $output['result']['score']['max']);
-        $this->assertEquals($input['attempt_score_scaled'], $output['result']['score']['scaled']);
-        $this->assertEquals($input['attempt_success'], $output['result']['success']);
-        $this->assertEquals($input['attempt_completed'], $output['result']['completion']);
-        $this->assertEquals($input['attempt_response'], $output['result']['response']);
-    }
-}
diff --git a/lib/emitter/tests/ScormEventTest.php b/lib/emitter/tests/ScormEventTest.php
deleted file mode 100644
index 2dc0465432ce89ee856b4eb5718fb7f59e85b20d..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/ScormEventTest.php
+++ /dev/null
@@ -1,52 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\ScormEvent as Event;
-
-class ScormEventTest extends EventTest {
-    protected static $recipeName = 'scorm_event';
-
-    /**
-     * Sets up the tests.
-     * @override ModuleViewedTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module'),
-            $this->constructScormTracking(),
-            $this->constructScormScoes()
-        );
-    }
-
-    protected function constructScormTracking() {
-        return [
-            'scorm_score_raw' => 100,
-            'scorm_score_min' => 0,
-            'scorm_score_scaled' => 1,
-            'scorm_score_max' => 100,
-            'scorm_status' => 'completed',
-        ];
-    }
-
-    protected function constructScormScoes() {
-        return [
-            'scorm_scoes_id' =>  1,
-            'scorm_scoes_url' =>  'http://www.example.com/module_url',
-            'scorm_scoes_type' => static::$xapiType. 'sco',
-            'scorm_scoes_name' => 'Sco name',
-            'scorm_scoes_description' => 'Sco Description',
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        $this->assertUser($input, $output['actor'], 'user');
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][0]);
-        $this->assertObject('module', $input, $output['object']);
-        $this->assertObject('scorm_scoes', $input, $output['context']['contextActivities']['grouping'][1]);
-    }
-
-}
diff --git a/lib/emitter/tests/ScormLaunchedTest.php b/lib/emitter/tests/ScormLaunchedTest.php
deleted file mode 100644
index bdc22419485b0a1951b76c8c4ffd5eeb6dbabace..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/ScormLaunchedTest.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\ScormLaunched as Event;
-
-class ScormLaunchedTest extends EventTest {
-    protected static $recipeName = 'scorm_launched';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->contructObject('course'),
-            $this->contructObject('module')
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/launched', 'launched', $output['verb']);
-        $this->assertObject('module', $input, $output['object']);
-        $this->assertObject('course', $input, $output['context']['contextActivities']['grouping'][1]);
-    }
-}
diff --git a/lib/emitter/tests/ScormScoreRawSubmittedTest.php b/lib/emitter/tests/ScormScoreRawSubmittedTest.php
deleted file mode 100644
index 6646380ba324ac2c9d4d016e4ffcbb77d724d266..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/ScormScoreRawSubmittedTest.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\ScormScoreRawSubmitted as Event;
-
-class ScormScoreRawSubmittedTest extends ScormEventTest {
-    protected static $recipeName = 'scorm_scoreraw_submitted';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
-        $this->assertEquals($input['scorm_score_raw'], $output['result']['score']['raw']);
-        $this->assertEquals($input['scorm_score_min'], $output['result']['score']['min']);
-        $this->assertEquals($input['scorm_score_max'], $output['result']['score']['max']);
-        $this->assertEquals($input['scorm_score_scaled'], $output['result']['score']['scaled']);
-        $this->assertEquals($input['scorm_status'], $output['verb']['display']['en']);
-    }
-}
diff --git a/lib/emitter/tests/ScormStatusSubmittedTest.php b/lib/emitter/tests/ScormStatusSubmittedTest.php
deleted file mode 100644
index b2147989c3cec8e42f66ec3be8c5c4d2d02903bd..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/ScormStatusSubmittedTest.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\ScormStatusSubmitted as Event;
-
-class ScormStatusSubmittedTest extends ScormEventTest {
-    protected static $recipeName = 'scorm_status_submitted';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
-        $this->assertEquals($input['scorm_status'], $output['verb']['display']['en']);
-    }
-}
diff --git a/lib/emitter/tests/TestRemoteLrs.php b/lib/emitter/tests/TestRemoteLrs.php
deleted file mode 100644
index 1b69f52852d7b35169ea1abdf099dfd1f7e14910..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/TestRemoteLrs.php
+++ /dev/null
@@ -1,17 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \TinCan\RemoteLRS as TinCanRemoteLrs;
-
-class TestRemoteLrs extends TinCanRemoteLrs {
-    /**
-     * Creates a statement in the LRS.
-     * @param $statement
-     * @return \TinCan\Statement
-     * @override TinCanRemoteLrs
-     */
-    public function saveStatement($statement) {
-        return (object) [
-            'success' => true,
-            'response' => $statement,
-        ];
-    }
-}
diff --git a/lib/emitter/tests/TestRepository.php b/lib/emitter/tests/TestRepository.php
deleted file mode 100644
index 415a5a09f937f7e13264f5234d14c5f7254a3468..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/TestRepository.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Repository as EmitterRepository;
-
-class TestRepository extends EmitterRepository {
-
-    /**
-     * Creates events in the store.
-     * @param [string => mixed] $event
-     * @return [string => mixed]
-     */
-    public function createEvents(array $events) {
-        return $events;
-    }
-}
diff --git a/lib/emitter/tests/UserLoggedinTest.php b/lib/emitter/tests/UserLoggedinTest.php
deleted file mode 100644
index b9a34e042d1b4f13d14830cc342b79ae92bbb022..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/UserLoggedinTest.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\UserLoggedin as Event;
-
-class UserLoggedinTest extends EventTest {
-    protected static $recipeName = 'user_loggedin';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->constructApp()
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('https://brindlewaye.com/xAPITerms/verbs/loggedin/', 'logged in to', $output['verb']);
-        $this->assertObject('app', $input, $output['object']);
-    }
-}
diff --git a/lib/emitter/tests/UserLoggedoutTest.php b/lib/emitter/tests/UserLoggedoutTest.php
deleted file mode 100644
index ae43abc59eb9ae32d3495052acac102d02b17033..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/UserLoggedoutTest.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\UserLoggedout as Event;
-
-class UserLoggedoutTest extends EventTest {
-    protected static $recipeName = 'user_loggedout';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->constructApp()
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('https://brindlewaye.com/xAPITerms/verbs/loggedout/', 'logged out of', $output['verb']);
-        $this->assertObject('app', $input, $output['object']);
-    }
-}
diff --git a/lib/emitter/tests/UserRegisteredTest.php b/lib/emitter/tests/UserRegisteredTest.php
deleted file mode 100644
index 7cbd7f65127060d58f27653b9463afc36e5d5da0..0000000000000000000000000000000000000000
--- a/lib/emitter/tests/UserRegisteredTest.php
+++ /dev/null
@@ -1,27 +0,0 @@
-<?php namespace XREmitter\Tests;
-use \XREmitter\Events\UserRegistered as Event;
-
-class UserRegisteredTest extends EventTest {
-    protected static $recipeName = 'user_registered';
-
-    /**
-     * Sets up the tests.
-     * @override EventTest
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(
-            parent::constructInput(),
-            $this->constructApp()
-        );
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertVerb('http://adlnet.gov/expapi/verbs/registered', 'registered to', $output['verb']);
-        $this->assertObject('app', $input, $output['object']);
-    }
-}
diff --git a/lib/expander/docs/examples/AssignmentGraded.json b/lib/expander/docs/examples/assignment_graded.json
similarity index 100%
rename from lib/expander/docs/examples/AssignmentGraded.json
rename to lib/expander/docs/examples/assignment_graded.json
diff --git a/lib/expander/docs/examples/AssignmentSubmitted.json b/lib/expander/docs/examples/assignment_submitted.json
similarity index 100%
rename from lib/expander/docs/examples/AssignmentSubmitted.json
rename to lib/expander/docs/examples/assignment_submitted.json
diff --git a/lib/expander/docs/examples/AttemptEvent.json b/lib/expander/docs/examples/attempt_event.json
similarity index 100%
rename from lib/expander/docs/examples/AttemptEvent.json
rename to lib/expander/docs/examples/attempt_event.json
diff --git a/lib/expander/docs/examples/CourseCompleted.json b/lib/expander/docs/examples/course_completed.json
similarity index 100%
rename from lib/expander/docs/examples/CourseCompleted.json
rename to lib/expander/docs/examples/course_completed.json
diff --git a/lib/expander/docs/examples/DiscussionEvent.json b/lib/expander/docs/examples/discussion_event.json
similarity index 100%
rename from lib/expander/docs/examples/DiscussionEvent.json
rename to lib/expander/docs/examples/discussion_event.json
diff --git a/lib/expander/docs/examples/Event.json b/lib/expander/docs/examples/event.json
similarity index 100%
rename from lib/expander/docs/examples/Event.json
rename to lib/expander/docs/examples/event.json
diff --git a/lib/expander/docs/examples/FacetofaceAttended.json b/lib/expander/docs/examples/facetoface_attended.json
similarity index 100%
rename from lib/expander/docs/examples/FacetofaceAttended.json
rename to lib/expander/docs/examples/facetoface_attended.json
diff --git a/lib/expander/docs/examples/FacetofaceEvent.json b/lib/expander/docs/examples/facetoface_event.json
similarity index 100%
rename from lib/expander/docs/examples/FacetofaceEvent.json
rename to lib/expander/docs/examples/facetoface_event.json
diff --git a/lib/expander/docs/examples/FeedbackSubitted.json b/lib/expander/docs/examples/feedback_submitted.json
similarity index 98%
rename from lib/expander/docs/examples/FeedbackSubitted.json
rename to lib/expander/docs/examples/feedback_submitted.json
index 670bb1a67fb3dca6c4b80c2f407783a22c666b45..c3b4365c5f3e0ca5efdb34d48869c7f0fede477e 100644
--- a/lib/expander/docs/examples/FeedbackSubitted.json
+++ b/lib/expander/docs/examples/feedback_submitted.json
@@ -116,6 +116,6 @@
                 "type": "object"
             }
         },
-        "timemodified": 1497229712
+        "timemodified": 1498820609
     }
 }
\ No newline at end of file
diff --git a/lib/expander/docs/examples/ModuleEvent.json b/lib/expander/docs/examples/module_event.json
similarity index 100%
rename from lib/expander/docs/examples/ModuleEvent.json
rename to lib/expander/docs/examples/module_event.json
diff --git a/lib/expander/docs/examples/ScormLaunched.json b/lib/expander/docs/examples/scorm_launched.json
similarity index 100%
rename from lib/expander/docs/examples/ScormLaunched.json
rename to lib/expander/docs/examples/scorm_launched.json
diff --git a/lib/expander/docs/examples/ScormSubmitted.json b/lib/expander/docs/examples/scorm_submitted.json
similarity index 100%
rename from lib/expander/docs/examples/ScormSubmitted.json
rename to lib/expander/docs/examples/scorm_submitted.json
diff --git a/lib/expander/src/Controller.php b/lib/expander/src/Controller.php
index 612c9964e659d9d443cf9ee428c35ba9d9627c6f..8a4f5b678ea446a4e0ecb19a8b2a4eb944fc7ba9 100644
--- a/lib/expander/src/Controller.php
+++ b/lib/expander/src/Controller.php
@@ -1,5 +1,25 @@
-<?php namespace LogExpander;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \stdClass as PhpObj;
+
 class Controller extends PhpObj {
     protected $repo;
     public static $routes = [
@@ -10,7 +30,7 @@ class Controller extends PhpObj {
         '\mod_folder\event\course_module_viewed' => 'ModuleEvent',
         '\mod_forum\event\course_module_viewed' => 'ModuleEvent',
         '\mod_forum\event\discussion_viewed' => 'DiscussionEvent',
-        '\mod_forum\event\user_report_viewed' =>  'ModuleEvent',
+        '\mod_forum\event\user_report_viewed' => 'ModuleEvent',
         '\mod_book\event\course_module_viewed' => 'ModuleEvent',
         '\mod_scorm\event\course_module_viewed' => 'ModuleEvent',
         '\mod_resource\event\course_module_viewed' => 'ModuleEvent',
@@ -41,10 +61,11 @@ class Controller extends PhpObj {
         '\mod_facetoface\event\signup_success' => 'FacetofaceEvent',
         '\mod_facetoface\event\cancel_booking' => 'FacetofaceEvent',
         '\mod_facetoface\event\take_attendance' => 'FacetofaceAttended',
-        '\core\event\course_completed'=>'CourseCompleted',
-        '\mod_scorm\event\scoreraw_submitted'=>'ScormSubmitted',
-        '\mod_scorm\event\status_submitted'=>'ScormSubmitted'
+        '\core\event\course_completed' => 'CourseCompleted',
+        '\mod_scorm\event\scoreraw_submitted' => 'ScormSubmitted',
+        '\mod_scorm\event\status_submitted' => 'ScormSubmitted',
     ];
+
     /**
      * Constructs a new Controller.
      * @param Repository $repo
@@ -52,12 +73,13 @@ class Controller extends PhpObj {
     public function __construct(Repository $repo) {
         $this->repo = $repo;
     }
+
     /**
      * Creates new events.
      * @param [String => Mixed] $events
      * @return [String => Mixed]
      */
-    public function createEvents(array $events) {
+    public function create_events(array $events) {
         $results = [];
         foreach ($events as $index => $opts) {
             $route = isset($opts['eventname']) ? $opts['eventname'] : '';
@@ -65,8 +87,7 @@ class Controller extends PhpObj {
                 try {
                     $event = '\LogExpander\Events\\'.static::$routes[$route];
                     array_push($results , (new $event($this->repo))->read($opts));
-                }
-                catch (\Exception $e) {
+                } catch (\Exception $e) { // @codingStandardsIgnoreLine
                     // Error processing event; skip it.
                 }
             }
diff --git a/lib/expander/src/Events/AssignmentGraded.php b/lib/expander/src/Events/AssignmentGraded.php
index 5ad816cb0c8205e401ce598c5f4a6a024b3bb326..8d4d7f25eda25946c3f96bbc77e0c4dd53af0f09 100644
--- a/lib/expander/src/Events/AssignmentGraded.php
+++ b/lib/expander/src/Events/AssignmentGraded.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AssignmentGraded extends Event {
     /**
@@ -8,15 +26,15 @@ class AssignmentGraded extends Event {
      * @override Event
      */
     public function read(array $opts) {
-        $grade = $this->repo->readObject($opts['objectid'], $opts['objecttable']);
-        $gradeComment = $this->repo->readGradeComment($grade->id, $grade->assignment)->commenttext;
-        $gradeItems = $this->repo->readGradeItems($grade->assignment, 'assign');
+        $grade = $this->repo->read_object($opts['objectid'], $opts['objecttable']);
+        $gradecomment = $this->repo->read_grade_comment($grade->id, $grade->assignment)->commenttext;
+        $gradeitems = $this->repo->read_grade_items($grade->assignment, 'assign');
         return array_merge(parent::read($opts), [
             'grade' => $grade,
-            'grade_comment' => $gradeComment,
-            'grade_items' => $gradeItems,
-            'graded_user' => $this->repo->readUser($grade->userid),
-            'module' => $this->repo->readModule($grade->assignment, 'assign'),
+            'grade_comment' => $gradecomment,
+            'grade_items' => $gradeitems,
+            'graded_user' => $this->repo->read_user($grade->userid),
+            'module' => $this->repo->read_module($grade->assignment, 'assign'),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/AssignmentSubmitted.php b/lib/expander/src/Events/AssignmentSubmitted.php
index 1acf1d4e73fabcb0fd6befc3a6b8f7b2407d3d86..2a89b65cf80d1b246e52d7d0d65e870417856c80 100644
--- a/lib/expander/src/Events/AssignmentSubmitted.php
+++ b/lib/expander/src/Events/AssignmentSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AssignmentSubmitted extends Event {
     /**
@@ -8,10 +26,10 @@ class AssignmentSubmitted extends Event {
      * @override Event
      */
     public function read(array $opts) {
-        $submission = $this->repo->readObject($opts['objectid'], $opts['objecttable']);
+        $submission = $this->repo->read_object($opts['objectid'], $opts['objecttable']);
         return array_merge(parent::read($opts), [
             'submission' => $submission,
-            'module' => $this->repo->readModule($submission->assignment, 'assign'),
+            'module' => $this->repo->read_module($submission->assignment, 'assign'),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/AttemptEvent.php b/lib/expander/src/Events/AttemptEvent.php
index 9946d487947c7dc7d413d2f568467f01418fd0aa..18a8aac01939023e6b9984f126509d4b521eff8e 100644
--- a/lib/expander/src/Events/AttemptEvent.php
+++ b/lib/expander/src/Events/AttemptEvent.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AttemptEvent extends Event {
     /**
@@ -8,16 +26,16 @@ class AttemptEvent extends Event {
      * @override Event
      */
     public function read(array $opts) {
-        $attempt = $this->repo->readAttempt($opts['objectid']);
-        $gradeItems = $this->repo->readGradeItems($attempt->quiz, 'quiz');
-        $attempt->questions = $this->repo->readQuestionAttempts($attempt->id);
-        $questions = $this->repo->readQuestions($attempt->quiz);
+        $attempt = $this->repo->read_attempt($opts['objectid']);
+        $gradeitems = $this->repo->read_grade_items($attempt->quiz, 'quiz');
+        $attempt->questions = $this->repo->read_question_attempts($attempt->id);
+        $questions = $this->repo->read_questions($attempt->quiz);
 
         return array_merge(parent::read($opts), [
             'attempt' => $attempt,
-            'module' => $this->repo->readModule($attempt->quiz, 'quiz'),
-            'grade_items' => $gradeItems,
+            'module' => $this->repo->read_module($attempt->quiz, 'quiz'),
+            'grade_items' => $gradeitems,
             'questions' => $questions
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/CourseCompleted.php b/lib/expander/src/Events/CourseCompleted.php
index 18e30d08bafd8ad98feebb600845c10fd2ae4581..6876f3fbe2046c82713d128934dabb65d5fd633d 100644
--- a/lib/expander/src/Events/CourseCompleted.php
+++ b/lib/expander/src/Events/CourseCompleted.php
@@ -1,16 +1,24 @@
 <?php
-/**
- * Created by PhpStorm.
- * User: lee.kirkland
- * Date: 5/20/2016
- * Time: 9:12 AM
- */
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 namespace LogExpander\Events;
 
+defined('MOODLE_INTERNAL') || die();
 
-class CourseCompleted extends Event
-{
+class CourseCompleted extends Event {
     /**
      * Reads data for an event.
      * @param [String => Mixed] $opts
@@ -18,7 +26,6 @@ class CourseCompleted extends Event
      * @override Event
      */
     public function read(array $opts) {
-        return array_merge(parent::read($opts), [
-        ]);
+        return array_merge(parent::read($opts), []);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/DiscussionEvent.php b/lib/expander/src/Events/DiscussionEvent.php
index 001206d05ce4c1ecab638c9bbe007640d6f8c490..00e67ecdafabdff9adc529ff411069c9d1c38ebf 100644
--- a/lib/expander/src/Events/DiscussionEvent.php
+++ b/lib/expander/src/Events/DiscussionEvent.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class DiscussionEvent extends Event {
     /**
@@ -8,10 +26,10 @@ class DiscussionEvent extends Event {
      * @override Event
      */
     public function read(array $opts) {
-        $discussion = $this->repo->readDiscussion($opts['objectid']);
+        $discussion = $this->repo->read_discussion($opts['objectid']);
         return array_merge(parent::read($opts), [
             'discussion' => $discussion,
-            'module' => $this->repo->readModule($discussion->forum, 'forum'),
+            'module' => $this->repo->read_module($discussion->forum, 'forum'),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/Event.php b/lib/expander/src/Events/Event.php
index 53f535c72f104e558aa6598016c9557359f5b616..dc254098b4a51afe6792a3f01cee515db5f81a00 100644
--- a/lib/expander/src/Events/Event.php
+++ b/lib/expander/src/Events/Event.php
@@ -1,4 +1,23 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \LogExpander\Repository as Repository;
 use \stdClass as PhpObj;
 
@@ -20,12 +39,12 @@ class Event extends PhpObj {
      */
     public function read(array $opts) {
         return [
-            'user' => $opts['userid'] < 1 ? null : $this->repo->readUser($opts['userid']),
-            'relateduser' => $opts['relateduserid'] < 1 ? null : $this->repo->readUser($opts['relateduserid']),
-            'course' => $this->repo->readCourse($opts['courseid']),
-            'app' => $this->repo->readSite(),
+            'user' => $opts['userid'] < 1 ? null : $this->repo->read_user($opts['userid']),
+            'relateduser' => $opts['relateduserid'] < 1 ? null : $this->repo->read_user($opts['relateduserid']),
+            'course' => $this->repo->read_course($opts['courseid']),
+            'app' => $this->repo->read_site(),
             'info' => (object) [
-                'https://moodle.org/' => $this->repo->readRelease(),
+                'https://moodle.org/' => $this->repo->read_release(),
             ],
             'event' => $opts,
         ];
diff --git a/lib/expander/src/Events/FacetofaceAttended.php b/lib/expander/src/Events/FacetofaceAttended.php
index 0e4721960760b294b2d3069bdf8ac644bd7adb90..ae545ed86381f83761880faa903b61ce0dec95a7 100644
--- a/lib/expander/src/Events/FacetofaceAttended.php
+++ b/lib/expander/src/Events/FacetofaceAttended.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FacetofaceAttended extends FacetofaceEvent {
     /**
@@ -8,9 +26,9 @@ class FacetofaceAttended extends FacetofaceEvent {
      * @override Event
      */
     public function read(array $opts) {
-        $session = $this->repo->readFacetofaceSession($opts['objectid']);
+        $session = $this->repo->read_facetoface_session($opts['objectid']);
         return array_merge(parent::read($opts), [
-            'signups' => $this->repo->readFacetofaceSessionSignups($opts['objectid'], $opts['timecreated'])
+            'signups' => $this->repo->read_facetoface_session_signups($opts['objectid'], $opts['timecreated'])
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/FacetofaceEvent.php b/lib/expander/src/Events/FacetofaceEvent.php
index a9f609302c1a30ca11977e82c81a5ab8630360db..727ee892fd8101014db0407d459795c93a3cf5a5 100644
--- a/lib/expander/src/Events/FacetofaceEvent.php
+++ b/lib/expander/src/Events/FacetofaceEvent.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FacetofaceEvent extends Event {
     /**
@@ -9,10 +27,10 @@ class FacetofaceEvent extends Event {
      */
     public function read(array $opts) {
 
-        $session = $this->repo->readFacetofaceSession($opts['objectid']);
+        $session = $this->repo->read_facetoface_session($opts['objectid']);
         return array_merge(parent::read($opts), [
-            'module' => $this->repo->readModule($session->facetoface, 'facetoface'),
+            'module' => $this->repo->read_module($session->facetoface, 'facetoface'),
             'session' => $session
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/FeedbackSubmitted.php b/lib/expander/src/Events/FeedbackSubmitted.php
index 5360b981d257cf1267fba53b3c4afca530456847..ebd15c44e2c30a7c4a2cf62963c29d9b782d0ebf 100644
--- a/lib/expander/src/Events/FeedbackSubmitted.php
+++ b/lib/expander/src/Events/FeedbackSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FeedbackSubmitted extends Event {
     /**
@@ -8,12 +26,11 @@ class FeedbackSubmitted extends Event {
      * @override Event
      */
     public function read(array $opts) {
-
-        $attempt = $this->repo->readFeedbackAttempt($opts['objectid']);
-        $attempt->timemodified = $this->timeSelector($attempt);
+        $attempt = $this->repo->read_feedback_attempt($opts['objectid']);
+        $attempt->timemodified = $this->time_selector($attempt);
         return array_merge(parent::read($opts), [
-            'module' => $this->repo->readModule($attempt->feedback, 'feedback'),
-            'questions' => $this->repo->readFeedbackQuestions($attempt->feedback),
+            'module' => $this->repo->read_module($attempt->feedback, 'feedback'),
+            'questions' => $this->repo->read_feedback_questions($attempt->feedback),
             'attempt' => $attempt,
         ]);
     }
@@ -24,17 +41,16 @@ class FeedbackSubmitted extends Event {
      * @param $attempt
      * @return int
      */
-    private function timeSelector($attempt) {
-
-        $retValue = time();
+    private function time_selector($attempt) {
+        $retvalue = time();
         if (!empty($attempt->timemodified)) {
-            $retValue = $attempt->timemodified;
+            $retvalue = $attempt->timemodified;
         } else if (!empty($attempt->timefinished)) {
-            $retValue = $attempt->timefinished;
+            $retvalue = $attempt->timefinished;
         } else if (!empty($attempt->timestarted)) {
-            $retValue = $attempt->timestarted;
+            $retvalue = $attempt->timestarted;
         }
 
-        return $retValue;
+        return $retvalue;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/ModuleEvent.php b/lib/expander/src/Events/ModuleEvent.php
index df1503a4b419a951e4eabea930c506a21b396187..9c858ce971997ac59aa4e04ebd20cbea6b35130a 100644
--- a/lib/expander/src/Events/ModuleEvent.php
+++ b/lib/expander/src/Events/ModuleEvent.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ModuleEvent extends Event {
     /**
@@ -9,7 +27,7 @@ class ModuleEvent extends Event {
      */
     public function read(array $opts) {
         return array_merge(parent::read($opts), [
-            'module' => $this->repo->readModule($opts['objectid'], $opts['objecttable']),
+            'module' => $this->repo->read_module($opts['objectid'], $opts['objecttable']),
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/ScormLaunched.php b/lib/expander/src/Events/ScormLaunched.php
index 67580935d02178d5d700261524d4a954ac6bab7e..fc6bedf9a21fda8682883569d515511f8d3eacb9 100644
--- a/lib/expander/src/Events/ScormLaunched.php
+++ b/lib/expander/src/Events/ScormLaunched.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormLaunched extends Event {
     /**
@@ -8,10 +26,10 @@ class ScormLaunched extends Event {
      * @override Event
      */
     public function read(array $opts) {
-        $scormScoes = $this->repo->readObject($opts['objectid'], $opts['objecttable']);
+        $scormscoes = $this->repo->read_object($opts['objectid'], $opts['objecttable']);
         return array_merge(parent::read($opts), [
-            'module' => $this->repo->readModule($scormScoes->scorm, 'scorm'),
-            'scorm_scoes' => $scormScoes
+            'module' => $this->repo->read_module($scormscoes->scorm, 'scorm'),
+            'scorm_scoes' => $scormscoes
         ]);
     }
-}
\ No newline at end of file
+}
diff --git a/lib/expander/src/Events/ScormSubmitted.php b/lib/expander/src/Events/ScormSubmitted.php
index ed419432b15077b6dfbdd853e8340f2a3090c997..7dc23cf5b6036a50e6d6ac235b06ac69b27b1fcc 100644
--- a/lib/expander/src/Events/ScormSubmitted.php
+++ b/lib/expander/src/Events/ScormSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace LogExpander\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormSubmitted extends Event {
     /**
@@ -8,11 +26,11 @@ class ScormSubmitted extends Event {
      * @override Event
      */
     public function read(array $opts) {
-        $cmiUnserialized = unserialize($opts['other']);
+        $cmiunserialized = unserialize($opts['other']);
         $scoid = $opts['contextinstanceid'];
         $scormid = $opts['objectid'];
-        $attempt = $cmiUnserialized['attemptid'];
-        $scormScoesTrack = $this->repo->readScormScoesTrack(
+        $attempt = $cmiunserialized['attemptid'];
+        $scormscoestrack = $this->repo->read_scorm_scoes_track(
             $opts['userid'],
             $scormid,
             $scoid,
@@ -20,10 +38,10 @@ class ScormSubmitted extends Event {
         );
 
         return array_merge(parent::read($opts), [
-            'module' => $this->repo->readModule($scormid, 'scorm'),
-            'scorm_scoes_track' => $scormScoesTrack,
-            'scorm_scoes' => $this->repo->readScormScoes($scoid),
-            'cmi_data' => $cmiUnserialized,
+            'module' => $this->repo->read_module($scormid, 'scorm'),
+            'scorm_scoes_track' => $scormscoestrack,
+            'scorm_scoes' => $this->repo->read_scorm_scoes($scoid),
+            'cmi_data' => $cmiunserialized,
         ]);
     }
 }
diff --git a/lib/expander/src/Repository.php b/lib/expander/src/Repository.php
index b9c07fef6f88e58ba52d791a1e32f5727d9c9e22..f5601707bf863d497db322c7559efa846805685c 100644
--- a/lib/expander/src/Repository.php
+++ b/lib/expander/src/Repository.php
@@ -1,4 +1,23 @@
-<?php namespace LogExpander;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \stdClass as PhpObj;
 use Exception;
 
@@ -23,7 +42,7 @@ class Repository extends PhpObj {
      * @throws Exception if the record was not found
      * @return PhpObj
      */
-    protected function readStoreRecord($type, array $query) {
+    protected function read_store_record($type, array $query) {
         $model = $this->store->get_record($type, $query);
         if ($model === false) {
             throw new Exception('Record not found.');
@@ -37,7 +56,7 @@ class Repository extends PhpObj {
      * @param [String => Mixed] $query
      * @return PhpArr
      */
-    protected function readStoreRecords($type, array $query) {
+    protected function read_store_records($type, array $query) {
         $model = $this->store->get_records($type, $query);
         return $model;
     }
@@ -57,8 +76,8 @@ class Repository extends PhpObj {
      * @param String $type
      * @return PhpObj
      */
-    public function readObject($id, $type) {
-        $model = $this->readStoreRecord($type, ['id' => $id]);
+    public function read_object($id, $type) {
+        $model = $this->read_store_record($type, ['id' => $id]);
         $model->type = $type;
         return $model;
     }
@@ -69,15 +88,15 @@ class Repository extends PhpObj {
      * @param String $type
      * @return PhpObj
      */
-    public function readModule($id, $type) {
-        $model = $this->readObject($id, $type);
-        $module = $this->readStoreRecord('modules', ['name' => $type]);
-        $courseModule = $this->readStoreRecord('course_modules', [
+    public function read_module($id, $type) {
+        $model = $this->read_object($id, $type);
+        $module = $this->read_store_record('modules', ['name' => $type]);
+        $coursemodule = $this->read_store_record('course_modules', [
             'instance' => $id,
             'module' => $module->id,
             'course' => $model->course
         ]);
-        $model->url = $this->cfg->wwwroot . '/mod/'.$type.'/view.php?id=' . $courseModule->id;
+        $model->url = $this->cfg->wwwroot . '/mod/'.$type.'/view.php?id=' . $coursemodule->id;
         return $model;
     }
 
@@ -86,8 +105,8 @@ class Repository extends PhpObj {
      * @param String $id
      * @return PhpObj
      */
-    public function readAttempt($id) {
-        $model = $this->readObject($id, 'quiz_attempts');
+    public function read_attempt($id) {
+        $model = $this->read_object($id, 'quiz_attempts');
         $model->url = $this->cfg->wwwroot . '/mod/quiz/attempt.php?attempt='.$id;
         $model->name = 'Attempt '.$id;
         return $model;
@@ -98,57 +117,62 @@ class Repository extends PhpObj {
      * @param String $id
      * @return PhpArr
      */
-    public function readQuestionAttempts($id) {
-        $questionAttempts = $this->readStoreRecords('question_attempts', ['questionusageid' => $id]);
-        foreach ($questionAttempts as $questionIndex => $questionAttempt) {
-            $questionAttemptSteps = $this->readStoreRecords('question_attempt_steps', ['questionattemptid' => $questionAttempt->id]);
-            foreach ($questionAttemptSteps as $stepIndex => $questionAttemptStep) {
-                $questionAttemptStep->data = $this->readStoreRecords('question_attempt_step_data', ['attemptstepid' => $questionAttemptStep->id]);
+    public function read_question_attempts($id) {
+        $questionattempts = $this->read_store_records('question_attempts', ['questionusageid' => $id]);
+        foreach ($questionattempts as $questionindex => $questionattempt) {
+            $questionattemptsteps = $this->read_store_records(
+                'question_attempt_steps',
+                ['questionattemptid' => $questionattempt->id]
+            );
+            foreach ($questionattemptsteps as $stepindex => $questionattemptstep) {
+                $questionattemptstep->data = $this->read_store_records(
+                    'question_attempt_step_data',
+                    ['attemptstepid' => $questionattemptstep->id]
+                );
             }
-            $questionAttempt->steps = $questionAttemptSteps;
+            $questionattempt->steps = $questionattemptsteps;
         }
-        return $questionAttempts;
+        return $questionattempts;
     }
 
     /**
      * Reads questions from the store with the given quiz id.
-     * @param String $id
+     * @param string $quizid
      * @return PhpArr
      */
-    public function readQuestions($quizId) {
-        $quizSlots = $this->readStoreRecords('quiz_slots', ['quizid' => $quizId]);
+    public function read_questions($quizid) {
+        $quizslots = $this->read_store_records('quiz_slots', ['quizid' => $quizid]);
         $questions = [];
-        foreach ($quizSlots as $index => $quizSlot) {
+        foreach ($quizslots as $index => $quizslot) {
             try {
-                $question = $this->readStoreRecord('question', ['id' => $quizSlot->questionid]);
-                $question->answers = $this->readStoreRecords('question_answers', ['question' => $question->id]);
+                $question = $this->read_store_record('question', ['id' => $quizslot->questionid]);
+                $question->answers = $this->read_store_records('question_answers', ['question' => $question->id]);
                 $question->url = $this->cfg->wwwroot . '/mod/question/question.php?id='.$question->id;
 
                 if ($question->qtype == 'numerical') {
                     $question->numerical = (object)[
-                        'answers' => $this->readStoreRecords('question_numerical', ['question' => $question->id]),
-                        'options' => $this->readStoreRecord('question_numerical_options', ['question' => $question->id]),
-                        'units' => $this->readStoreRecords('question_numerical_units', ['question' => $question->id])
+                        'answers' => $this->read_store_records('question_numerical', ['question' => $question->id]),
+                        'options' => $this->read_store_record('question_numerical_options', ['question' => $question->id]),
+                        'units' => $this->read_store_records('question_numerical_units', ['question' => $question->id])
                     ];
                 } else if ($question->qtype == 'match') {
                     $question->match = (object)[
-                        'options' => $this->readStoreRecord('qtype_match_options', ['questionid' => $question->id]),
-                        'subquestions' => $this->readStoreRecords('qtype_match_subquestions', ['questionid' => $question->id])
+                        'options' => $this->read_store_record('qtype_match_options', ['questionid' => $question->id]),
+                        'subquestions' => $this->read_store_records('qtype_match_subquestions', ['questionid' => $question->id])
                     ];
                 } else if (strpos($question->qtype, 'calculated') === 0) {
                     $question->calculated = (object)[
-                        'answers' => $this->readStoreRecords('question_calculated', ['question' => $question->id]),
-                        'options' => $this->readStoreRecord('question_calculated_options', ['question' => $question->id])
+                        'answers' => $this->read_store_records('question_calculated', ['question' => $question->id]),
+                        'options' => $this->read_store_record('question_calculated_options', ['question' => $question->id])
                     ];
                 } else if ($question->qtype == 'shortanswer') {
                     $question->shortanswer = (object)[
-                        'options' => $this->readStoreRecord('qtype_shortanswer_options', ['questionid' => $question->id])
+                        'options' => $this->read_store_record('qtype_shortanswer_options', ['questionid' => $question->id])
                     ];
                 }
 
                 $questions[$question->id] = $question;
-            }
-            catch (\Exception $e) {
+            } catch (\Exception $e) { // @codingStandardsIgnoreLine
                 // Question not found; maybe it was deleted since the event.
                 // Don't add the question to the list, but also don't block the attempt event.
             }
@@ -158,26 +182,26 @@ class Repository extends PhpObj {
     }
 
     /**
-     * Reads  grade metadata from the store with the given type and id.
-     * @param String $id
-     * @param String $type
+     * Reads grade metadata from the store with the given type and id.
+     * @param string $id
+     * @param string $type
      * @return PhpObj
      */
-    public function readGradeItems($id, $type) {
-        return $this->readStoreRecord('grade_items', ['itemmodule' => $type, 'iteminstance' => $id]);
+    public function read_grade_items($id, $type) {
+        return $this->read_store_record('grade_items', ['itemmodule' => $type, 'iteminstance' => $id]);
     }
 
     /**
      * Reads assignemnt grade comment from the store for a given grade and assignment id
-     * @param String $id
+     * @param string $id
      * @return PhpObj
      */
-    public function readGradeComment($gradeId, $assignmentId) {
-        $model = $this->readStoreRecord(
+    public function read_grade_comment($gradeid, $assignmentid) {
+        $model = $this->read_store_record(
             'assignfeedback_comments',
             [
-                'assignment' => $assignmentId,
-                'grade' => $gradeId
+                'assignment' => $assignmentid,
+                'grade' => $gradeid
             ]
         );
         return $model;
@@ -188,11 +212,11 @@ class Repository extends PhpObj {
      * @param String $id
      * @return PhpObj
      */
-    public function readFeedbackAttempt($id) {
-        $model = $this->readObject($id, 'feedback_completed');
+    public function read_feedback_attempt($id) {
+        $model = $this->read_object($id, 'feedback_completed');
         $model->url = $this->cfg->wwwroot . '/mod/feedback/complete.php?id='.$id;
         $model->name = 'Attempt '.$id;
-        $model->responses = $this->readStoreRecords('feedback_value', ['completed' => $id]);
+        $model->responses = $this->read_store_records('feedback_value', ['completed' => $id]);
         return $model;
     }
 
@@ -201,16 +225,16 @@ class Repository extends PhpObj {
      * @param String $id
      * @return PhpArr
      */
-    public function readFeedbackQuestions($id) {
-        $questions = $this->readStoreRecords('feedback_item', ['feedback' => $id]);
-        $expandedQuestions = [];
+    public function read_feedback_questions($id) {
+        $questions = $this->read_store_records('feedback_item', ['feedback' => $id]);
+        $expandedquestions = [];
         foreach ($questions as $index => $question) {
-            $expandedQuestion = $question;
-            $expandedQuestion->template = $this->readStoreRecord('feedback_template', ['id' => $question->template]);
-            $expandedQuestion->url = $this->cfg->wwwroot . '/mod/feedback/edit_item.php?id='.$question->id;
-            $expandedQuestions[$index] = $expandedQuestion;
+            $expandedquestion = $question;
+            $expandedquestion->template = $this->read_store_record('feedback_template', ['id' => $question->template]);
+            $expandedquestion->url = $this->cfg->wwwroot . '/mod/feedback/edit_item.php?id='.$question->id;
+            $expandedquestions[$index] = $expandedquestion;
         }
-        return $expandedQuestions;
+        return $expandedquestions;
     }
 
     /**
@@ -218,36 +242,36 @@ class Repository extends PhpObj {
      * @param String $id
      * @return PhpObj
      */
-    public function readCourse($id) {
+    public function read_course($id) {
         if ($id == 0) {
-            $courses = $this->store->get_records('course',array());
+            $courses = $this->store->get_records('course', array());
 
-            //since get_records will return the ids as Key values for the array,
-            //just use key to find the first id in the course table for the index page
+            // Since get_records will return the ids as Key values for the array,
+            // just use key to find the first id in the course table for the index page.
             $id = key($courses);
         }
-        $model = $this->readObject($id, 'course');
+        $model = $this->read_object($id, 'course');
         $model->url = $this->cfg->wwwroot.($id > 0 ? '/course/view.php?id=' . $id : '');
         return $model;
     }
 
     /**
      * Reads a user from the store with the given id.
-     * @param String $id
+     * @param string $id
      * @return PhpObj
      */
-    public function readUser($id) {
-        $model = $this->readObject($id, 'user');
+    public function read_user($id) {
+        $model = $this->read_object($id, 'user');
         $model->url = $this->cfg->wwwroot;
         $model->fullname = $this->fullname($model);
-        if (isset($model->password)){
-             unset($model->password);
+        if (isset($model->password)) {
+            unset($model->password);
         }
-        if (isset($model->secret)){
-             unset($model->secret);
+        if (isset($model->secret)) {
+            unset($model->secret);
         }
-        if (isset($model->lastip)){
-             unset($model->lastip);
+        if (isset($model->lastip)) {
+            unset($model->lastip);
         }
         return $model;
     }
@@ -257,8 +281,8 @@ class Repository extends PhpObj {
      * @param String $id
      * @return PhpObj
      */
-    public function readDiscussion($id) {
-        $model = $this->readObject($id, 'forum_discussions');
+    public function read_discussion($id) {
+        $model = $this->read_object($id, 'forum_discussions');
         $model->url = $this->cfg->wwwroot . '/mod/forum/discuss.php?d=' . $id;
         return $model;
     }
@@ -267,7 +291,7 @@ class Repository extends PhpObj {
      * Reads the Moodle release number.
      * @return String
      */
-    public function readRelease() {
+    public function read_release() {
         return $this->cfg->release;
     }
 
@@ -275,8 +299,8 @@ class Repository extends PhpObj {
      * Reads the Moodle site
      * @return PhpObj
      */
-    public function readSite() {
-        $model = $this->readCourse(1);
+    public function read_site() {
+        $model = $this->read_course(1);
         $model->url = $this->cfg->wwwroot;
         $model->type = "site";
         return $model;
@@ -286,9 +310,9 @@ class Repository extends PhpObj {
      * Reads a face to face session
      * @return PhpObj
      */
-    public function readFacetofaceSession($id) {
-        $model = $this->readObject($id, 'facetoface_sessions');
-        $model->dates = $this->readStoreRecords('facetoface_sessions_dates', ['sessionid' => $id]);
+    public function read_facetoface_session($id) {
+        $model = $this->read_object($id, 'facetoface_sessions');
+        $model->dates = $this->read_store_records('facetoface_sessions_dates', ['sessionid' => $id]);
         $model->url = $this->cfg->wwwroot . '/mod/facetoface/signup.php?s=' . $id;
         return $model;
     }
@@ -297,12 +321,12 @@ class Repository extends PhpObj {
      * Reads face to face session signups
      * @return PhpObj
      */
-    public function readFacetofaceSessionSignups($sessionid, $timecreated) {
-        $signups = $this->readStoreRecords('facetoface_signups', ['sessionid' => $sessionid]);
+    public function read_facetoface_session_signups($sessionid, $timecreated) {
+        $signups = $this->read_store_records('facetoface_signups', ['sessionid' => $sessionid]);
 
         foreach ($signups as $index => $signup) {
-            $signups[$index]->statuses = $this->readStoreRecords('facetoface_signups_status', ['signupid' => $signup->id]);
-            $signups[$index]->attendee = $this->readUser($signup->userid);
+            $signups[$index]->statuses = $this->read_store_records('facetoface_signups_status', ['signupid' => $signup->id]);
+            $signups[$index]->attendee = $this->read_user($signup->userid);
         }
 
         return $signups;
@@ -312,34 +336,34 @@ class Repository extends PhpObj {
      * Reads Scorm tracking data
      * @return PhpObj
      */
-    public function readScormScoesTrack($userid, $scormid, $scoid, $attempt) {
-        $trackingValues = [];
-        $scormTracking = $this->readStoreRecords('scorm_scoes_track', [
+    public function read_scorm_scoes_track($userid, $scormid, $scoid, $attempt) {
+        $trackingvalues = [];
+        $scormtracking = $this->read_store_records('scorm_scoes_track', [
             'userid' => $userid,
-            'scormid'=> $scormid,
+            'scormid' => $scormid,
             'scoid' => $scoid,
             'attempt' => $attempt
         ]);
 
-        foreach ($scormTracking as $st) {
+        foreach ($scormtracking as $st) {
             if ($st->element == 'cmi.core.score.min') {
-                $trackingValues['scoremin'] = $st->value;
+                $trackingvalues['scoremin'] = $st->value;
             } else if ($st->element == 'cmi.core.score.max') {
-                $trackingValues['scoremax'] = $st->value;
+                $trackingvalues['scoremax'] = $st->value;
             } else if ($st->element == 'cmi.core.lesson_status') {
-                $trackingValues['status'] = $st->value;
+                $trackingvalues['status'] = $st->value;
             }
         }
 
-        return $trackingValues;
+        return $trackingvalues;
     }
 
     /**
      * Reads a scorm scoes
      * @return PhpObj
      */
-    public function readScormScoes($scoid) {
-        $model = $this->readObject($scoid, 'scorm_scoes');
+    public function read_scorm_scoes($scoid) {
+        $model = $this->read_object($scoid, 'scorm_scoes');
         return $model;
     }
 }
diff --git a/lib/expander/tests/AssignmentGradedTest.php b/lib/expander/tests/AssignmentGradedTest.php
deleted file mode 100644
index d5a608c853557b97e88da4b1902f9c97b13b0545..0000000000000000000000000000000000000000
--- a/lib/expander/tests/AssignmentGradedTest.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\AssignmentGraded as Event;
-
-class AssignmentGradedTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'assign_grades',
-            'objectid' => 1,
-            'eventname' => '\mod_assign\event\submission_graded',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'assign');
-        $this->assertUser(1, $output['graded_user']);
-        $this->assertRecord($input['objectid'], $output['grade']);
-        $this->assertEquals(5, $output['grade_items']->gradepass);
-        $this->assertEquals(5, $output['grade_items']->grademax);
-        $this->assertEquals(0, $output['grade_items']->grademin);
-        $this->assertEquals('<p>test comment</p>', $output['grade_comment']);
-    }
-}
diff --git a/lib/expander/tests/AssignmentSubmittedTest.php b/lib/expander/tests/AssignmentSubmittedTest.php
deleted file mode 100644
index 94b6ed17ae082145d761adce7fcac83756a61b75..0000000000000000000000000000000000000000
--- a/lib/expander/tests/AssignmentSubmittedTest.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\AssignmentSubmitted as Event;
-
-class AssignmentSubmittedTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'assign_submission',
-            'objectid' => 1,
-            'eventname' => '\mod_assign\event\assessable_submitted',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'assign');
-        $this->assertRecord($input['objectid'], $output['submission']);
-    }
-}
diff --git a/lib/expander/tests/CourseCompletedTest.php b/lib/expander/tests/CourseCompletedTest.php
deleted file mode 100644
index 808f86a388a6778c8b244a5d57a5c9b7ce9e7e61..0000000000000000000000000000000000000000
--- a/lib/expander/tests/CourseCompletedTest.php
+++ /dev/null
@@ -1,74 +0,0 @@
-<?php
-/**
- * Created by PhpStorm.
- * User: lee.kirkland
- * Date: 5/19/2016
- * Time: 4:25 PM
- */
-
-namespace LogExpander\Tests;
-use \LogExpander\Events\Event as Event;
-
-/**
- * Class CourseCompletedTest
- * @package LogExpander\Tests
- */
-class CourseCompletedTest extends EventTest
-{
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    /**
-     * Construct the event, using even name, course_completed
-     * @return array
-     */
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => null,
-            'objectid' => null,
-            'eventname' => '\core\event\course_completed',
-            'action' =>'completed',
-            'target'=>'course',
-            'component'=>'core',
-        ]);
-    }
-
-    /**
-     * Assert output is equal to what we expect. 
-     * @param $input
-     * @param $output
-     */
-    protected function assertOutput($input, $output) {
-        $this->assertUser($input['userid'], $output['user']);
-        $this->assertUser($input['relateduserid'], $output['relateduser']);
-        $this->assertCourse($input['courseid'], $output['course']);
-        $this->assertSite($input, $output['app']);
-        $this->assertEquals($input, $output['event']);
-        $this->assertInfo($input, $output['info']);
-    }
-
-    /**
-     * Assert Site is what we expect it to be
-     * @param $input 
-     * @param $output
-     */
-    private function assertSite($input, $output) {
-        $this->assertEquals($this->cfg->wwwroot, $output->url);
-        $this->assertEquals('site', $output->type);
-    }
-
-    /**
-     * Assert course is as expected.
-     * @param $input
-     * @param $output
-     */
-    private function assertCourse($input, $output) {
-        $this->assertRecord($input, $output);
-        $this->assertEquals($this->cfg->wwwroot . '/course/view.php?id=' . $output->id, $output->url);
-    }
-}
\ No newline at end of file
diff --git a/lib/expander/tests/DiscussionEventTest.php b/lib/expander/tests/DiscussionEventTest.php
deleted file mode 100644
index c73eb7c2c21784e388143808589ef61a509dfdcb..0000000000000000000000000000000000000000
--- a/lib/expander/tests/DiscussionEventTest.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\DiscussionEvent as Event;
-
-class DiscussionEventTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'forum_discussions',
-            'objectid' => 1,
-            'eventname' => '\mod_forum\event\discussion_viewed',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'forum');
-        $this->assertDiscussion($input['objectid'], $output['discussion']);
-    }
-}
diff --git a/lib/expander/tests/EventTest.php b/lib/expander/tests/EventTest.php
deleted file mode 100644
index c4753e5eb17789d19754cea1755e27c42494f5bb..0000000000000000000000000000000000000000
--- a/lib/expander/tests/EventTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \PHPUnit_Framework_TestCase as PhpUnitTestCase;
-use \LogExpander\Events\Event as Event;
-
-class EventTest extends PhpUnitTestCase {
-    protected $cfg;
-    protected $repo;
-
-    public function __construct() {
-        $this->cfg = (object) [
-            'wwwroot' => 'http://www.example.com',
-            'release' => '1.0.0',
-        ];
-        $this->repo = new TestRepository((object) [], $this->cfg);
-    }
-
-    /**
-     * Sets up the tests.
-     * @override PhpUnitTestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    /**
-     * Tests the read method of the Event.
-     */
-    public function testRead() {
-        $input = $this->constructInput();
-        $output = $this->event->read($input);
-        $this->assertOutput($input, $output);
-        $this->createExampleFile($output);
-    }
-
-    protected function constructInput() {
-        return [
-            'userid' => 1,
-            'relateduserid' => 1,
-            'courseid' => 1,
-            'timecreated' => 1433946701,
-            'eventname' => '\core\event\course_viewed',
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        $this->assertUser($input['userid'], $output['user']);
-        $this->assertUser($input['relateduserid'], $output['relateduser']);
-        $this->assertCourse($input['courseid'], $output['course']);
-        $this->assertSite($input, $output['app']);
-        $this->assertEquals($input, $output['event']);
-        $this->assertInfo($input, $output['info']);
-    }
-
-    protected function assertInfo($input, $output) {
-        $this->assertEquals($this->cfg->release, $output->{'https://moodle.org/'});
-    }
-
-    protected function assertRecord($input, $output) {
-        $this->assertEquals($input, $output->id);
-        $this->assertEquals('object', $output->type);
-    }
-
-    protected function assertUser($input, $output) {
-        $this->assertRecord($input, $output);
-        $this->assertEquals($this->cfg->wwwroot, $output->url);
-        $this->assertEquals('test_fullname', $output->fullname);
-    }
-
-    private function assertCourse($input, $output) {
-        $this->assertRecord($input, $output);
-        $this->assertEquals($this->cfg->wwwroot . '/course/view.php?id=' . $output->id, $output->url);
-    }
-
-    private function assertSite($input, $output) {
-        $this->assertEquals($this->cfg->wwwroot, $output->url);
-        $this->assertEquals('site', $output->type);
-    }
-
-    protected function assertModule($input, $output, $type) {
-        $this->assertRecord($input, $output);
-        $this->assertEquals($this->cfg->wwwroot . '/mod/'.$type.'/view.php?id=' . $output->id, $output->url);
-    }
-
-    protected function assertAttempt($input, $output) {
-        $this->assertRecord($input, $output);
-        $this->assertEquals($this->cfg->wwwroot . '/mod/quiz/attempt.php?attempt=' . $output->id, $output->url);
-    }
-
-    protected function assertDiscussion($input, $output) {
-        $this->assertRecord($input, $output);
-        $this->assertEquals($this->cfg->wwwroot . '/mod/forum/discuss.php?d=' . $output->id, $output->url);
-    }
-
-    protected function createExampleFile($output) {
-        $classArray = explode('\\', get_class($this));
-        $eventName = str_replace('Test', '', array_pop($classArray));
-        $exampleFile = __DIR__.'/../docs/examples/'.$eventName.'.json';
-        file_put_contents($exampleFile, json_encode($output, JSON_PRETTY_PRINT));
-    }
-}
diff --git a/lib/expander/tests/FacetofaceAttendedTest.php b/lib/expander/tests/FacetofaceAttendedTest.php
deleted file mode 100644
index 1217183dc8b37e26de5d2d2489409e363a98391b..0000000000000000000000000000000000000000
--- a/lib/expander/tests/FacetofaceAttendedTest.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\FacetofaceAttended as Event;
-
-class FacetofaceAttendedTest extends FacetofaceEventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'facetoface_sessions',
-            'objectid' => 1,
-            'eventname' => '\mod_facetoface\event\signup_success',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertEquals(1, $output['signups'][1]->id);
-        $this->assertEquals(1, $output['signups'][1]->attendee->id);
-    }
-}
diff --git a/lib/expander/tests/FacetofaceEventTest.php b/lib/expander/tests/FacetofaceEventTest.php
deleted file mode 100644
index b020f47bd7c148629337a4fc4def7939e6b7ae92..0000000000000000000000000000000000000000
--- a/lib/expander/tests/FacetofaceEventTest.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\FacetofaceEvent as Event;
-
-class FacetofaceEventTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'facetoface_sessions',
-            'objectid' => 1,
-            'eventname' => '\mod_facetoface\event\signup_success',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'facetoface');
-        $this->assertEquals(2, $output['session']->dates[2]->id);
-    }
-}
diff --git a/lib/expander/tests/FeedbackSubmittedTest.php b/lib/expander/tests/FeedbackSubmittedTest.php
deleted file mode 100644
index c9606298839cf3c1871aeeda4a6143611b7d0c4c..0000000000000000000000000000000000000000
--- a/lib/expander/tests/FeedbackSubmittedTest.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\FeedbackSubmitted as Event;
-
-class FeedbackSubittedTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'feedback_completed',
-            'objectid' => '1',
-            'eventname' => '\mod_feedback\event\response_submitted',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'feedback');
-        $this->assertEquals('test_name', $output['questions'][1]->name);
-        $this->assertEquals('http://www.example.com/mod/feedback/edit_item.php?id=1', $output['questions']['1']->url);
-        $this->assertEquals('test_name', $output['questions'][1]->template->name);
-        $this->assertEquals('http://www.example.com/mod/feedback/complete.php?id=1', $output['attempt']->url);
-        $this->assertEquals('1', $output['attempt']->responses['1']->id);
-    }
-}
diff --git a/lib/expander/tests/ModuleEventTest.php b/lib/expander/tests/ModuleEventTest.php
deleted file mode 100644
index 6115653477fc0f6a620f64a8e2e927738da656e3..0000000000000000000000000000000000000000
--- a/lib/expander/tests/ModuleEventTest.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\ModuleEvent as Event;
-
-class ModuleEventTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'page',
-            'objectid' => 1,
-            'eventname' => '\mod_page\event\course_module_viewed',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule($input['objectid'], $output['module'], 'page');
-    }
-}
diff --git a/lib/expander/tests/ScormLaunchedTest.php b/lib/expander/tests/ScormLaunchedTest.php
deleted file mode 100644
index 9de4bcc14c7c3293ea00b680ef1090df4b389d70..0000000000000000000000000000000000000000
--- a/lib/expander/tests/ScormLaunchedTest.php
+++ /dev/null
@@ -1,30 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\ScormLaunched as Event;
-
-class ScormLaunchedTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'scorm_scoes',
-            'objectid' => 1,
-            'eventname' => '\mod_scorm\event\sco_launched',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'scorm');
-        $this->assertScorm(1, $output['scorm_scoes']);
-    }
-
-    protected function assertScorm($input, $output) {
-        $this->assertRecord($input, $output);
-    }
-}
diff --git a/lib/expander/tests/ScormSubmittedTest.php b/lib/expander/tests/ScormSubmittedTest.php
deleted file mode 100644
index 118102d57c7e2b5437bf340b96edd1d5c1c16c72..0000000000000000000000000000000000000000
--- a/lib/expander/tests/ScormSubmittedTest.php
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Events\ScormSubmitted as Event;
-
-class ScormSubmittedTest extends EventTest {
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event($this->repo);
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'scorm_scoes_track',
-            'objectid' => 1,
-            'contextinstanceid' => 1,
-            'eventname' => '\mod_scorm\event\scoreraw_submitted',
-            'other' => 'a:3:{s:9:"attemptid";i:1;s:10:"cmielement";s:18:"cmi.core.score.raw";s:8:"cmivalue";s:3:"100";}',
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'scorm');
-        $this->assertEquals(1, $output['scorm_scoes']->id);
-        $this->assertScormScoesTrack($output);
-        $this->assertCmiData($output);
-    }
-
-    protected function assertScormScoesTrack($output) {
-        $this->assertEquals('status', $output['scorm_scoes_track']['status']);
-        $this->assertEquals(100, $output['scorm_scoes_track']['scoremax']);
-        $this->assertEquals(0, $output['scorm_scoes_track']['scoremin']);
-    }
-
-    protected function assertCmiData($output) {
-        $this->assertEquals(1, $output['cmi_data']['attemptid']);
-        $this->assertEquals('cmi.core.score.raw', $output['cmi_data']['cmielement']);
-        $this->assertEquals(100, $output['cmi_data']['cmivalue']);
-    }
-}
diff --git a/lib/expander/tests/TestRepository.php b/lib/expander/tests/TestRepository.php
deleted file mode 100644
index e17be294d9d463d8c131c66e3a2434d347c3cfcf..0000000000000000000000000000000000000000
--- a/lib/expander/tests/TestRepository.php
+++ /dev/null
@@ -1,88 +0,0 @@
-<?php namespace LogExpander\Tests;
-use \LogExpander\Repository as MoodleRepository;
-use \stdClass as PhpObj;
-
-class TestRepository extends MoodleRepository {
-
-    protected $fakeMoodleDatabase;
-
-    function __construct($store, PhpObj $cfg) {
-        parent::__construct($store, $cfg);
-        $file = file_get_contents(__DIR__ ."/fakeDB.json");
-        $this->fakeMoodleDatabase = json_decode($file, true);
-   }
-
-    /**
-     * Reads an object from the store with the given id.
-     * @param string $type
-     * @param [string => mixed] $query
-     * @return php_obj
-     * @override MoodleRepository
-     */
-    protected function readStoreRecord($type, array $query, $index = 0) {
-        $records = $this->readStoreRecords($type, $query);
-        if (is_array($records)) {
-            return reset($records);
-        }
-        return $records;
-    }
-
-    /**
-     * Reads an array of objects from the store with the given type and query.
-     * @param String $type
-     * @param [String => Mixed] $query
-     * @return PhpArr
-     * @override MoodleRepository
-     */
-    protected function readStoreRecords($type, array $query) {
-        $records = $this->fakeMoodleDatabase[$type];
-        $matchingRecords = [];
-
-        foreach ($records as $record) {
-            foreach ($query as $key => $value) {
-                if ($record[$key] === $value) {
-                    $record['type'] = 'object'; // Required for assertRecord in EventTest.php to pass, but what's the purpose of including and testing this? 
-                    $matchingRecords[$record['id']] = (object) $record;
-                }
-            }
-        }
-
-        // If no matching records found, try to create some!
-        if (count($matchingRecords) == 0) {
-            foreach ($records as $record) {
-                $record['type'] = 'object'; 
-                $id = $record['id'];
-                foreach ($query as $key => $value) {
-                    $record[$key] = $value;
-                }
-                $matchingRecords[$id] = (object) $record;
-            }
-        }
-
-        // Always return at least 2 records.
-        if (count($matchingRecords) == 1) {
-            $newRecord = clone(reset($matchingRecords));
-            $newId = strval(intval($newRecord->id) + 1);
-            $newRecord->id = $newId;
-            $matchingRecords[$newId] = $newRecord;
-        }
-
-        return $matchingRecords;
-    }
-
-    protected function fullname($user) {
-        return "test_fullname";
-    }
-
-    /**
-     * Reads an object from the store with the given id.
-     * @param string $id
-     * @param string $type
-     * @return php_obj
-     */
-    public function readObject($id, $type) {
-        $model = $this->readStoreRecord($type, ['id' => $id]);
-        $model->id = $id;
-        return $model;
-    }
-}
diff --git a/lib/translator/docs/examples/AssignmentGraded.json b/lib/translator/docs/examples/assignment_graded.json
similarity index 98%
rename from lib/translator/docs/examples/AssignmentGraded.json
rename to lib/translator/docs/examples/assignment_graded.json
index afd1c1ec0bfa9c70111a078e1a95e68da825d481..e2e5d475031d698af2ebae86b6ebf912949e830c 100644
--- a/lib/translator/docs/examples/AssignmentGraded.json
+++ b/lib/translator/docs/examples/assignment_graded.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/AssignmentSubmitted.json b/lib/translator/docs/examples/assignment_submitted.json
similarity index 98%
rename from lib/translator/docs/examples/AssignmentSubmitted.json
rename to lib/translator/docs/examples/assignment_submitted.json
index 8fb492b1ea500a0cc77ee1bfa74d30cbf2c0ea06..138af9bdf4edf0ee93205790796661260f819ca5 100644
--- a/lib/translator/docs/examples/AssignmentSubmitted.json
+++ b/lib/translator/docs/examples/assignment_submitted.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/AttemptAbandoned.json b/lib/translator/docs/examples/attempt_abandoned.json
similarity index 98%
rename from lib/translator/docs/examples/AttemptAbandoned.json
rename to lib/translator/docs/examples/attempt_abandoned.json
index eab5984b302a5d344c364e572f5883942bc903d7..ca97a275fcf9456c4d8c3b47a92e9e207732963d 100644
--- a/lib/translator/docs/examples/AttemptAbandoned.json
+++ b/lib/translator/docs/examples/attempt_abandoned.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/AttemptReviewed.json b/lib/translator/docs/examples/attempt_reviewed.json
similarity index 98%
rename from lib/translator/docs/examples/AttemptReviewed.json
rename to lib/translator/docs/examples/attempt_reviewed.json
index 4523ce56911611540760f4d57a1bfefb575278e9..7d909bacce4e956f7c8672d94ce08ebb6a76714b 100644
--- a/lib/translator/docs/examples/AttemptReviewed.json
+++ b/lib/translator/docs/examples/attempt_reviewed.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/AttemptStarted.json b/lib/translator/docs/examples/attempt_started.json
similarity index 98%
rename from lib/translator/docs/examples/AttemptStarted.json
rename to lib/translator/docs/examples/attempt_started.json
index 27d7deff148b7caececa30e01bdc1fb8b7961118..3c158a50135d68f8b484dbb0889764e4bf553bed 100644
--- a/lib/translator/docs/examples/AttemptStarted.json
+++ b/lib/translator/docs/examples/attempt_started.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/CourseCompleted.json b/lib/translator/docs/examples/course_completed.json
similarity index 97%
rename from lib/translator/docs/examples/CourseCompleted.json
rename to lib/translator/docs/examples/course_completed.json
index 955589cbfbbc00d15e13b1e32bc1cd39a85cff7a..132c423404e6a70ed122745089b802eca2b86aea 100644
--- a/lib/translator/docs/examples/CourseCompleted.json
+++ b/lib/translator/docs/examples/course_completed.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/CourseViewed.json b/lib/translator/docs/examples/course_viewed.json
similarity index 97%
rename from lib/translator/docs/examples/CourseViewed.json
rename to lib/translator/docs/examples/course_viewed.json
index a0be8d68595bd1fe3f4170258f238a0753aee8b5..16ca2738106e26be31ea2dc2c0649738e437f1df 100644
--- a/lib/translator/docs/examples/CourseViewed.json
+++ b/lib/translator/docs/examples/course_viewed.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/DiscussionViewed.json b/lib/translator/docs/examples/discussion_viewed.json
similarity index 98%
rename from lib/translator/docs/examples/DiscussionViewed.json
rename to lib/translator/docs/examples/discussion_viewed.json
index 860c1d12cb95b3155b50979846f6c19a8c4176e9..dc5fa14a439b317dc8efc9d69572b84dafb43f46 100644
--- a/lib/translator/docs/examples/DiscussionViewed.json
+++ b/lib/translator/docs/examples/discussion_viewed.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/EnrolmentCreated.json b/lib/translator/docs/examples/enrolment_created.json
similarity index 98%
rename from lib/translator/docs/examples/EnrolmentCreated.json
rename to lib/translator/docs/examples/enrolment_created.json
index 5aa788c76e28f83e0dbb629c12362c46fbc135d9..3f6217d8667726d664488ae2e5a900ddede76263 100644
--- a/lib/translator/docs/examples/EnrolmentCreated.json
+++ b/lib/translator/docs/examples/enrolment_created.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/FacetofaceAttend.json b/lib/translator/docs/examples/facetoface_attend.json
similarity index 98%
rename from lib/translator/docs/examples/FacetofaceAttend.json
rename to lib/translator/docs/examples/facetoface_attend.json
index fbcb198879f260f89d8c9b672c07800be2aa58f0..578ec28311d59b5d04f643c77d1a9ec06995a6f8 100644
--- a/lib/translator/docs/examples/FacetofaceAttend.json
+++ b/lib/translator/docs/examples/facetoface_attend.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/FacetofaceEnrol.json b/lib/translator/docs/examples/facetoface_enrol.json
similarity index 98%
rename from lib/translator/docs/examples/FacetofaceEnrol.json
rename to lib/translator/docs/examples/facetoface_enrol.json
index 2d7f93547e9186ff706d3a33a0bc8d08e0ac4a31..dede05bb66ece98b231fa4434576f7aa9cf062ba 100644
--- a/lib/translator/docs/examples/FacetofaceEnrol.json
+++ b/lib/translator/docs/examples/facetoface_enrol.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/FacetofaceUnenrol.json b/lib/translator/docs/examples/facetoface_unenrol.json
similarity index 98%
rename from lib/translator/docs/examples/FacetofaceUnenrol.json
rename to lib/translator/docs/examples/facetoface_unenrol.json
index cc59c2a04ac4c125817c2ca56ca8edd45794c347..0bdb2cb74b83a19e0fdd104606e28af3462ebbfd 100644
--- a/lib/translator/docs/examples/FacetofaceUnenrol.json
+++ b/lib/translator/docs/examples/facetoface_unenrol.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/FeedbackQuestionSubmitted.json b/lib/translator/docs/examples/feedback_question_submitted.json
similarity index 99%
rename from lib/translator/docs/examples/FeedbackQuestionSubmitted.json
rename to lib/translator/docs/examples/feedback_question_submitted.json
index 8123a6ceb7e8d7ac3cb5629f7e2b7d81bee77958..9ee7cfc1d8e5f680dfd4631feccb401fe7bad0ef 100644
--- a/lib/translator/docs/examples/FeedbackQuestionSubmitted.json
+++ b/lib/translator/docs/examples/feedback_question_submitted.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/FeedbackSubmitted.json b/lib/translator/docs/examples/feedback_submitted.json
similarity index 98%
rename from lib/translator/docs/examples/FeedbackSubmitted.json
rename to lib/translator/docs/examples/feedback_submitted.json
index 2232bd3d00d715511156ee8f9c13422f1154ae2b..0c2f6b47691f98cf582f32ca2dcdb0ee22bdac3f 100644
--- a/lib/translator/docs/examples/FeedbackSubmitted.json
+++ b/lib/translator/docs/examples/feedback_submitted.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/ModuleViewed.json b/lib/translator/docs/examples/module_viewed.json
similarity index 98%
rename from lib/translator/docs/examples/ModuleViewed.json
rename to lib/translator/docs/examples/module_viewed.json
index 9c2a274f60585bdce904cdd5c3e5da4aed516028..7de7c5c7f48c641bd428aa1cae594ebc41023d1a 100644
--- a/lib/translator/docs/examples/ModuleViewed.json
+++ b/lib/translator/docs/examples/module_viewed.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/QuestionSubmitted.json b/lib/translator/docs/examples/question_submitted.json
similarity index 99%
rename from lib/translator/docs/examples/QuestionSubmitted.json
rename to lib/translator/docs/examples/question_submitted.json
index b14f30818cdf3ffc84d44e4d1b729aa0a382f772..1bd6a2a0f86181530479a174e2c1b779798b4fcf 100644
--- a/lib/translator/docs/examples/QuestionSubmitted.json
+++ b/lib/translator/docs/examples/question_submitted.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/ScormEvent.json b/lib/translator/docs/examples/scorm_event.json
similarity index 98%
rename from lib/translator/docs/examples/ScormEvent.json
rename to lib/translator/docs/examples/scorm_event.json
index cb2b12267a7645e9eccb60f352b95cbd5fc04e9b..fe65e0492ebe81c49d34f4474aa01c1855caa731 100644
--- a/lib/translator/docs/examples/ScormEvent.json
+++ b/lib/translator/docs/examples/scorm_event.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/ScormLaunched.json b/lib/translator/docs/examples/scorm_launched.json
similarity index 98%
rename from lib/translator/docs/examples/ScormLaunched.json
rename to lib/translator/docs/examples/scorm_launched.json
index 042bd45396563e27fbdad3e7ff81f9af2872d023..3e3cb5c2dcc10e7a1d77300918c8c010d9c834d7 100644
--- a/lib/translator/docs/examples/ScormLaunched.json
+++ b/lib/translator/docs/examples/scorm_launched.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/ScormScorerawSubmitted.json b/lib/translator/docs/examples/scorm_score_raw_submitted.json
similarity index 98%
rename from lib/translator/docs/examples/ScormScorerawSubmitted.json
rename to lib/translator/docs/examples/scorm_score_raw_submitted.json
index ee1da0f3106fb26c8e24bc99efa40da88d6832dd..295e201cfde95bec9ac880a959dbc3ccb4fd79e1 100644
--- a/lib/translator/docs/examples/ScormScorerawSubmitted.json
+++ b/lib/translator/docs/examples/scorm_score_raw_submitted.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/ScormStatusSubmitted.json b/lib/translator/docs/examples/scorm_status_submitted.json
similarity index 98%
rename from lib/translator/docs/examples/ScormStatusSubmitted.json
rename to lib/translator/docs/examples/scorm_status_submitted.json
index 67d417a27895cf659318516a9252ca7a659317f0..561915a31678e8a8327e5cd4d12540202a3223bb 100644
--- a/lib/translator/docs/examples/ScormStatusSubmitted.json
+++ b/lib/translator/docs/examples/scorm_status_submitted.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/UserLoggedin.json b/lib/translator/docs/examples/user_loggedin.json
similarity index 97%
rename from lib/translator/docs/examples/UserLoggedin.json
rename to lib/translator/docs/examples/user_loggedin.json
index 5336b8d0de1626309d0996059c991b862b9978b5..4f76e5324491df5b78c22ad95999d846044b989a 100644
--- a/lib/translator/docs/examples/UserLoggedin.json
+++ b/lib/translator/docs/examples/user_loggedin.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/UserLoggedout.json b/lib/translator/docs/examples/user_loggedout.json
similarity index 97%
rename from lib/translator/docs/examples/UserLoggedout.json
rename to lib/translator/docs/examples/user_loggedout.json
index ddeaa573d565b98ed7e2e2dcef916fa2538d3620..c1ac6f6358e5ce8b80b2d72e3243abc5d7a5beec 100644
--- a/lib/translator/docs/examples/UserLoggedout.json
+++ b/lib/translator/docs/examples/user_loggedout.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/docs/examples/UserRegistered.json b/lib/translator/docs/examples/user_registered.json
similarity index 97%
rename from lib/translator/docs/examples/UserRegistered.json
rename to lib/translator/docs/examples/user_registered.json
index b8737cc81ebfe997819f208536c3e14e4fcfc356..9a75d891f16d888c95f507e48e7c602299c7969e 100644
--- a/lib/translator/docs/examples/UserRegistered.json
+++ b/lib/translator/docs/examples/user_registered.json
@@ -13,7 +13,7 @@
     "context_info": {
         "https:\/\/moodle.org\/": "1.0.0"
     },
-    "time": "2015-06-10T14:31:41+00:00",
+    "time": "2015-06-10T22:31:41+08:00",
     "app_url": "http:\/\/www.example.com",
     "app_name": "Test site_fullname",
     "app_description": "Test site_summary",
diff --git a/lib/translator/src/Controller.php b/lib/translator/src/Controller.php
index 66dc250ee5102ceffeda6e951500f8f43f229ff9..5fc142a208e19fc84ee95776cc4acb6df57b4d8a 100644
--- a/lib/translator/src/Controller.php
+++ b/lib/translator/src/Controller.php
@@ -1,4 +1,23 @@
-<?php namespace MXTranslator;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \stdClass as PhpObj;
 
 class Controller extends PhpObj {
@@ -11,8 +30,8 @@ class Controller extends PhpObj {
         '\mod_url\event\course_module_viewed' => 'ModuleViewed',
         '\mod_folder\event\course_module_viewed' => 'ModuleViewed',
         '\mod_forum\event\course_module_viewed' => 'ModuleViewed',
-        '\mod_forum\event\discussion_viewed' =>  'DiscussionViewed',
-        '\mod_forum\event\user_report_viewed' =>  'ModuleViewed',
+        '\mod_forum\event\discussion_viewed' => 'DiscussionViewed',
+        '\mod_forum\event\user_report_viewed' => 'ModuleViewed',
         '\mod_book\event\course_module_viewed' => 'ModuleViewed',
         '\mod_scorm\event\course_module_viewed' => 'ModuleViewed',
         '\mod_resource\event\course_module_viewed' => 'ModuleViewed',
@@ -39,37 +58,41 @@ class Controller extends PhpObj {
         '\core\event\user_created' => 'UserRegistered',
         '\core\event\user_enrolment_created' => 'EnrolmentCreated',
         '\mod_scorm\event\sco_launched' => 'ScormLaunched',
-        '\mod_feedback\event\response_submitted' => ['FeedbackSubmitted','FeedbackQuestionSubmitted'],
+        '\mod_feedback\event\response_submitted' => ['FeedbackSubmitted', 'FeedbackQuestionSubmitted'],
         '\mod_facetoface\event\signup_success' => 'FacetofaceEnrol',
         '\mod_facetoface\event\cancel_booking' => 'FacetofaceUnenrol',
         '\mod_facetoface\event\take_attendance' => 'FacetofaceAttend',
         '\mod_scorm\event\scoreraw_submitted' => 'ScormScoreRawSubmitted',
-        '\mod_scorm\event\status_submitted' => 'ScormStatusSubmitted'
+        '\mod_scorm\event\status_submitted' => 'ScormStatusSubmitted',
     ];
 
     /**
      * Constructs a new Controller.
      */
-    public function __construct() {}
+    public function __construct() {
+        // Empty.
+    }
 
     /**
      * Creates a new event.
      * @param [String => Mixed] $events
      * @return [String => Mixed]
      */
-    public function createEvents(array $events) {
+    public function create_events(array $events) {
         $results = [];
         foreach ($events as $index => $opts) {
             $route = isset($opts['event']['eventname']) ? $opts['event']['eventname'] : '';
             if (isset(static::$routes[$route])) {
-                    $routeEvents = is_array(static::$routes[$route]) ? static::$routes[$route] : [static::$routes[$route]];
-                    foreach ($routeEvents as $routeEvent) {
+                $routeevents = is_array(static::$routes[$route]) ? static::$routes[$route] : [static::$routes[$route]];
+                foreach ($routeevents as $routeevent) {
                     try {
-                        $event = '\MXTranslator\Events\\'.$routeEvent;
+                        $event = '\MXTranslator\Events\\' . $routeevent;
                         foreach ((new $event())->read($opts) as $index => $result) {
-                             array_push($results, $result);
-                         }
-                    } catch (UnnecessaryEvent $ex) {}
+                                array_push($results, $result);
+                        }
+                    } catch (UnnecessaryEvent $ex) { // @codingStandardsIgnoreLine
+                        // Empty.
+                    }
                 }
             }
         }
diff --git a/lib/translator/src/Events/AssignmentGraded.php b/lib/translator/src/Events/AssignmentGraded.php
index ebe11d2eecb16b8bfa06401782d7c4bc8dde4ea6..053b85e89d1b02981fead41a9075fb65607a8ea3 100644
--- a/lib/translator/src/Events/AssignmentGraded.php
+++ b/lib/translator/src/Events/AssignmentGraded.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AssignmentGraded extends ModuleViewed {
     /**
@@ -8,27 +26,24 @@ class AssignmentGraded extends ModuleViewed {
      * @override ModuleViewed
      */
     public function read(array $opts) {
-
-        $scoreRaw = (float) ($opts['grade']->grade ?: 0);
-        $scoreMin = (float) ($opts['grade_items']->grademin ?: 0);
-        $scoreMax = (float) ($opts['grade_items']->grademax ?: 0);
-        $scorePass = (float) ($opts['grade_items']->gradepass ?: null);
+        $scoreraw = (float) ($opts['grade']->grade ?: 0);
+        $scoremin = (float) ($opts['grade_items']->grademin ?: 0);
+        $scoremax = (float) ($opts['grade_items']->grademax ?: 0);
+        $scorepass = (float) ($opts['grade_items']->gradepass ?: null);
         $success = false;
-        //if there is no passing score then success is unknown.
-        if ($scorePass == null) {
+        // If there is no passing score then success is unknown.
+        if ($scorepass == null) {
             $success = null;
-        }
-        elseif ($scoreRaw >= $scorePass) {
+        } else if ($scoreraw >= $scorepass) {
             $success = true;
         }
-        //Calculate scaled score as the distance from zero towards the max (or min for negative scores).
-        $scoreScaled;
-        if ($scoreRaw >= 0) {
-            $scoreScaled = $scoreRaw / $scoreMax;
-        }
-        else
-        {
-            $scoreScaled = $scoreRaw / $scoreMin;
+
+        // Calculate scaled score as the distance from zero towards the max (or min for negative scores).
+        $scorescaled;
+        if ($scoreraw >= 0) {
+            $scorescaled = $scoreraw / $scoremax;
+        } else {
+            $scorescaled = $scoreraw / $scoremin;
         }
 
         return [array_merge(parent::read($opts)[0], [
@@ -36,10 +51,10 @@ class AssignmentGraded extends ModuleViewed {
             'graded_user_id' => $opts['graded_user']->id,
             'graded_user_url' => $opts['graded_user']->url,
             'graded_user_name' => $opts['graded_user']->fullname,
-            'grade_score_raw' => $scoreRaw,
-            'grade_score_min' => $scoreMin,
-            'grade_score_max' => $scoreMax,
-            'grade_score_scaled' => $scoreScaled,
+            'grade_score_raw' => $scoreraw,
+            'grade_score_min' => $scoremin,
+            'grade_score_max' => $scoremax,
+            'grade_score_scaled' => $scorescaled,
             'grade_success' => $success,
             'grade_completed' => true,
             'grade_comment' => strip_tags($opts['grade_comment']),
diff --git a/lib/translator/src/Events/AssignmentSubmitted.php b/lib/translator/src/Events/AssignmentSubmitted.php
index 6309a2547e7bb4362729beda2c05056d4a96290f..58d40e3619d6c5dcf6532ed75a2f49664f63c536 100644
--- a/lib/translator/src/Events/AssignmentSubmitted.php
+++ b/lib/translator/src/Events/AssignmentSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AssignmentSubmitted extends ModuleViewed {
     /**
@@ -12,4 +30,4 @@ class AssignmentSubmitted extends ModuleViewed {
             'recipe' => 'assignment_submitted',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/AttemptAbandoned.php b/lib/translator/src/Events/AttemptAbandoned.php
index 3f89d841d83fe6082ca4f685aadb6466b75e2dc2..b1e9ea0991dfbb894349becd341a6ae46e6876b9 100644
--- a/lib/translator/src/Events/AttemptAbandoned.php
+++ b/lib/translator/src/Events/AttemptAbandoned.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AttemptAbandoned extends AttemptReviewed {
     /**
@@ -12,4 +30,4 @@ class AttemptAbandoned extends AttemptReviewed {
             'recipe' => 'attempt_abandoned'
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/AttemptReviewed.php b/lib/translator/src/Events/AttemptReviewed.php
index 0ee6382468d4c3b9a0edba56e3263dd26dfcaf10..41ca80e092effdf8fea12f748985c78f9d78b129 100644
--- a/lib/translator/src/Events/AttemptReviewed.php
+++ b/lib/translator/src/Events/AttemptReviewed.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AttemptReviewed extends AttemptStarted {
     /**
@@ -8,62 +26,58 @@ class AttemptReviewed extends AttemptStarted {
      * @override AttemtStarted
      */
     public function read(array $opts) {
-        if(isset($opts['attempt']->timefinish)){
+        if (isset($opts['attempt']->timefinish)) {
             $seconds = $opts['attempt']->timefinish - $opts['attempt']->timestart;
             $duration = "PT".(string) $seconds."S";
-        }
-        else{
+        } else {
             $duration = "PT0S";
         }
 
-        $scoreRaw = isset($opts['attempt']->sumgrades) ? $opts['attempt']->sumgrades : 0;
-        $scoreMin = (float) ($opts['grade_items']->grademin ?: 0);
-        $scoreMax = (float) ($opts['grade_items']->grademax ?: 0);
-        $scorePass = (float) ($opts['grade_items']->gradepass ?: null);
+        $scoreraw = isset($opts['attempt']->sumgrades) ? $opts['attempt']->sumgrades : 0;
+        $scoremin = (float) ($opts['grade_items']->grademin ?: 0);
+        $scoremax = (float) ($opts['grade_items']->grademax ?: 0);
+        $scorepass = (float) ($opts['grade_items']->gradepass ?: null);
         $success = false;
         // If there is no passing score then success is unknown.
-        if ($scorePass == null) {
+        if ($scorepass == null) {
             $success = null;
-        }
-        elseif ($scoreRaw >= $scorePass) {
+        } else if ($scoreraw >= $scorepass) {
             $success = true;
         }
 
-        // It's possible to configure Moodle quizzes such that you can score higher than the maximum grade. 
-        // This is not allowed by xAPI, so cap the raw at the min/max. 
-        if ($scoreRaw > $scoreMax) {
-            $scoreRaw = $scoreMax;
+        // It's possible to configure Moodle quizzes such that you can score higher than the maximum grade.
+        // This is not allowed by xAPI, so cap the raw at the min/max.
+        if ($scoreraw > $scoremax) {
+            $scoreraw = $scoremax;
         }
-        if ($scoreRaw < $scoreMin) {
-            $scoreRaw = $scoreMin;
+        if ($scoreraw < $scoremin) {
+            $scoreraw = $scoremin;
         }
 
         // Calculate scaled score as the distance from zero towards the max (or min for negative scores).
-        if ($scoreRaw >= 0) {
-            $scoreScaled = $scoreRaw / $scoreMax;
-        }
-        else {
-            $scoreScaled = $scoreRaw / $scoreMin;
+        if ($scoreraw >= 0) {
+            $scorescaled = $scoreraw / $scoremax;
+        } else {
+            $scorescaled = $scoreraw / $scoremin;
         }
 
-        //Determine if the attempt was marked finished
-        if(isset($opts['attempt']->state)){
-            $completedState = $opts['attempt']->state === 'finished';
-        }
-        else{
-            $completedState = false;
+        // Determine if the attempt was marked finished.
+        if (isset($opts['attempt']->state)) {
+            $completedstate = $opts['attempt']->state === 'finished';
+        } else {
+            $completedstate = false;
         }
 
         return [array_merge(parent::read($opts)[0], [
             'recipe' => 'attempt_completed',
-            'attempt_score_raw' => $scoreRaw,
-            'attempt_score_min' => $scoreMin,
-            'attempt_score_max' => $scoreMax,
-            'attempt_score_scaled' => $scoreScaled,
+            'attempt_score_raw' => $scoreraw,
+            'attempt_score_min' => $scoremin,
+            'attempt_score_max' => $scoremax,
+            'attempt_score_scaled' => $scorescaled,
             'attempt_success' => $success,
-            'attempt_completed' => $completedState,
+            'attempt_completed' => $completedstate,
             'attempt_duration' => $duration,
         ])];
     }
 
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/AttemptStarted.php b/lib/translator/src/Events/AttemptStarted.php
index 5f164f317b03d18773db68332beaef056b605c14..8118ac7a17266211f56afc1caf62dd68dd198629 100644
--- a/lib/translator/src/Events/AttemptStarted.php
+++ b/lib/translator/src/Events/AttemptStarted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class AttemptStarted extends ModuleViewed {
     /**
@@ -11,10 +29,10 @@ class AttemptStarted extends ModuleViewed {
         return [array_merge(parent::read($opts)[0], [
             'recipe' => 'attempt_started',
             'attempt_url' => $opts['attempt']->url,
-            'attempt_type' => static::$xapiType.$opts['attempt']->type,
+            'attempt_type' => static::$xapitype.$opts['attempt']->type,
             'attempt_ext' => $opts['attempt'],
             'attempt_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_attempt',
             'attempt_name' => $opts['attempt']->name,
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/CourseCompleted.php b/lib/translator/src/Events/CourseCompleted.php
index fe7fb3f721337726c58b6d7b8277dcc927eef36b..b572e0a7064ce0fde033ad02dd9d68e1418b3f01 100644
--- a/lib/translator/src/Events/CourseCompleted.php
+++ b/lib/translator/src/Events/CourseCompleted.php
@@ -1,22 +1,30 @@
 <?php
-/**
- * Created by PhpStorm.
- * User: lee.kirkland
- * Date: 5/2/2016
- * Time: 4:33 PM
- */
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
 namespace MXTranslator\Events;
 
+defined('MOODLE_INTERNAL') || die();
 
 /**
  * Class CourseCompleted
  * @package MXTranslator\Events
  */
-class CourseCompleted extends CourseViewed
-{
+class CourseCompleted extends CourseViewed {
     /**
-     * overides CourseViewed recipe. 
+     * overides CourseViewed recipe.
      * @param array $opts
      * @return array
      */
diff --git a/lib/translator/src/Events/CourseViewed.php b/lib/translator/src/Events/CourseViewed.php
index bde7ef6f228fb9dfe6dfdf5b7fe96080d126ffb5..fa0a2efa80fe0e6767b671aef24b53cb291ac47d 100644
--- a/lib/translator/src/Events/CourseViewed.php
+++ b/lib/translator/src/Events/CourseViewed.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class CourseViewed extends Event {
     /**
@@ -13,9 +31,9 @@ class CourseViewed extends Event {
             'course_url' => $opts['course']->url,
             'course_name' => $opts['course']->fullname ?: 'A Moodle course',
             'course_description' => strip_tags($opts['course']->summary) ?: 'A Moodle course',
-            'course_type' => static::$xapiType.$opts['course']->type,
+            'course_type' => static::$xapitype.$opts['course']->type,
             'course_ext' => $opts['course'],
             'course_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_course',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/DiscussionViewed.php b/lib/translator/src/Events/DiscussionViewed.php
index 5887f0173d34955fc9f946b3ce270f0a6560bc1f..9731699f1a72941dcaee5a4221ef0db3063707f5 100644
--- a/lib/translator/src/Events/DiscussionViewed.php
+++ b/lib/translator/src/Events/DiscussionViewed.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class DiscussionViewed extends ModuleViewed {
     /**
@@ -13,9 +31,9 @@ class DiscussionViewed extends ModuleViewed {
             'discussion_url' => $opts['discussion']->url,
             'discussion_name' => $opts['discussion']->name,
             'discussion_description' => 'A Moodle discussion.',
-            'discussion_type' => static::$xapiType.$opts['discussion']->type,
+            'discussion_type' => static::$xapitype.$opts['discussion']->type,
             'discussion_ext' => $opts['discussion'],
             'discussion_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_discussion',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/EnrolmentCreated.php b/lib/translator/src/Events/EnrolmentCreated.php
index e6ce8b57bce6024f3f4474f46082664872f88d19..ea9c7648d0212ffc194caf83c2ed947817177578 100644
--- a/lib/translator/src/Events/EnrolmentCreated.php
+++ b/lib/translator/src/Events/EnrolmentCreated.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class EnrolmentCreated extends CourseViewed {
     /**
@@ -18,4 +36,4 @@ class EnrolmentCreated extends CourseViewed {
             'instructor_name' => $opts['user']->fullname,
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/Event.php b/lib/translator/src/Events/Event.php
index d09dab4ff7c4ef1f10fc728bbab764614b067846..a2b8c7cdfe25be586e6d31367a5fe37f34b3ebd3 100644
--- a/lib/translator/src/Events/Event.php
+++ b/lib/translator/src/Events/Event.php
@@ -1,9 +1,28 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \MXTranslator\Repository as Repository;
 use \stdClass as PhpObj;
 
 class Event extends PhpObj {
-    protected static $xapiType = 'http://lrs.learninglocker.net/define/type/moodle/';
+    protected static $xapitype = 'http://lrs.learninglocker.net/define/type/moodle/';
 
     /**
      * Reads data for an event.
@@ -11,7 +30,7 @@ class Event extends PhpObj {
      * @return [String => Mixed]
      */
     public function read(array $opts) {
-        $appName = $opts['app']->fullname ?: 'A Moodle site';
+        $appname = $opts['app']->fullname ?: 'A Moodle site';
 
         return [[
             'user_id' => $opts['user']->id,
@@ -26,8 +45,8 @@ class Event extends PhpObj {
             'context_info' => $opts['info'],
             'time' => date('c', $opts['event']['timecreated']),
             'app_url' => $opts['app']->url,
-            'app_name' => $appName,
-            'app_description' => strip_tags($opts['app']->summary) ?: $appName,
+            'app_name' => $appname,
+            'app_description' => strip_tags($opts['app']->summary) ?: $appname,
             'app_type' => 'http://id.tincanapi.com/activitytype/site',
             'app_ext' => $opts['app'],
             'sendmbox' => $opts['sendmbox'],
diff --git a/lib/translator/src/Events/FacetofaceAttend.php b/lib/translator/src/Events/FacetofaceAttend.php
index 3846c336476193c99e85fc976685bb2482e371f3..258d9aa64e1ebe2f6349e27a767b30db5f430ccb 100644
--- a/lib/translator/src/Events/FacetofaceAttend.php
+++ b/lib/translator/src/Events/FacetofaceAttend.php
@@ -1,10 +1,28 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FacetofaceAttend extends FacetofaceEnrol {
 
-    protected $sessionDuration ;
+    protected $sessionduration;
     protected $statuscodes;
-    protected $partialAttendanceDurationCredit;
+    protected $partialattendancedurationcredit;
 
     /**
      * Reads data for an event.
@@ -25,15 +43,15 @@ class FacetofaceAttend extends FacetofaceEnrol {
             $this->sessionDuration += $date->timefinish;
         }
 
-        $translatorEvents = [];
-        foreach ($opts['signups'] as $signupIndex => $signup) {
-            $signupEvent = $this->getSignupEvent($signup, $opts);
-            if (!is_null($signupEvent)) {
-                $translatorEvent = array_merge(parent::read($opts)[0], $signupEvent);
-                array_push($translatorEvents,$translatorEvent);
+        $translatorevents = [];
+        foreach ($opts['signups'] as $signupindex => $signup) {
+            $signupevent = $this->get_signup_event($signup, $opts);
+            if (!is_null($signupevent)) {
+                $translatorevent = array_merge(parent::read($opts)[0], $signupevent);
+                array_push($translatorevents, $translatorevent);
             }
         }
-        return $translatorEvents;
+        return $translatorevents;
     }
 
     /**
@@ -42,39 +60,38 @@ class FacetofaceAttend extends FacetofaceEnrol {
      * @param [String => Mixed] $opts
      * @return [String => Mixed]
      */
-    private function getSignupEvent($signup, $opts) {
-
-        $currentStatus = null;
-        $previousAttendance = false;
-        $previousPartialAttendance = false;
+    private function get_signup_event($signup, $opts) {
+        $currentstatus = null;
+        $previousattendance = false;
+        $previouspartialattendance = false;
         foreach ($signup->statuses as $status) {
             if ($status->timecreated == $opts['event']['timecreated']) {
-                $currentStatus = $status;
-            } else if ($status->timecreated < $opts['event']['timecreated'] 
+                $currentstatus = $status;
+            } else if ($status->timecreated < $opts['event']['timecreated']
                 && $status->statuscode == $this->statuscodes->partial) {
-                $previousPartialAttendance = true;
-            } else if ($status->timecreated < $opts['event']['timecreated'] 
+                $previouspartialattendance = true;
+            } else if ($status->timecreated < $opts['event']['timecreated']
                 && $status->statuscode == $this->statuscodes->attended) {
-                $previousAttendance = true;
+                $previousattendance = true;
             }
         }
 
-        if (is_null($currentStatus)){
+        if (is_null($currentstatus)) {
             // There is no status with a timestamp matching the event.
             return null;
         }
 
         $duration = null;
         $completion = null;
-        if ($currentStatus->statuscode == $this->statuscodes->attended){
-            if ($previousAttendance == true){
+        if ($currentstatus->statuscode == $this->statuscodes->attended) {
+            if ($previousattendance == true) {
                 // Attendance has already been recorded for this user and session.'
                 return null;
             }
             $duration = $this->sessionDuration;
             $completion = true;
-        } else if ($currentStatus->statuscode == $this->statuscodes->partial){
-            if ($previousPartialAttendance == true){
+        } else if ($currentstatus->statuscode == $this->statuscodes->partial) {
+            if ($previouspartialattendance == true) {
                 // Partial attendance has already been recorded for this user and session.
                 return null;
             }
@@ -94,4 +111,4 @@ class FacetofaceAttend extends FacetofaceEnrol {
             'attempt_completion' => $completion
         ];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/FacetofaceEnrol.php b/lib/translator/src/Events/FacetofaceEnrol.php
index adcd67e6a5119f8b134ab58d09dae515bef42aa7..0ae7091a8ba8613a4f3d50c6c4072b3669ff31a9 100644
--- a/lib/translator/src/Events/FacetofaceEnrol.php
+++ b/lib/translator/src/Events/FacetofaceEnrol.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FacetofaceEnrol extends ModuleViewed {
     /**
@@ -8,14 +26,13 @@ class FacetofaceEnrol extends ModuleViewed {
      * @override ModuleViewed
      */
     public function read(array $opts) {
-
-        $sessionName = 'Session '.$opts['session']->id.' of '.$opts['module']->name;
+        $sessionname = 'Session '.$opts['session']->id.' of '.$opts['module']->name;
         return [array_merge(parent::read($opts)[0], [
             'recipe' => 'training_session_enrol',
             'session_url' => $opts['session']->url,
-            'session_name' => $sessionName,
-            'session_description' => $sessionName,
+            'session_name' => $sessionname,
+            'session_description' => $sessionname,
             'session_type' => 'http://activitystrea.ms/schema/1.0/event',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/FacetofaceUnenrol.php b/lib/translator/src/Events/FacetofaceUnenrol.php
index d0948c7d8c0412f12c1b67b1d71a9ba52031c906..771d4aad68488886748a3426bc59730af2771039 100644
--- a/lib/translator/src/Events/FacetofaceUnenrol.php
+++ b/lib/translator/src/Events/FacetofaceUnenrol.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FacetofaceUnenrol extends FacetofaceEnrol {
     /**
@@ -12,4 +30,4 @@ class FacetofaceUnenrol extends FacetofaceEnrol {
             'recipe' => 'training_session_unenrol'
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/FeedbackQuestionSubmitted.php b/lib/translator/src/Events/FeedbackQuestionSubmitted.php
index abe782f79b22c4b6ebadb4fa212f1ea21f7c1fbc..4971f927810dcf488fce3b1f9f7ca32a0ce66264 100644
--- a/lib/translator/src/Events/FeedbackQuestionSubmitted.php
+++ b/lib/translator/src/Events/FeedbackQuestionSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FeedbackQuestionSubmitted extends FeedbackSubmitted {
     /**
@@ -8,86 +26,86 @@ class FeedbackQuestionSubmitted extends FeedbackSubmitted {
      * @override AttemtStarted
      */
     public function read(array $opts) {
-        $translatorEvents = [];
+        $translatorevents = [];
 
-        $feedback = parent::parseFeedback($opts);
+        $feedback = parent::parse_feedback($opts);
 
-        // Push question statements to $translatorEvents['events'].
-        foreach ($feedback->questions as $questionId => $questionAttempt) {
+        // Push question statements to $translatorevents['events'].
+        foreach ($feedback->questions as $questionid => $questionattempt) {
             array_push(
-                $translatorEvents,
-                $this->questionStatement(
+                $translatorevents,
+                $this->question_statement(
                     parent::read($opts)[0],
-                    $questionAttempt
+                    $questionattempt
                 )
             );
         }
 
-        return $translatorEvents;
+        return $translatorevents;
     }
 
     /**
      * Build a translator event for an individual question attempt.
      * @param [String => Mixed] $template
-     * @param PHPObj $questionAttempt
+     * @param PHPObj $questionattempt
      * @param PHPObj $question
      * @return [String => Mixed]
      */
-    protected function questionStatement($template, $questionAttempt) {
+    protected function question_statement($template, $questionattempt) {
 
-        $translatorEvent = [
+        $translatorevent = [
             'recipe' => 'attempt_question_completed',
-            'question_attempt_ext' => $questionAttempt,
+            'question_attempt_ext' => $questionattempt,
             'question_attempt_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_feedback_question_attempt',
-            'question_ext' => $questionAttempt->question,
+            'question_ext' => $questionattempt->question,
             'question_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_feedback_question',
-            'question_name' => $questionAttempt->question->name ?: 'A Moodle feedback question',
-            'question_description' => $questionAttempt->question->name ?: 'A Moodle feedback question',
-            'question_url' => $questionAttempt->question->url,
-            'attempt_score_scaled' => $questionAttempt->score->scaled,
-            'attempt_score_raw' => $questionAttempt->score->raw, 
-            'attempt_score_min' => $questionAttempt->score->min, 
-            'attempt_score_max' => $questionAttempt->score->max,
-            'attempt_response' => $questionAttempt->response,
+            'question_name' => $questionattempt->question->name ?: 'A Moodle feedback question',
+            'question_description' => $questionattempt->question->name ?: 'A Moodle feedback question',
+            'question_url' => $questionattempt->question->url,
+            'attempt_score_scaled' => $questionattempt->score->scaled,
+            'attempt_score_raw' => $questionattempt->score->raw,
+            'attempt_score_min' => $questionattempt->score->min,
+            'attempt_score_max' => $questionattempt->score->max,
+            'attempt_response' => $questionattempt->response,
             'attempt_success' => null,
             'attempt_completed' => true,
             'interaction_correct_responses' => null,
-            'attempt_ext' => null // For questions the attempt extension is not used, so there's no need to pass that bulk of data
+            'attempt_ext' => null // For questions the attempt extension is not used, so there's no need to pass that bulk of data.
         ];
 
-        switch ($questionAttempt->question->typ) {
+        switch ($questionattempt->question->typ) {
             case 'multichoice':
-                $translatorEvent['interaction_type'] = 'choice';
-                $translatorEvent['interaction_choices'] = (object)[];
-                foreach ($questionAttempt->options as $index => $option) {
-                    $translatorEvent['interaction_choices']->$index = $option->description;
+                $translatorevent['interaction_type'] = 'choice';
+                $translatorevent['interaction_choices'] = (object)[];
+                foreach ($questionattempt->options as $index => $option) {
+                    $translatorevent['interaction_choices']->$index = $option->description;
                 }
                 break;
             case 'multichoicerated':
-                $translatorEvent['interaction_type'] = 'likert';
-                $translatorEvent['interaction_scale'] = (object)[];
-                foreach ($questionAttempt->options as $index => $option) {
-                    $translatorEvent['interaction_scale']->$index = $option->description;
+                $translatorevent['interaction_type'] = 'likert';
+                $translatorevent['interaction_scale'] = (object)[];
+                foreach ($questionattempt->options as $index => $option) {
+                    $translatorevent['interaction_scale']->$index = $option->description;
                 }
                 break;
             case 'textfield':
-                $translatorEvent['interaction_type'] = 'fill-in';
+                $translatorevent['interaction_type'] = 'fill-in';
                 break;
             case 'textarea':
-                $translatorEvent['interaction_type'] = 'long-fill-in';
+                $translatorevent['interaction_type'] = 'long-fill-in';
                 break;
             case 'numeric':
-                $translatorEvent['interaction_type'] = 'numeric';
+                $translatorevent['interaction_type'] = 'numeric';
                 break;
             case 'info':
-                $translatorEvent['interaction_type'] = 'other';
+                $translatorevent['interaction_type'] = 'other';
                 break;
             default:
-                // Unsupported type. 
+                // Unsupported type.
                 break;
         }
 
-        return array_merge($template, $translatorEvent);
+        return array_merge($template, $translatorevent);
     }
 
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/FeedbackSubmitted.php b/lib/translator/src/Events/FeedbackSubmitted.php
index d747bf1bb81484ece9c3c636c7b49cb3dac92eef..43032c569aaa7a578b8de5d733c499ab57ac9f46 100644
--- a/lib/translator/src/Events/FeedbackSubmitted.php
+++ b/lib/translator/src/Events/FeedbackSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class FeedbackSubmitted extends ModuleViewed {
     /**
@@ -9,12 +27,12 @@ class FeedbackSubmitted extends ModuleViewed {
      */
     public function read(array $opts) {
 
-        $feedback = $this->parseFeedback($opts);
+        $feedback = $this->parse_feedback($opts);
 
         return [array_merge(parent::read($opts)[0], [
             'recipe' => 'attempt_completed',
             'attempt_url' => $opts['attempt']->url,
-            'attempt_type' => static::$xapiType.$opts['attempt']->type,
+            'attempt_type' => static::$xapitype.$opts['attempt']->type,
             'attempt_ext' => $opts['attempt'],
             'attempt_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_feedback_attempt',
             'attempt_name' => $opts['attempt']->name,
@@ -34,29 +52,29 @@ class FeedbackSubmitted extends ModuleViewed {
      * @param [Array => Mixed] $opts
      * @return [PHPObj => Mixed]
      */
-    public function parseFeedback($opts){
-        $parsedQuestions = [];
-        $scoreMax = 0;
-        $scoreRaw = 0;
+    public function parse_feedback($opts) {
+        $parsedquestions = [];
+        $scoremax = 0;
+        $scoreraw = 0;
 
         foreach ($opts['questions'] as $item => $question) {
-            // Find the response to the current question
-            $currentResponse = null;
-            foreach ($opts['attempt']->responses as $responseId => $response) {
+            // Find the response to the current question.
+            $currentresponse = null;
+            foreach ($opts['attempt']->responses as $responseid => $response) {
                 if (!empty($response->item) && $response->item == $item) {
-                    $currentResponse = $response;
+                    $currentresponse = $response;
                 }
             }
 
-            if (is_null($currentResponse)) {
+            if (is_null($currentresponse)) {
                 // Perhaps a label or the learner did not answer this question - don't add to the array.
                 break;
             }
 
-            // Parse the current question
-            $parsedQuestion = (object)[
+            // Parse the current question.
+            $parsedquestion = (object)[
                 'question' => $question,
-                'options' => $this->parseQuestionPresentation($question->presentation, $question->typ),
+                'options' => $this->parse_question_presentation($question->presentation, $question->typ),
                 'score' => (object) [
                     'max' => 0,
                     'raw' => 0
@@ -64,59 +82,57 @@ class FeedbackSubmitted extends ModuleViewed {
                 'response' => null
             ];
 
-            $parsedQuestion->response = $currentResponse->id;
+            $parsedquestion->response = $currentresponse->id;
 
-            // Add scores and response
-            foreach ($parsedQuestion->options as $optionIndex => $option) {
-                if (isset($option->value) && $option->value > $parsedQuestion->score->max) {
-                    $parsedQuestion->score->max = $option->value;
+            // Add scores and response.
+            foreach ($parsedquestion->options as $optionindex => $option) {
+                if (isset($option->value) && $option->value > $parsedquestion->score->max) {
+                    $parsedquestion->score->max = $option->value;
                 }
 
-                // Find the option the learner selected
-                if ($optionIndex == $currentResponse->id){
+                // Find the option the learner selected.
+                if ($optionindex == $currentresponse->id) {
                     if (isset($option->value)) {
-                        $parsedQuestion->score->raw = $option->value;
+                        $parsedquestion->score->raw = $option->value;
                     }
                 }
             }
 
-            $scoreMax += $parsedQuestion->score->max;
-            $scoreRaw += $parsedQuestion->score->raw;
+            $scoremax += $parsedquestion->score->max;
+            $scoreraw += $parsedquestion->score->raw;
 
-            if ($parsedQuestion->score->max == 0) {
-                $parsedQuestion->score->max = null;
-                $parsedQuestion->score->raw = null;
-            }
-            else {
-                $parsedQuestion->score->min = 0;
-                $parsedQuestion->score->scaled = $parsedQuestion->score->raw / $parsedQuestion->score->max;
+            if ($parsedquestion->score->max == 0) {
+                $parsedquestion->score->max = null;
+                $parsedquestion->score->raw = null;
+            } else {
+                $parsedquestion->score->min = 0;
+                $parsedquestion->score->scaled = $parsedquestion->score->raw / $parsedquestion->score->max;
             }
 
             array_push(
-                $parsedQuestions, 
-                $parsedQuestion
+                $parsedquestions,
+                $parsedquestion
             );
         }
 
-        $scoreMin = null;
-        $scoreScaled = null;
-        if ($scoreMax == 0){
-            $scoreMax = null;
-            $scoreRaw = null;
-        }
-        else {
-            $scoreScaled = $scoreRaw / $scoreMax;
-            $scoreMin = 0;
+        $scoremin = null;
+        $scorescaled = null;
+        if ($scoremax == 0) {
+            $scoremax = null;
+            $scoreraw = null;
+        } else {
+            $scorescaled = $scoreraw / $scoremax;
+            $scoremin = 0;
         }
 
         return (object)[
-            'questions' => $parsedQuestions,
+            'questions' => $parsedquestions,
             'score' => (object) [
-                'max' => $scoreMax,
-                'raw' => $scoreRaw,
-                'min' => $scoreMin,
-                'scaled' => $scoreScaled
-            ] 
+                'max' => $scoremax,
+                'raw' => $scoreraw,
+                'min' => $scoremin,
+                'scaled' => $scorescaled
+            ]
         ];
     }
 
@@ -126,9 +142,9 @@ class FeedbackSubmitted extends ModuleViewed {
      * @param [String => Mixed] $type
      * @return [Array => Mixed]
      */
-    protected function parseQuestionPresentation ($presentation, $type){
+    protected function parse_question_presentation($presentation, $type) {
 
-        // Text areas don't have options or scores
+        // Text areas don't have options or scores.
         if ($type == 'textarea') {
             return [];
         }
@@ -151,14 +167,14 @@ class FeedbackSubmitted extends ModuleViewed {
                     ]);
                     break;
                 case 'multichoicerated':
-                    $optionArr = explode('#### ', $option);
+                    $optionarr = explode('#### ', $option);
                     array_push($return, (object)[
-                        'description' => $optionArr[1],
-                        'value' => $optionArr[0]
+                        'description' => $optionarr[1],
+                        'value' => $optionarr[0]
                     ]);
                     break;
                 default:
-                    // Unsupported type. 
+                    // Unsupported type.
                     return [];
                     break;
             }
@@ -167,4 +183,4 @@ class FeedbackSubmitted extends ModuleViewed {
         return $return;
     }
 
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/ModuleViewed.php b/lib/translator/src/Events/ModuleViewed.php
index 2d1af660de15f97d7f254518b324e4e4ef7d015d..f4351ca3470aa6bf2575f20136706f2edb771caf 100644
--- a/lib/translator/src/Events/ModuleViewed.php
+++ b/lib/translator/src/Events/ModuleViewed.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ModuleViewed extends CourseViewed {
     /**
@@ -13,7 +31,7 @@ class ModuleViewed extends CourseViewed {
             'module_url' => $opts['module']->url,
             'module_name' => $opts['module']->name,
             'module_description' => isset($opts['module']->intro) ? $opts['module']->intro : 'A module',
-            'module_type' => static::$xapiType.$opts['module']->type,
+            'module_type' => static::$xapitype.$opts['module']->type,
             'module_ext' => $opts['module'],
             'module_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_module'
         ])];
diff --git a/lib/translator/src/Events/QuestionSubmitted.php b/lib/translator/src/Events/QuestionSubmitted.php
index d612e6c9b9ecf43cd4e8f02e55e091dc0dec5a47..9542c57cece7d5a795857015029a745275872a45 100644
--- a/lib/translator/src/Events/QuestionSubmitted.php
+++ b/lib/translator/src/Events/QuestionSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class QuestionSubmitted extends AttemptStarted {
     /**
@@ -8,34 +26,34 @@ class QuestionSubmitted extends AttemptStarted {
      * @override AttemtStarted
      */
     public function read(array $opts) {
-        $translatorEvents = [];
+        $translatorevents = [];
 
-        // Push question statements to $translatorEvents['events'].
-        foreach ($opts['attempt']->questions as $questionId => $questionAttempt) {
-            $question = $this->expandQuestion(
-                $opts['questions'][$questionAttempt->questionid],
+        // Push question statements to $translatorevents['events'].
+        foreach ($opts['attempt']->questions as $questionid => $questionattempt) {
+            $question = $this->expand_question(
+                $opts['questions'][$questionattempt->questionid],
                 $opts['questions']
             );
             array_push(
-                $translatorEvents,
-                $this->questionStatement(
+                $translatorevents,
+                $this->question_statement(
                     parent::read($opts)[0],
-                    $questionAttempt,
+                    $questionattempt,
                     $question
                 )
             );
         }
 
-        return $translatorEvents;
+        return $translatorevents;
     }
 
     /**
-     * For certain question types, expands question data by pulling from other questions. 
+     * For certain question types, expands question data by pulling from other questions.
      * @param PHPObj $question
      * @param Array $questions
      * @return PHPObj $question
      */
-    protected function expandQuestion($question, $questions) {
+    protected function expand_question($question, $questions) {
         if ($question->qtype == 'randomsamatch') {
             $subquestions = [];
             foreach ($questions as $otherquestion) {
@@ -43,22 +61,22 @@ class QuestionSubmitted extends AttemptStarted {
                     foreach ($otherquestion->answers as $answer) {
                         if (intval($answer->fraction) === 1) {
                             array_push(
-                                $subquestions, 
+                                $subquestions,
                                 (object) [
                                     "id" => $answer->id,
                                     "questiontext" => $otherquestion->questiontext,
                                     "answertext" => $answer->answer
                                 ]
                             );
-                            // Only take the first correct answer because that's what Moodle does. 
+                            // Only take the first correct answer because that's what Moodle does.
                             break;
                         }
                     }
-                } 
+                }
             }
 
             $question->match = (object) [
-             'subquestions' => $subquestions
+                'subquestions' => $subquestions
             ];
         }
         return $question;
@@ -67,41 +85,41 @@ class QuestionSubmitted extends AttemptStarted {
     /**
      * Build a translator event for an individual question attempt.
      * @param [String => Mixed] $template
-     * @param PHPObj $questionAttempt
+     * @param PHPObj $questionattempt
      * @param PHPObj $question
      * @return [String => Mixed]
      */
-    protected function questionStatement($template, $questionAttempt, $question) {
+    protected function question_statement($template, $questionattempt, $question) {
 
-        // For questions, only include data relevant to the current question in the attempt extension. 
-        $template['attempt_ext']->questions = [$questionAttempt];
+        // For questions, only include data relevant to the current question in the attempt extension.
+        $template['attempt_ext']->questions = [$questionattempt];
 
-        $translatorEvent = [
+        $translatorevent = [
             'recipe' => 'attempt_question_completed',
             'attempt_ext' => $template['attempt_ext'],
-            'question_attempt_ext' => $questionAttempt,
+            'question_attempt_ext' => $questionattempt,
             'question_attempt_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_question_attempt',
             'question_ext' => $question,
             'question_ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_question',
             'question_name' => $question->name ?: 'A Moodle quiz question',
             'question_description' => strip_tags($question->questiontext) ?: 'A Moodle quiz question',
             'question_url' => $question->url,
-            'attempt_score_scaled' => 0, //default
-            'attempt_score_raw' => 0, //default
-            'attempt_score_min' => 0, //always 0
-            'attempt_score_max' => isset($questionAttempt->maxmark) ? floatval($questionAttempt->maxmark) : 100,
-            'attempt_response' => $questionAttempt->responsesummary, //default
-            'interaction_correct_responses' => [$questionAttempt->rightanswer], //default
-            'interaction_type' => 'other', //default
+            'attempt_score_scaled' => 0, // Default.
+            'attempt_score_raw' => 0, // Default.
+            'attempt_score_min' => 0, // Always 0.
+            'attempt_score_max' => isset($questionattempt->maxmark) ? floatval($questionattempt->maxmark) : 100,
+            'attempt_response' => $questionattempt->responsesummary, // Default.
+            'interaction_correct_responses' => [$questionattempt->rightanswer], // Default.
+            'interaction_type' => 'other', // Default.
         ];
 
-        $submittedState = $this->getLastState($questionAttempt);
+        $submittedstate = $this->get_last_state($questionattempt);
 
-        if (!is_null($submittedState->timestamp)) {
-            $translatorEvent['time'] = date('c', $submittedState->timestamp);
+        if (!is_null($submittedstate->timestamp)) {
+            $translatorevent['time'] = date('c', $submittedstate->timestamp);
         }
 
-        $translatorEvent = $this->resultFromState($translatorEvent, $questionAttempt, $submittedState);
+        $translatorevent = $this->result_from_state($translatorevent, $questionattempt, $submittedstate);
 
         $numerictypes = [
             'numerical',
@@ -120,155 +138,153 @@ class QuestionSubmitted extends AttemptStarted {
         ];
 
         if (in_array($question->qtype, $matchtypes)) {
-             $translatorEvent = $this->matchStatement($translatorEvent, $questionAttempt, $question);
+             $translatorevent = $this->match_statement($translatorevent, $questionattempt, $question);
         } else if (in_array($question->qtype, $numerictypes)) {
-             $translatorEvent = $this->numericStatement($translatorEvent, $questionAttempt, $question);
+             $translatorevent = $this->numeric_statement($translatorevent, $questionattempt, $question);
         } else if (in_array($question->qtype, $fillintypes)) {
-             $translatorEvent = $this->shortanswerStatement($translatorEvent, $questionAttempt, $question);
+             $translatorevent = $this->shortanswer_statement($translatorevent, $questionattempt, $question);
         } else if (!is_null($question->answers) && ($question->answers !== [])) {
-            $translatorEvent = $this->multichoiceStatement($translatorEvent, $questionAttempt, $question);
+            $translatorevent = $this->multichoice_statement($translatorevent, $questionattempt, $question);
         }
 
         if (strpos($question->qtype, 'calculated') === 0) {
-            $translatorEvent['question_url'] .= '&variant='.$questionAttempt->variant;
-            $translatorEvent['question_name'] .= ' - variant '.$questionAttempt->variant;
-            $translatorEvent['question_description'] .= ' - variant '.$questionAttempt->variant;
+            $translatorevent['question_url'] .= '&variant=' . $questionattempt->variant;
+            $translatorevent['question_name'] .= ' - variant ' . $questionattempt->variant;
+            $translatorevent['question_description'] .= ' - variant ' . $questionattempt->variant;
         }
 
-        return array_merge($template, $translatorEvent);
+        return array_merge($template, $translatorevent);
     }
 
     /**
      * Add some result data to translator event for an individual question attempt based on Moodle's question attempt state
-     * @param [String => Mixed] $translatorEvent
-     * @param PHPObj $questionAttempt
+     * @param [String => Mixed] $translatorevent
+     * @param PHPObj $questionattempt
      * @param PHPObj $submittedState
      * @return [String => Mixed]
      */
-    public function resultFromState($translatorEvent, $questionAttempt, $submittedState) {
-        $maxMark = isset($questionAttempt->maxmark) ? $questionAttempt->maxmark : 100;
-        $scaledScore = $submittedState->fraction;
-        $rawScore = $scaledScore * floatval($maxMark);
+    public function result_from_state($translatorevent, $questionattempt, $submittedstate) {
+        $maxmark = isset($questionattempt->maxmark) ? $questionattempt->maxmark : 100;
+        $scaledscore = $submittedstate->fraction;
+        $rawscore = $scaledscore * floatval($maxmark);
 
-        switch ($submittedState->state) {
+        switch ($submittedstate->state) {
             case "todo":
-                $translatorEvent['attempt_completed'] = false;
-                $translatorEvent['attempt_success'] = null;
+                $translatorevent['attempt_completed'] = false;
+                $translatorevent['attempt_success'] = null;
                 break;
             case "gaveup":
-                $translatorEvent['attempt_completed'] = false;
-                $translatorEvent['attempt_success'] = false;
+                $translatorevent['attempt_completed'] = false;
+                $translatorevent['attempt_success'] = false;
                 break;
             case "complete":
-                $translatorEvent['attempt_completed'] = true;
-                $translatorEvent['attempt_success'] = null;
+                $translatorevent['attempt_completed'] = true;
+                $translatorevent['attempt_success'] = null;
                 break;
             case "gradedwrong":
-                $translatorEvent['attempt_completed'] = true;
-                $translatorEvent['attempt_success'] = false;
-                $translatorEvent['attempt_score_scaled'] = $scaledScore;
-                $translatorEvent['attempt_score_raw'] = $rawScore;
+                $translatorevent['attempt_completed'] = true;
+                $translatorevent['attempt_success'] = false;
+                $translatorevent['attempt_score_scaled'] = $scaledscore;
+                $translatorevent['attempt_score_raw'] = $rawscore;
                 break;
             case "gradedpartial":
-                $translatorEvent['attempt_completed'] = true;
-                $translatorEvent['attempt_success'] = false;
-                $translatorEvent['attempt_score_scaled'] = $scaledScore;
-                $translatorEvent['attempt_score_raw'] = $rawScore;
+                $translatorevent['attempt_completed'] = true;
+                $translatorevent['attempt_success'] = false;
+                $translatorevent['attempt_score_scaled'] = $scaledscore;
+                $translatorevent['attempt_score_raw'] = $rawscore;
                 break;
             case "gradedright":
-                $translatorEvent['attempt_completed'] = true;
-                $translatorEvent['attempt_success'] = true;
-                $translatorEvent['attempt_score_scaled'] = $scaledScore;
-                $translatorEvent['attempt_score_raw'] = $rawScore;
+                $translatorevent['attempt_completed'] = true;
+                $translatorevent['attempt_success'] = true;
+                $translatorevent['attempt_score_scaled'] = $scaledscore;
+                $translatorevent['attempt_score_raw'] = $rawscore;
                 break;
             default:
-                $translatorEvent['attempt_completed'] = null;
-                $translatorEvent['attempt_success'] = null;
+                $translatorevent['attempt_completed'] = null;
+                $translatorevent['attempt_success'] = null;
                 break;
         }
 
-        return $translatorEvent;
+        return $translatorevent;
     }
 
     /**
      * Add data specifc to multichoice and true/false question types to a translator event.
-     * @param [String => Mixed] $translatorEvent
-     * @param PHPObj $questionAttempt
+     * @param [String => Mixed] $translatorevent
+     * @param PHPObj $questionattempt
      * @param PHPObj $question
      * @return [String => Mixed]
      */
-    public function multichoiceStatement($translatorEvent, $questionAttempt, $question) {
+    public function multichoice_statement($translatorevent, $questionattempt, $question) {
         $choices = [];
         foreach ($question->answers as $answer) {
             $choices['moodle_quiz_question_answer_'.$answer->id] = strip_tags($answer->answer);
         }
 
         // If there are answers, assume multiple choice until proven otherwise.
-        $translatorEvent['interaction_type'] = 'choice';
-        $translatorEvent['interaction_choices'] = $choices;
+        $translatorevent['interaction_type'] = 'choice';
+        $translatorevent['interaction_choices'] = $choices;
 
         $responses = [];
-        $correctResponses = [];
+        $correctresponses = [];
 
-        // We can't simply explode $questionAttempt->responsesummary because responses may contain "; ". 
-        foreach ($choices as $answerId => $choice) {
-            if ($this->inResponsesSummary($questionAttempt->responsesummary, $choice, '; ', '; ')) {
-                array_push($responses, $answerId);
+        // We can't simply explode $questionAttempt->responsesummary because responses may contain "; ".
+        foreach ($choices as $answerid => $choice) {
+            if ($this->in_responses_summary($questionattempt->responsesummary, $choice, '; ', '; ')) {
+                array_push($responses, $answerid);
             }
-            if (!(strpos($questionAttempt->rightanswer, $choice) === false)) {
-                array_push($correctResponses, $answerId);
+            if (!(strpos($questionattempt->rightanswer, $choice) === false)) {
+                array_push($correctresponses, $answerid);
             }
         }
 
         if ($responses != []) {
-            $translatorEvent['attempt_response'] = implode('[,]', $responses);
+            $translatorevent['attempt_response'] = implode('[,]', $responses);
         }
 
-        $translatorEvent['interaction_correct_responses'] = [implode('[,]', $correctResponses)];
+        $translatorevent['interaction_correct_responses'] = [implode('[,]', $correctresponses)];
 
         // Special handling of true-false question type (some overlap with multichoice).
         if ($question->qtype == 'truefalse') {
-            $translatorEvent['interaction_type'] = 'true-false';
-            $translatorEvent['interaction_choices'] = null;
+            $translatorevent['interaction_type'] = 'true-false';
+            $translatorevent['interaction_choices'] = null;
 
-            if ($questionAttempt->responsesummary == 'True') {
-                $translatorEvent['attempt_response'] = 'true';
-            } else if ($questionAttempt->responsesummary == 'False') {
-                $translatorEvent['attempt_response'] = 'false';
+            if ($questionattempt->responsesummary == 'True') {
+                $translatorevent['attempt_response'] = 'true';
+            } else if ($questionattempt->responsesummary == 'False') {
+                $translatorevent['attempt_response'] = 'false';
             }
 
-            if ($questionAttempt->rightanswer == 'True') {
-                $translatorEvent['interaction_correct_responses'] = ['true'];
-            } else if ($questionAttempt->rightanswer == 'False') {
-                $translatorEvent['interaction_correct_responses'] = ['false'];
+            if ($questionattempt->rightanswer == 'True') {
+                $translatorevent['interaction_correct_responses'] = ['true'];
+            } else if ($questionattempt->rightanswer == 'False') {
+                $translatorevent['interaction_correct_responses'] = ['false'];
             }
         }
 
-
-        return $translatorEvent;
+        return $translatorevent;
     }
 
     /**
      * Add data specifc to numeric question types to a translator event.
-     * @param [String => Mixed] $translatorEvent
-     * @param PHPObj $questionAttempt
+     * @param [String => Mixed] $translatorevent
+     * @param PHPObj $questionattempt
      * @param PHPObj $question
      * @return [String => Mixed]
      */
-    public function numericStatement($translatorEvent, $questionAttempt, $question) {
-
-        $translatorEvent['interaction_type'] = 'numeric';
+    public function numeric_statement($translatorevent, $questionattempt, $question) {
 
+        $translatorevent['interaction_type'] = 'numeric';
 
-        $correctAnswerId = null;
+        $correctanswerid = null;
         foreach ($question->answers as $answer) {
             if (intval($answer->fraction) === 1) {
-                $correctAnswerId = $answer->id;
+                $correctanswerid = $answer->id;
             }
         }
 
         $tolerance = 0;
-        $toleranceType = 2;
+        $tolerancetype = 2;
         $answersdata = [];
         if ($question->qtype == "numerical") {
             $answersdata = $question->numerical->answers;
@@ -276,136 +292,136 @@ class QuestionSubmitted extends AttemptStarted {
             $answersdata = $question->calculated->answers;
         }
 
-        if (!is_null($correctAnswerId) && count($answersdata) > 0) {
+        if (!is_null($correctanswerid) && count($answersdata) > 0) {
             foreach ($answersdata as $answerdata) {
-                if(isset($answerdata->answer)){
-                    if ($answerdata->answer == $correctAnswerId) {
+                if (isset($answerdata->answer)) {
+                    if ($answerdata->answer == $correctanswerid) {
                         $tolerance = floatval($answerdata->tolerance);
                         if (isset($answerdata->tolerancetype)) {
-                            $toleranceType = intval($answerdata->tolerancetype);
+                            $tolerancetype = intval($answerdata->tolerancetype);
                         }
                     }
                 }
             }
         }
 
-        $rigthtanswer = floatval($questionAttempt->rightanswer);
+        $rigthtanswer = floatval($questionattempt->rightanswer);
         if ($tolerance > 0) {
-            $toleranceMax = $rigthtanswer + $tolerance;
-            $toleranceMin = $rigthtanswer - $tolerance;
-            switch ($toleranceType) {
+            $tolerancemax = $rigthtanswer + $tolerance;
+            $tolerancemin = $rigthtanswer - $tolerance;
+            switch ($tolerancetype) {
                 case 1:
-                    $toleranceMax = $rigthtanswer + ($rigthtanswer * $tolerance);
-                    $toleranceMin = $rigthtanswer - ($rigthtanswer * $tolerance);
+                    $tolerancemax = $rigthtanswer + ($rigthtanswer * $tolerance);
+                    $tolerancemin = $rigthtanswer - ($rigthtanswer * $tolerance);
                     break;
                 case 3:
-                    $toleranceMax = $rigthtanswer + ($rigthtanswer * $tolerance);
-                    $toleranceMin = $rigthtanswer / (1 + $tolerance);
+                    $tolerancemax = $rigthtanswer + ($rigthtanswer * $tolerance);
+                    $tolerancemin = $rigthtanswer / (1 + $tolerance);
                     break;
                 default:
                     break;
             }
-            $rigthtanswerstring = strval($toleranceMin) . '[:]' . strval($toleranceMax);
-            $translatorEvent['interaction_correct_responses'] = [$rigthtanswerstring];
+            $rigthtanswerstring = strval($tolerancemin) . '[:]' . strval($tolerancemax);
+            $translatorevent['interaction_correct_responses'] = [$rigthtanswerstring];
         } else {
-            $translatorEvent['interaction_correct_responses'] = [$questionAttempt->rightanswer];
+            $translatorevent['interaction_correct_responses'] = [$questionattempt->rightanswer];
         }
 
-        return $translatorEvent;
+        return $translatorevent;
     }
 
     /**
      * Add data specifc to shortanswer question types to a translator event.
-     * @param [String => Mixed] $translatorEvent
-     * @param PHPObj $questionAttempt
+     * @param [String => Mixed] $translatorevent
+     * @param PHPObj $questionattempt
      * @param PHPObj $question
      * @return [String => Mixed]
      */
-    public function shortanswerStatement($translatorEvent, $questionAttempt, $question) {
+    public function shortanswer_statement($translatorevent, $questionattempt, $question) {
 
-        $translatorEvent['interaction_type'] = 'fill-in';
-        $translatorEvent['interaction_correct_responses'] = [];
+        $translatorevent['interaction_type'] = 'fill-in';
+        $translatorevent['interaction_correct_responses'] = [];
 
         foreach ($question->answers as $answer) {
             if (intval($answer->fraction) === 1) {
-                $correctResponse;
+                $correctresponse;
                 if ($question->shortanswer->options->usecase == '1') {
-                    $correctResponse = '{case_matters=true}'.$answer->answer;
+                    $correctresponse = '{case_matters=true}'.$answer->answer;
                 } else {
-                    $correctResponse = '{case_matters=false}'.$answer->answer;
+                    $correctresponse = '{case_matters=false}'.$answer->answer;
                 }
-                array_push($translatorEvent['interaction_correct_responses'], $correctResponse);
+                array_push($translatorevent['interaction_correct_responses'], $correctresponse);
             }
         }
 
-        return $translatorEvent;
+        return $translatorevent;
     }
 
     /**
      * Add data specifc to matching question types to a translator event.
-     * @param [String => Mixed] $translatorEvent
-     * @param PHPObj $questionAttempt
+     * @param [String => Mixed] $translatorevent
+     * @param PHPObj $questionattempt
      * @param PHPObj $question
      * @return [String => Mixed]
      */
-    public function matchStatement($translatorEvent, $questionAttempt, $question) {
+    public function match_statement($translatorevent, $questionattempt, $question) {
 
-        $translatorEvent['interaction_type'] = 'matching';
+        $translatorevent['interaction_type'] = 'matching';
 
         $targets = [];
         $sources = [];
-        $correctResponses = [];
-        $responseTargetsPos = [];
-        $responseSourcesPos = [];
+        $correctresponses = [];
+        $responsetargetspos = [];
+        $responsesourcespos = [];
 
         foreach ($question->match->subquestions as $subquestion) {
             $target = strip_tags($subquestion->questiontext);
             $source = strip_tags($subquestion->answertext);
-            $targetId = 'moodle_quiz_question_target_'.$subquestion->id;
-            $sourceId = 'moodle_quiz_question_source_'.$subquestion->id;
-            $targets[$targetId] = $target;
-            $sources[$sourceId] = $source;
+            $targetid = 'moodle_quiz_question_target_'.$subquestion->id;
+            $sourceid = 'moodle_quiz_question_source_'.$subquestion->id;
+            $targets[$targetid] = $target;
+            $sources[$sourceid] = $source;
             array_push(
-                $correctResponses, 
-                $sourceId.'[.]'.$targetId
+                $correctresponses,
+                $sourceid . '[.]' . $targetid
             );
 
             // Get the positions of the target and source within the response string.
-            $responseTargetsPos[strpos($questionAttempt->responsesummary, $target)] = $targetId;
-            $responseSourcesPos[strpos($questionAttempt->responsesummary, $source)] = $sourceId;
+            $responsetargetspos[strpos($questionattempt->responsesummary, $target)] = $targetid;
+            $responsesourcespos[strpos($questionattempt->responsesummary, $source)] = $sourceid;
         }
 
         // Get ordered and indexed lists of target and source.
-        ksort($responseTargetsPos);
-        $responseTargets = array_values($responseTargetsPos);
-        ksort($responseSourcesPos);
-        $responseSources = array_values($responseSourcesPos);
+        ksort($responsetargetspos);
+        $responsetargets = array_values($responsetargetspos);
+        ksort($responsesourcespos);
+        $responsesources = array_values($responsesourcespos);
 
-        $translatorEvent['attempt_response'] = '';
-        if (count($responseTargets) == count($responseSources) && count($responseTargets) > 0) {
+        $translatorevent['attempt_response'] = '';
+        if (count($responsetargets) == count($responsesources) && count($responsetargets) > 0) {
             $responses = [];
-            foreach ($responseTargets as $index => $targetId) {
+            foreach ($responsetargets as $index => $targetid) {
                 array_push(
                     $responses,
-                    $responseSources[$index].'[.]'.$targetId
+                    $responsesources[$index] . '[.]' . $targetid
                 );
             }
-            $translatorEvent['attempt_response'] = implode('[,]', $responses);
+            $translatorevent['attempt_response'] = implode('[,]', $responses);
         }
 
-        $translatorEvent['interaction_target'] = $targets;
-        $translatorEvent['interaction_source'] = $sources;
-        $translatorEvent['interaction_correct_responses'] = [implode('[,]', $correctResponses)];
+        $translatorevent['interaction_target'] = $targets;
+        $translatorevent['interaction_source'] = $sources;
+        $translatorevent['interaction_correct_responses'] = [implode('[,]', $correctresponses)];
 
-        return $translatorEvent;
+        return $translatorevent;
     }
 
     /**
      * Get pertient data from the last recorded step of a learners interactions within a question attempt.
-     * @param PHPObj $questionAttempt
+     * @param PHPObj $questionattempt
      * @return [String => Mixed]
      */
-    private function getLastState($questionAttempt) {
+    private function get_last_state($questionattempt) {
 
         // Default placeholder to -1 so that the first item we check will always be greater than the placeholder.
         $sequencenumber = -1;
@@ -417,7 +433,7 @@ class QuestionSubmitted extends AttemptStarted {
         ];
 
         // Cycle through steps to find the last one (the one with the highest sequence number).
-        foreach ($questionAttempt->steps as $stepId => $step) {
+        foreach ($questionattempt->steps as $stepid => $step) {
             if ($step->sequencenumber > $sequencenumber) {
 
                 // Now this step has the highest sequence number we've seen.
@@ -432,24 +448,24 @@ class QuestionSubmitted extends AttemptStarted {
         return $state;
     }
 
-    private function inResponsesSummary($haystack, $needle, $leftDelim, $rightDelim) {
-        $needlePos = strpos($haystack, $needle);
+    private function in_responses_summary($haystack, $needle, $leftdelim, $rightdelim) {
+        $needlepos = strpos($haystack, $needle);
         if (
-            // Check if choice is contained in the learner's response
-            !($needlePos === false)
+            // Check if choice is contained in the learner's response.
+            !($needlepos === false)
             // Check choice is prefixed with left delimiter or at start of string.
             && (
-                ($needlePos == 0)
-                || (substr($haystack, $needlePos - strlen($leftDelim), strlen($leftDelim)) == $leftDelim)
+                ($needlepos == 0)
+                || (substr($haystack, $needlepos - strlen($leftdelim), strlen($leftdelim)) == $leftdelim)
             )
             // Check choice is follow by right delimiter or at end of string.
             && (
-                ($needlePos == strlen($haystack) - strlen($needle))
-                || (substr($haystack, $needlePos + strlen($needle), strlen($rightDelim)) == $rightDelim)
+                ($needlepos == strlen($haystack) - strlen($needle))
+                || (substr($haystack, $needlepos + strlen($needle), strlen($rightdelim)) == $rightdelim)
             )
         ) {
             return true;
         }
         return false;
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/ScormEvent.php b/lib/translator/src/Events/ScormEvent.php
index f22a9908d83e15cb4f088a4bba20b9e9891c9c12..84497081160a4434936b3e3ed5c5d0a593e78aeb 100644
--- a/lib/translator/src/Events/ScormEvent.php
+++ b/lib/translator/src/Events/ScormEvent.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormEvent extends ModuleViewed {
     /**
@@ -21,4 +39,4 @@ class ScormEvent extends ModuleViewed {
             'scorm_status' => $opts['scorm_scoes_track']['status'],
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/ScormLaunched.php b/lib/translator/src/Events/ScormLaunched.php
index 7a612cd6e7eaed97b0fefc257dda6001ef8d899a..0818aba6c9d1e58cb747a495a448a9c9b3ac21a4 100644
--- a/lib/translator/src/Events/ScormLaunched.php
+++ b/lib/translator/src/Events/ScormLaunched.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormLaunched extends ModuleViewed {
     /**
@@ -12,4 +30,4 @@ class ScormLaunched extends ModuleViewed {
             'recipe' => 'scorm_launched',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/ScormScoreRawSubmitted.php b/lib/translator/src/Events/ScormScoreRawSubmitted.php
index f6eba474069660d2f5cc7b2732e877c4e54f1213..8b601eb1937e72b7d81a51f4bf8f28eaa687dccb 100644
--- a/lib/translator/src/Events/ScormScoreRawSubmitted.php
+++ b/lib/translator/src/Events/ScormScoreRawSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormScoreRawSubmitted extends ScormEvent {
     /**
@@ -8,19 +26,19 @@ class ScormScoreRawSubmitted extends ScormEvent {
      * @override ModuleViewed
      */
     public function read(array $opts) {
-        $scoreMax = $opts['scorm_scoes_track']['scoremax'];
-        $scoreRaw = $opts['cmi_data']['cmivalue'];
-        $scoreMin = $opts['scorm_scoes_track']['scoremin'];
-        $scoreScaled = NULL;
+        $scoremax = $opts['scorm_scoes_track']['scoremax'];
+        $scoreraw = $opts['cmi_data']['cmivalue'];
+        $scoremin = $opts['scorm_scoes_track']['scoremin'];
+        $scorescaled = null;
 
-        $scoreScaled = $scoreRaw >= 0 ? ($scoreRaw / $scoreMax) : ($scoreRaw / $scoreMin);
+        $scorescaled = $scoreraw >= 0 ? ($scoreraw / $scoremax) : ($scoreraw / $scoremin);
 
         return [array_merge(parent::read($opts)[0], [
             'recipe' => 'scorm_scoreraw_submitted',
-            'scorm_score_raw' => $scoreRaw,
-            'scorm_score_min' => $scoreMin,
-            'scorm_score_max' => $scoreMax,
-            'scorm_score_scaled' => $scoreScaled,
+            'scorm_score_raw' => $scoreraw,
+            'scorm_score_min' => $scoremin,
+            'scorm_score_max' => $scoremax,
+            'scorm_score_scaled' => $scorescaled,
         ])];
     }
 }
diff --git a/lib/translator/src/Events/ScormStatusSubmitted.php b/lib/translator/src/Events/ScormStatusSubmitted.php
index ad0181786966c695bee5a1fc0bf1dd533dd04239..0e7cecf627d170a2d2cb0d7c0ab790037cfaefa6 100644
--- a/lib/translator/src/Events/ScormStatusSubmitted.php
+++ b/lib/translator/src/Events/ScormStatusSubmitted.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class ScormStatusSubmitted extends ScormEvent {
     /**
diff --git a/lib/translator/src/Events/UserLoggedin.php b/lib/translator/src/Events/UserLoggedin.php
index eaa8644e77a0ba74613f4d6d927796d53125e2e0..b41b89247d68bcbff91df08f5ed729149bdb2eca 100644
--- a/lib/translator/src/Events/UserLoggedin.php
+++ b/lib/translator/src/Events/UserLoggedin.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UserLoggedin extends Event {
     /**
@@ -12,4 +30,4 @@ class UserLoggedin extends Event {
             'recipe' => 'user_loggedin',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/UserLoggedout.php b/lib/translator/src/Events/UserLoggedout.php
index b414f26903c2316dbe0316eee2efefdf225a2988..fba5282e3991d361c34804411f1c14136d7c5a37 100644
--- a/lib/translator/src/Events/UserLoggedout.php
+++ b/lib/translator/src/Events/UserLoggedout.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UserLoggedout extends Event {
     /**
@@ -12,4 +30,4 @@ class UserLoggedout extends Event {
             'recipe' => 'user_loggedout',
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/Events/UserRegistered.php b/lib/translator/src/Events/UserRegistered.php
index 9a97edb22e238e763a604d9c64b51bca82a3855d..3e357977ee3677044c9858fbfb84f6734ab7a7b8 100644
--- a/lib/translator/src/Events/UserRegistered.php
+++ b/lib/translator/src/Events/UserRegistered.php
@@ -1,4 +1,22 @@
-<?php namespace MXTranslator\Events;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Events;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UserRegistered extends Event {
     /**
@@ -15,4 +33,4 @@ class UserRegistered extends Event {
             'user_name' => $opts['relateduser']->fullname,
         ])];
     }
-}
\ No newline at end of file
+}
diff --git a/lib/translator/src/UnnecessaryEvent.php b/lib/translator/src/UnnecessaryEvent.php
index 200706c7ce2b9dd7309ead219484af1a73349c31..a8ac0fa40c16036987b95f675cb12ece1e03ad40 100644
--- a/lib/translator/src/UnnecessaryEvent.php
+++ b/lib/translator/src/UnnecessaryEvent.php
@@ -1,5 +1,23 @@
-<?php namespace MXTranslator;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator;
+
+defined('MOODLE_INTERNAL') || die();
 
 class UnnecessaryEvent extends Exception {
-    
-}
\ No newline at end of file
+
+}
diff --git a/lib/translator/tests/AssignmentGradedTest.php b/lib/translator/tests/AssignmentGradedTest.php
deleted file mode 100644
index bee9c218f31642c54bbfdb9b135f2751afed3a36..0000000000000000000000000000000000000000
--- a/lib/translator/tests/AssignmentGradedTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\AssignmentGraded as Event;
-
-class AssignmentGradedTest extends ModuleViewedTest {
-    protected static $recipeName = 'assignment_graded';
-
-    /**
- * Sets up the tests.
- * @override TestCase
- */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'grade' => (object) [
-                'grade' => 1,
-            ],
-            'graded_user' => $this->constructUser(),
-            'grade_items' => $this->constructGradeitems(),
-            'grade_comment' => "test comment"
-        ]);
-    }
-
-    private function constructGradeitems() {
-        return (object) [
-            'grademin' => 0,
-            'grademax' => 5,
-            'gradepass' => 5
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertEquals($input['grade']->grade, $output['grade_score_raw']);
-        $this->assertEquals($input['grade_comment'], $output['grade_comment']);
-        $this->assertEquals(true, $output['grade_completed']);
-        $this->assertGradeItems($input, $output);
-        $this->assertUser($input['graded_user'], $output, 'graded_user');
-    }
-
-    protected function assertGradeItems($input, $output) {
-        $this->assertEquals((float) $input['grade_items']->grademin, $output['grade_score_min']);
-        $this->assertEquals((float) $input['grade_items']->grademax, $output['grade_score_max']);
-        $this->assertEquals(($input['grade']->grade >= $input['grade_items']->gradepass), $output['grade_success']);
-        if ($output['grade_score_scaled']  >= 0) {
-            $this->assertEquals($output['grade_score_scaled'], $output['grade_score_raw'] / $output['grade_score_max']);
-        }
-        else
-        {
-            $this->assertEquals($output['grade_score_scaled'], $output['grade_score_raw'] / $output['grade_score_min']);
-        }
-    }
-}
diff --git a/lib/translator/tests/AssignmentSubmittedTest.php b/lib/translator/tests/AssignmentSubmittedTest.php
deleted file mode 100644
index c8c886692da8d751d8477e0ae95b986a841e9199..0000000000000000000000000000000000000000
--- a/lib/translator/tests/AssignmentSubmittedTest.php
+++ /dev/null
@@ -1,20 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\AssignmentSubmitted as Event;
-
-class AssignmentSubmittedTest extends ModuleViewedTest {
-    protected static $recipeName = 'assignment_submitted';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'submission' => (object) [],
-        ]);
-    }
-}
diff --git a/lib/translator/tests/AttemptAbandonedTest.php b/lib/translator/tests/AttemptAbandonedTest.php
deleted file mode 100644
index 37d56c59a508669603fd032cb1bb94fb871c8e52..0000000000000000000000000000000000000000
--- a/lib/translator/tests/AttemptAbandonedTest.php
+++ /dev/null
@@ -1,18 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\AttemptAbandoned as Event;
-
-class AttemptAbandonedTest extends AttemptReviewedTest {
-    protected static $recipeName = 'attempt_abandoned';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertAttempt($input, $output) {
-        parent::assertAttempt($input, $output);
-    }
-}
\ No newline at end of file
diff --git a/lib/translator/tests/AttemptReviewedTest.php b/lib/translator/tests/AttemptReviewedTest.php
deleted file mode 100644
index a9ed8c924e92e49fb15e0f70b64808cab0ad6f5e..0000000000000000000000000000000000000000
--- a/lib/translator/tests/AttemptReviewedTest.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\AttemptReviewed as Event;
-
-class AttemptReviewedTest extends AttemptStartedTest {
-    protected static $recipeName = 'attempt_completed';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'grade_items' => $this->constructGradeitems()
-        ]);
-    }
-
-    private function constructGradeitems() {
-        return (object) [
-            'grademin' => 0,
-            'grademax' => 5,
-            'gradepass' => 5
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertAttempt($input['attempt'], $output);
-        $this->assertGradeItems($input, $output);
-    }
-
-    protected function assertAttempt($input, $output) {
-        parent::assertAttempt($input, $output);
-        $this->assertEquals((float) $input->sumgrades, $output['attempt_score_raw']);
-        $this->assertEquals($input->state === 'finished', $output['attempt_completed']);
-    }
-
-    protected function assertGradeItems($input, $output) {
-        $this->assertEquals((float) $input['grade_items']->grademin, $output['attempt_score_min']);
-        $this->assertEquals((float) $input['grade_items']->grademax, $output['attempt_score_max']);
-        $this->assertEquals(($input['attempt']->sumgrades >= $input['grade_items']->gradepass), $output['attempt_success']);
-        if ($output['attempt_score_scaled']  >= 0) {
-            $this->assertEquals($output['attempt_score_scaled'], $output['attempt_score_raw'] / $output['attempt_score_max']);
-        } else {
-            $this->assertEquals($output['attempt_score_scaled'], $output['attempt_score_raw'] / $output['attempt_score_min']);
-        }
-    }
-}
diff --git a/lib/translator/tests/AttemptStartedTest.php b/lib/translator/tests/AttemptStartedTest.php
deleted file mode 100644
index 7ad689f8439faaf65c11409c8fcc94ac095cf5a1..0000000000000000000000000000000000000000
--- a/lib/translator/tests/AttemptStartedTest.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\AttemptStarted as Event;
-
-class AttemptStartedTest extends ModuleViewedTest {
-    protected static $recipeName = 'attempt_started';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'attempt' => $this->constructAttempt(),
-        ]);
-    }
-
-    private function constructAttempt() {
-        return (object) [
-            'url' => 'http://www.example.com/attempt_url',
-            'name' => 'Test attempt_name',
-            'type' => 'moodle_attempt',
-            'timestart' => 1433946701,
-            'timefinish' => 1433946701,
-            'sumgrades' => 1,
-            'state' => 'finished',
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertAttempt($input['attempt'], $output);
-    }
-
-    protected function assertAttempt($input, $output) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_attempt';
-        $this->assertEquals($input->url, $output['attempt_url']);
-        $this->assertEquals($input->name, $output['attempt_name']);
-        $this->assertEquals(static::$xapiType.$input->type, $output['attempt_type']);
-        $this->assertEquals($input, $output['attempt_ext']);
-        $this->assertEquals($extKey, $output['attempt_ext_key']);
-    }
-}
diff --git a/lib/translator/tests/CourseCompletedTest.php b/lib/translator/tests/CourseCompletedTest.php
deleted file mode 100644
index ecf667a8f1fbb064351ea86216439e3e63ef3e4b..0000000000000000000000000000000000000000
--- a/lib/translator/tests/CourseCompletedTest.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-namespace MXTranslator\Tests;
-use \MXTranslator\Events\CourseCompleted as Event;
-
-/**
- * Class CourseCompletedTest
- * @package MXTranslator\Tests
- */
-class CourseCompletedTest extends EventTest {
-    /**
-     * @var string
-     */
-    protected static $recipeName = 'course_completed';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    /**
-     * Constructs the Input with course completed
-     * @return array
-     */
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'event' => $this->constructEvent('\core\event\course_completed'),
-        ]);
-    }
-
-    /**
-     * Constructs the event with the given event name
-     * @param $eventName
-     * @return array
-     */
-    private function constructEvent($eventName) {
-        return [
-            'eventname' => $eventName,
-            'timecreated' => 1433946701,
-        ];
-    }
-
-    /**
-     * Assets that the input is the same as the output.
-     * @param $input
-     * @param $output
-     */
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertCourse($input['course'], $output, 'course');
-    }
-}
\ No newline at end of file
diff --git a/lib/translator/tests/CourseViewedTest.php b/lib/translator/tests/CourseViewedTest.php
deleted file mode 100644
index 47be03bdc9bcc69278e7bf0c29dee37e799269cb..0000000000000000000000000000000000000000
--- a/lib/translator/tests/CourseViewedTest.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\CourseViewed as Event;
-
-class CourseViewedTest extends UserEventTest {
-    protected static $recipeName = 'course_viewed';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertCourse($input['course'], $output, 'course');
-    }
-}
diff --git a/lib/translator/tests/DiscussionViewedTest.php b/lib/translator/tests/DiscussionViewedTest.php
deleted file mode 100644
index 661c89200a2477857a51371a7143efc641161d8f..0000000000000000000000000000000000000000
--- a/lib/translator/tests/DiscussionViewedTest.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\DiscussionViewed as Event;
-
-class DiscussionViewedTest extends ModuleViewedTest {
-    protected static $recipeName = 'discussion_viewed';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'discussion' => $this->constructDiscussion(),
-        ]);
-    }
-    
-    private function constructDiscussion() {
-        return (object) [
-            'url' => 'http://www.example.com/discussion_url',
-            'name' => 'Test discussion_name',
-            'type' => 'moodle_discussion',
-            'ext' => 'discussion_ext',
-            'ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_discussion',
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertDiscussion($input['discussion'], $output, 'discussion');
-    }
-
-    private function assertDiscussion($input, $output, $type) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_discussion';
-        $this->assertEquals($input->url, $output[$type.'_url']);
-        $this->assertEquals($input->name, $output[$type.'_name']);
-        $this->assertEquals('A Moodle discussion.', $output[$type.'_description']);
-        $this->assertEquals(static::$xapiType.$input->type, $output[$type.'_type']);
-        $this->assertEquals($input, $output[$type.'_ext']);
-        $this->assertEquals($extKey, $output[$type.'_ext_key']);
-    }
-}
diff --git a/lib/translator/tests/EnrolmentCreatedTest.php b/lib/translator/tests/EnrolmentCreatedTest.php
deleted file mode 100644
index c17ec12a3d57eb843dcf50d8ef010787f89447fb..0000000000000000000000000000000000000000
--- a/lib/translator/tests/EnrolmentCreatedTest.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\EnrolmentCreated as Event;
-
-class EnrolmentCreatedTest extends EventTest {
-    protected static $recipeName = 'enrolment_created';
-    
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertUser($input['user'], $output, 'instructor');
-        $this->assertUser($input['relateduser'], $output, 'user');
-        $this->assertCourse($input['course'], $output, 'course');
-    }
-}
diff --git a/lib/translator/tests/EventTest.php b/lib/translator/tests/EventTest.php
deleted file mode 100644
index 03734e46c99ccbcc98a1caabd9244c0c621007a7..0000000000000000000000000000000000000000
--- a/lib/translator/tests/EventTest.php
+++ /dev/null
@@ -1,171 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \PHPUnit_Framework_TestCase as PhpUnitTestCase;
-use \MXTranslator\Events\Event as Event;
-
-abstract class EventTest extends PhpUnitTestCase {
-    protected static $xapiType = 'http://lrs.learninglocker.net/define/type/moodle/';
-    protected static $recipeName;
-
-    /**
-     * Sets up the tests.
-     * @override PhpUnitTestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    /**
-     * Tests the read method of the Event.
-     */
-    public function testRead() {
-        $input = $this->constructInput();
-        $outputs = $this->event->read($input);
-        $this->assertOutputs($input, $outputs);
-        foreach ($outputs as $output) {
-            $input = $this->constructInput();
-            $this->assertOutput($input, $output);
-            $this->createExampleFile($output);
-        }
-    }
-
-    protected function constructInput() {
-        return [
-            'user' => $this->constructUser(),
-            'relateduser' => $this->constructUser(),
-            'course' => $this->constructCourse(),
-            'app' => $this->constructApp(),
-            'source' => $this->constructSource(),
-            'event' => $this->constructEvent('\core\event\course_viewed'),
-            'info' => $this->constructInfo(),
-            'sendmbox' => true
-        ];
-    }
-
-    protected function constructInfo() {
-        return (object) [
-            'https://moodle.org/' => '1.0.0'
-        ];
-    }
-
-    protected function constructUser() {
-        return (object) [
-            'id' => 1,
-            'url' => 'http://www.example.com/user_url',
-            'fullname' => 'Test user_name',
-            'email' => 'test@test.com',
-        ];
-    }
-
-    private function constructEvent($eventName) {
-        return [
-            'eventname' => $eventName,
-            'timecreated' => 1433946701,
-        ];
-    }
-
-    protected function constructCourse() {
-        return (object) [
-            'url' => 'http://www.example.com/course_url',
-            'fullname' => 'Test course_fullname',
-            'summary' => '<p>Test course_summary</p>',
-            'lang' => 'en',
-            'type' => 'moodle_course',
-        ];
-    }
-
-    protected function constructApp() {
-        return (object) [
-            'url' => 'http://www.example.com',
-            'fullname' => 'Test site_fullname',
-            'summary' => '<p>Test site_summary</p>',
-            'lang' => 'en',
-            'type' => 'moodle_site',
-        ];
-    }
-
-    protected function constructSource() {
-        return (object) [
-            'url' => 'http://moodle.org',
-            'fullname' => 'Moodle',
-            'summary' => 'Moodle is a open source learning platform designed to provide educators,'
-                .' administrators and learners with a single robust, secure and integrated system'
-                .' to create personalised learning environments.',
-            'lang' => 'en',
-            'type' => 'moodle_source',
-        ];
-    }
-
-    protected function assertOutputs($input, $output) {
-        //output is an associative array
-        $this->assertEquals(0, count(array_filter(array_keys($output), 'is_string')));
-        //length of output is 1. Overwrite this function if a different value is needed.
-        $this->assertEquals(1 , count($output));
-    }
-
-    protected function assertOutput($input, $output) {
-        $this->assertApp($input['app'], $output, 'app');
-        $this->assertEvent($input['event'], $output);
-        $this->assertEquals(static::$recipeName, $output['recipe']);
-        $this->assertInfo($input['info'], $output['context_info']);
-    }
-
-    protected function assertUser($input, $output, $type) {
-        $this->assertEquals($input->id, $output[$type.'_id']);
-        $this->assertEquals($input->url, $output[$type.'_url']);
-        $this->assertEquals($input->fullname, $output[$type.'_name']);
-    }
-
-    protected function assertCourse($input, $output, $type) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_course';
-        $this->assertEquals($input->lang, $output['context_lang']);
-        $this->assertEquals($input->url, $output[$type.'_url']);
-        $this->assertEquals($input->fullname, $output[$type.'_name']);
-        $this->assertEquals(strip_tags($input->summary), $output[$type.'_description']);
-        $this->assertEquals(static::$xapiType.$input->type, $output[$type.'_type']);
-        $this->assertEquals($input, $output[$type.'_ext']);
-        $this->assertEquals($extKey, $output[$type.'_ext_key']);
-    }
-
-    protected function assertApp($input, $output, $type) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_course';
-        $appType = 'http://id.tincanapi.com/activitytype/site';
-        $this->assertEquals($input->lang, $output['context_lang']);
-        $this->assertEquals($input->url, $output[$type.'_url']);
-        $this->assertEquals($input->fullname, $output[$type.'_name']);
-        $this->assertEquals(strip_tags($input->summary), $output[$type.'_description']);
-        $this->assertEquals($appType, $output[$type.'_type']);
-        $this->assertEquals($input, $output[$type.'_ext']);
-        $this->assertEquals($extKey, $output[$type.'_ext_key']);
-    }
-
-    protected function assertSource($input, $output, $type) {
-        $appType = 'http://id.tincanapi.com/activitytype/source';
-        $this->assertEquals($input->lang, $output['context_lang']);
-        $this->assertEquals($input->url, $output[$type.'_url']);
-        $this->assertEquals($input->fullname, $output[$type.'_name']);
-        $this->assertEquals(strip_tags($input->summary), $output[$type.'_description']);
-        $this->assertEquals($appType, $output[$type.'_type']);
-    }
-
-    private function assertEvent($input, $output) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_logstore_standard_log';
-        $this->assertEquals('Moodle', $output['context_platform']);
-        $this->assertEquals($input, $output['context_ext']);
-        $this->assertEquals($extKey, $output['context_ext_key']);
-        $this->assertEquals(date('c', $input['timecreated']), $output['time']);
-    }
-
-    private function assertInfo($input, $output) {
-        $this->assertEquals(
-            $input->{'https://moodle.org/'},
-            $output->{'https://moodle.org/'}
-        );
-    }
-
-    protected function createExampleFile($output) {
-        $classArray = explode('\\', get_class($this));
-        $eventName = str_replace('Test', '', array_pop($classArray));
-        $exampleFile = __DIR__.'/../docs/examples/'.$eventName.'.json';
-        file_put_contents($exampleFile, json_encode($output, JSON_PRETTY_PRINT));
-    }
-}
diff --git a/lib/translator/tests/FacetofaceAttendedTest.php b/lib/translator/tests/FacetofaceAttendedTest.php
deleted file mode 100644
index c18049b79e3e07d9d92bd78391cb913f1847cd85..0000000000000000000000000000000000000000
--- a/lib/translator/tests/FacetofaceAttendedTest.php
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\FacetofaceAttend as Event;
-
-class FacetofaceAttendTest extends FacetofaceEnrolTest {
-    protected static $recipeName = 'training_session_attend';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'signups' => [
-                "1" => $this->constructSignup("1"),
-                "2" => $this->constructSignup("2")
-            ]
-        ]);
-    }
-
-    private function constructSignup($faceToFaceId) {
-        $signups =  (object) [  
-            "id" => $faceToFaceId,
-            "sessionid" => "1",
-            "userid" => "1",
-            "mailedreminder" => "0",
-            "discountcode" => null,
-            "notificationtype" => "3",
-            "statuses" => [
-                "1" => $this->constructStatus("1"),
-                "2" => $this->constructStatus("2"),
-                "3" => $this->constructFinalStatus("3"),
-            ],
-            "attendee" => $this->constructUser()
-        ];
-
-        return $signups;
-    }
-
-    private function constructStatus($faceToFaceId) {
-        return (object) [
-            "id" => $faceToFaceId,
-            "signupid" => "4",
-            "statuscode" => "90",
-            "superceded" => "1",
-            "grade" => "50.00000",
-            "note" => "",
-            "advice" => null,
-            "createdby" => "1",
-            "timecreated" => "143394660".$faceToFaceId // Earlier than the final status
-        ];
-    }
-
-    private function constructFinalStatus($faceToFaceId) {
-        return (object) [
-            "id" => $faceToFaceId,
-            "signupid" => "4",
-            "statuscode" => "100",
-            "superceded" => "0",
-            "grade" => "100.00000",
-            "note" => "",
-            "advice" => null,
-            "createdby" => "1",
-            "timecreated" => "1433946701" // Must be the same as timecreated in EventTest.php
-        ];
-    }
-
-    protected function assertOutputs($input, $output) {
-        //output is an associative array
-        $this->assertEquals(0, count(array_filter(array_keys($output), 'is_string')));
-        //length of output is 3.
-        $this->assertEquals(2 , count($output));
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertEquals($input['signups']['1']->attendee->id, $output['attendee_id']);
-        $this->assertEquals($input['signups']['1']->attendee->url, $output['attendee_url']);
-        $this->assertEquals($input['signups']['1']->attendee->fullname, $output['attendee_name']);
-        
-        $sessionDuration = 0;
-        foreach ($input['session']->dates as $index => $date) {
-            $sessionDuration -= $date->timestart;
-            $sessionDuration += $date->timefinish;
-        }
-
-        $this->assertEquals("PT".$sessionDuration."S", $output['attempt_duration']);
-        $this->assertEquals(true, $output['attempt_completion']);
-    }
-}
diff --git a/lib/translator/tests/FacetofaceEnrolTest.php b/lib/translator/tests/FacetofaceEnrolTest.php
deleted file mode 100644
index c8b2dc0713a22cc8ea896ae50930d210413aef50..0000000000000000000000000000000000000000
--- a/lib/translator/tests/FacetofaceEnrolTest.php
+++ /dev/null
@@ -1,55 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\FacetofaceEnrol as Event;
-
-class FacetofaceEnrolTest extends ModuleViewedTest {
-    protected static $recipeName = 'training_session_enrol';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'session' => $this->constructSession()
-        ]);
-    }
-
-    private function constructSession() {
-        return (object) [
-            "id" => "1",
-            "facetoface" => "1",
-            "capacity" => "10",
-            "allowoverbook" => "0",
-            "details" => "",
-            "datetimeknown" => "0",
-            "duration" => "0",
-            "normalcost" => "0",
-            "discountcost" => "0",
-            "timecreated" => "1464179438",
-            "timemodified" => "0",
-            "type" => "facetoface_sessions",
-            "dates" => [
-                "1" => (object) [
-                    "id" => "1",
-                    "sessionid" => "1",
-                    "timestart" => "1464176400",
-                    "timefinish" => "1464179400"
-                ]
-            ],
-            'url' => 'http://www.example.com/session_url'
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertEquals($input['session']->url, $output['session_url']);
-        $sessionName = 'Session '.$input['session']->id.' of '.$input['module']->name;
-        $this->assertEquals($sessionName, $output['session_name']);
-        $this->assertEquals($sessionName, $output['session_description']);
-        $this->assertEquals('http://activitystrea.ms/schema/1.0/event', $output['session_type']);
-    }
-}
diff --git a/lib/translator/tests/FacetofaceUnernrolTest.php b/lib/translator/tests/FacetofaceUnernrolTest.php
deleted file mode 100644
index cf3c73f4fc3b2e620ac3497cb2cbd301b277af86..0000000000000000000000000000000000000000
--- a/lib/translator/tests/FacetofaceUnernrolTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\FacetofaceUnenrol as Event;
-
-class FacetofaceUnenrolTest extends FacetofaceEnrolTest {
-    protected static $recipeName = 'training_session_unenrol';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-}
diff --git a/lib/translator/tests/FeedbackQuestionSubmittedTest.php b/lib/translator/tests/FeedbackQuestionSubmittedTest.php
deleted file mode 100644
index cd9f438ed19ce98e4d7e5e5dae2b92609384f071..0000000000000000000000000000000000000000
--- a/lib/translator/tests/FeedbackQuestionSubmittedTest.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\FeedbackQuestionSubmitted as Event;
-
-class FeedbackQuestionSubmittedTest extends FeedbackSubmittedTest {
-    protected static $recipeName = 'attempt_question_completed';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-
-        $questions = $input['questions'];
-        $questionsArr = (array) $questions;
-
-        $responses = $input['attempt']->responses;
-        $responsesArr = (array) $responses;
-
-        $this->assertEquals($questionsArr['1']->name, $output['question_name']);
-        $this->assertEquals($questionsArr['1']->name, $output['question_description']);
-        $this->assertEquals($questionsArr['1']->url, $output['question_url']);
-        $this->assertEquals($responsesArr['2']->value, $output['attempt_response']);
-        $this->assertEquals(null, $output['interaction_correct_responses']);
-        $this->assertEquals('likert', $output['interaction_type']);
-        $this->assertEquals((object) [
-            "0" => "Not selected",
-            '1' => "incorrect",
-            '2' => "correct"
-        ], $output['interaction_scale']);
-    }
-
-    protected function assertAttempt($input, $output) {
-        // Overides parent and does nothing
-    }
-
-}
\ No newline at end of file
diff --git a/lib/translator/tests/ModuleViewedTest.php b/lib/translator/tests/ModuleViewedTest.php
deleted file mode 100644
index 1f1ec61211413980bcf718ce2751a0e875703857..0000000000000000000000000000000000000000
--- a/lib/translator/tests/ModuleViewedTest.php
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\ModuleViewed as Event;
-
-class ModuleViewedTest extends CourseViewedTest {
-    protected static $recipeName = 'module_viewed';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'module' => $this->constructModule(),
-        ]);
-    }
-
-    private function constructModule() {
-        return (object) [
-            'url' => 'http://www.example.com/module_url',
-            'name' => 'Test module_name',
-            'intro' => 'Test module_intro',
-            'type' => 'moodle_module',
-        ];
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule($input['module'], $output, 'module');
-    }
-
-    private function assertModule($input, $output, $type) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_module';
-        $this->assertEquals($input->url, $output[$type.'_url']);
-        $this->assertEquals($input->name, $output[$type.'_name']);
-        $this->assertEquals($input->intro, $output[$type.'_description']);
-        $this->assertEquals(static::$xapiType.$input->type, $output[$type.'_type']);
-        $this->assertEquals($input, $output[$type.'_ext']);
-        $this->assertEquals($extKey, $output[$type.'_ext_key']);
-    }
-}
diff --git a/lib/translator/tests/ScormEventTest.php b/lib/translator/tests/ScormEventTest.php
deleted file mode 100644
index 32abe2ba2a8876749e24b83fe122ca6d27e46b8a..0000000000000000000000000000000000000000
--- a/lib/translator/tests/ScormEventTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\ScormEvent as Event;
-
-class ScormEventTest extends ModuleViewedTest {
-    protected static $recipeName = 'scorm_event';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'scorm_scoes_track' => [
-                'status' => 'completed',
-            ],
-            'cmi_data' => [
-                'cmivalue' => 'completed',
-                'cmielement' => 'cmi.core.lesson_status',
-                'attemptid' => 2,
-            ],
-            'scorm_scoes' => $this->constructScormScoes(),
-        ]);
-    }
-
-    protected function constructScormScoes() {
-        return (object)[
-            'id' => 1,
-            'scorm' => 1,
-            'scormtype' => 'sco',
-            'title' => 'Sco title'
-        ];
-    }
-}
-
diff --git a/lib/translator/tests/ScormLaunchedTest.php b/lib/translator/tests/ScormLaunchedTest.php
deleted file mode 100644
index 9c5610e55f9c09471d48494656d1bde23e1d54b5..0000000000000000000000000000000000000000
--- a/lib/translator/tests/ScormLaunchedTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\ScormLaunched as Event;
-
-class ScormLaunchedTest extends ModuleViewedTest {
-    protected static $recipeName = 'scorm_launched';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-}
diff --git a/lib/translator/tests/ScormStatusSubmittedTest.php b/lib/translator/tests/ScormStatusSubmittedTest.php
deleted file mode 100644
index 4b800f0d815eb4a1cec075b8f317b45190b6f4d4..0000000000000000000000000000000000000000
--- a/lib/translator/tests/ScormStatusSubmittedTest.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\ScormStatusSubmitted as Event;
-
-class ScormStatusSubmittedTest extends ScormEventTest {
-    protected static $recipeName = 'scorm_status_submitted';
-
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'scorm_scoes_track' => [
-                'status' => 'completed',
-            ],
-            'cmi_data' => [
-                'cmivalue' => 'completed',
-                'cmielement' => 'cmi.core.lesson_status',
-                'attemptid' => 2,
-            ],
-            'scorm_scoes' => $this->constructScormScoes()
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertEquals($input['module']->name, $output['scorm_name']);
-        $this->assertEquals($input['module']->url, $output['scorm_url']);
-        $this->assertEquals($input['scorm_scoes_track']['status'], $output['scorm_status']);
-        $this->assertEquals($input['cmi_data']['cmivalue'], $output['scorm_status']);
-        $this->assertEquals($input['cmi_data']['attemptid'], $output['scorm_attempt']);
-    }
-}
diff --git a/lib/translator/tests/UserEventTest.php b/lib/translator/tests/UserEventTest.php
deleted file mode 100644
index aac63c0577f709d631fd768556d328da1c6daf0f..0000000000000000000000000000000000000000
--- a/lib/translator/tests/UserEventTest.php
+++ /dev/null
@@ -1,16 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\Event as Event;
-
-abstract class UserEventTest extends EventTest {
-
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'user' => $this->constructUser(),
-        ]);
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertUser($input['user'], $output, 'user');
-    }
-}
diff --git a/lib/translator/tests/UserLoggedinTest.php b/lib/translator/tests/UserLoggedinTest.php
deleted file mode 100644
index c69d04e8dbb5ac3cd5f067948e7cbc6855645a99..0000000000000000000000000000000000000000
--- a/lib/translator/tests/UserLoggedinTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\UserLoggedin as Event;
-
-class UserLoggedinTest extends UserEventTest {
-    protected static $recipeName = 'user_loggedin';
-    
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-}
diff --git a/lib/translator/tests/UserLoggedoutTest.php b/lib/translator/tests/UserLoggedoutTest.php
deleted file mode 100644
index 9a1aca106eb8d6f4d2597043dd3a45f7826757b8..0000000000000000000000000000000000000000
--- a/lib/translator/tests/UserLoggedoutTest.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\UserLoggedout as Event;
-
-class UserLoggedoutTest extends UserEventTest {
-    protected static $recipeName = 'user_loggedout';
-    
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-}
diff --git a/lib/translator/tests/UserRegisteredTest.php b/lib/translator/tests/UserRegisteredTest.php
deleted file mode 100644
index 50121f4bfe2f9da3920385b528826a4a6dedc4fc..0000000000000000000000000000000000000000
--- a/lib/translator/tests/UserRegisteredTest.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php namespace MXTranslator\Tests;
-use \MXTranslator\Events\UserRegistered as Event;
-
-class UserRegisteredTest extends EventTest {
-    protected static $recipeName = 'user_registered';
-    
-    /**
-     * Sets up the tests.
-     * @override TestCase
-     */
-    public function setup() {
-        $this->event = new Event();
-    }
-
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertUser($input['relateduser'], $output, 'user');
-    }
-}
diff --git a/phpunit.xml b/phpunit.xml
deleted file mode 100644
index 67ac6813f12c8b06b0894cdfc24b91cb9d5c0953..0000000000000000000000000000000000000000
--- a/phpunit.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<phpunit backupGlobals="false"
-         backupStaticAttributes="false"
-         bootstrap="vendor/autoload.php"
-         colors="true"
-         convertErrorsToExceptions="true"
-         convertNoticesToExceptions="true"
-         convertWarningsToExceptions="true"
-         processIsolation="false"
-         stopOnFailure="false"
-         syntaxCheck="false"
->
-    <testsuites>
-        <testsuite name="Application Test Suite">
-            <directory>./tests/</directory>
-            <directory>./lib/expander/tests/</directory>
-            <directory>./lib/translator/tests/</directory>
-            <directory>./lib/emitter/tests/</directory>
-        </testsuite>
-    </testsuites>
-</phpunit>
diff --git a/settings.php b/settings.php
index 12c0251a8c847101375070b3ede773c7d91abb78..703f884232926147f76cb0a27f4735cd2ed9bd3c 100644
--- a/settings.php
+++ b/settings.php
@@ -40,7 +40,7 @@ if ($hassiteconfig) {
     $settings->add(new admin_setting_configtext('logstore_xapi/password',
         get_string('password', 'logstore_xapi'), '', 'password', PARAM_TEXT));
 
-    // Switch background batch mode on
+    // Switch background batch mode on.
     $settings->add(new admin_setting_configcheckbox('logstore_xapi/backgroundmode',
         get_string('backgroundmode', 'logstore_xapi'),
         get_string('backgroundmode_desc', 'logstore_xapi'), 0));
@@ -61,11 +61,13 @@ if ($hassiteconfig) {
     $settings->add(new admin_setting_configcheckbox('logstore_xapi/logguests',
         get_string('logguests', 'logstore_xapi'), '', '0'));
 
-    $menu_routes = array();
+    $menuroutes = array();
     $routes = translator_controller::$routes;
-    foreach (array_keys($routes) as $route_key) $menu_routes[$route_key] = $route_key;
+    foreach (array_keys($routes) as $routekey) {
+        $menuroutes[$routekey] = $routekey;
+    }
 
     $settings->add(new admin_setting_configmulticheckbox('logstore_xapi/routes',
-        get_string('routes', 'logstore_xapi'), '', $menu_routes, $menu_routes));
+        get_string('routes', 'logstore_xapi'), '', $menuroutes, $menuroutes));
 
 }
diff --git a/tests/AssignmentGradedTest.php b/tests/AssignmentGradedTest.php
deleted file mode 100644
index d5e6db8a5db1431270d32e9d74e29dac99827325..0000000000000000000000000000000000000000
--- a/tests/AssignmentGradedTest.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php namespace Tests;
-
-class AssignmentGradedTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'assign_grades',
-            'objectid' => '1',
-            'eventname' => '\mod_assign\event\submission_graded',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/AssignmentSubmittedTest.php b/tests/AssignmentSubmittedTest.php
deleted file mode 100644
index d154eb7f916f75b9699323a77a44f63f4a4f9f56..0000000000000000000000000000000000000000
--- a/tests/AssignmentSubmittedTest.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php namespace Tests;
-
-class AssignmentSubmittedTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'assign_submission',
-            'objectid' => 1,
-            'eventname' => '\mod_assign\event\assessable_submitted',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/AttemptAbandonedTest.php b/tests/AttemptAbandonedTest.php
deleted file mode 100644
index c6d7f4dbeba764573f17cb2fa1070b2e08022de7..0000000000000000000000000000000000000000
--- a/tests/AttemptAbandonedTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class AttemptAbandonedTest extends AttemptTestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\mod_quiz\event\attempt_abandoned',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/AttemptReviewedTest.php b/tests/AttemptReviewedTest.php
deleted file mode 100644
index 930236a02a5b4bacfe12d55c3b9e904bbfa0c612..0000000000000000000000000000000000000000
--- a/tests/AttemptReviewedTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class AttemptReviewedTest extends AttemptTestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\mod_quiz\event\attempt_reviewed',
-        ]);
-    }
-}
diff --git a/tests/AttemptStartedTest.php b/tests/AttemptStartedTest.php
deleted file mode 100644
index c443da7b357f8920ec508c03fdcbba3467bc9f6e..0000000000000000000000000000000000000000
--- a/tests/AttemptStartedTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class AttemptStartedTest extends AttemptTestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\mod_quiz\event\attempt_preview_started',
-        ]);
-    }
-}
diff --git a/tests/AttemptTestCase.php b/tests/AttemptTestCase.php
deleted file mode 100644
index bebc1a28d498ab41f7b6cb66e9141d2a1af6a610..0000000000000000000000000000000000000000
--- a/tests/AttemptTestCase.php
+++ /dev/null
@@ -1,10 +0,0 @@
-<?php namespace Tests;
-
-abstract class AttemptTestCase extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'quiz_attempts',
-            'objectid' => 1,
-        ]);
-    }
-}
diff --git a/tests/CourseCompletedTest.php b/tests/CourseCompletedTest.php
deleted file mode 100644
index 1658bdfa1fd50431ae33c374cb4b1ab873189111..0000000000000000000000000000000000000000
--- a/tests/CourseCompletedTest.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-/**
- * Created by PhpStorm.
- * User: lee.kirkland
- * Date: 5/26/2016
- * Time: 9:29 AM
- */
-
-namespace Tests;
-
-
-class CourseCompletedTest extends TestCase
-{
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'course_completed',
-            'objectid' => 1,
-            'eventname' => '\core\event\course_completed',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/CourseViewedTest.php b/tests/CourseViewedTest.php
deleted file mode 100644
index b2e5a794e048d628a1b438a19f698bb30284d008..0000000000000000000000000000000000000000
--- a/tests/CourseViewedTest.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?php namespace Tests;
-
-class CourseViewedTest extends TestCase {}
\ No newline at end of file
diff --git a/tests/DiscussionViewedTest.php b/tests/DiscussionViewedTest.php
deleted file mode 100644
index 112238c842e03bf4a7937b805b2bc862db171514..0000000000000000000000000000000000000000
--- a/tests/DiscussionViewedTest.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php namespace Tests;
-
-class DiscussionViewedTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'forum_discussions',
-            'objectid' => 1,
-            'eventname' => '\mod_forum\event\discussion_viewed',
-        ]);
-    }
-}
diff --git a/tests/EnrolmentCreatedTest.php b/tests/EnrolmentCreatedTest.php
deleted file mode 100644
index 20fad15a93244d237a4cccfdb01683abdc4c963b..0000000000000000000000000000000000000000
--- a/tests/EnrolmentCreatedTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class EnrolmentCreatedTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\core\event\user_enrolment_created',
-        ]);
-    }
-}
diff --git a/tests/FeedbackSubmittedTest.php b/tests/FeedbackSubmittedTest.php
deleted file mode 100644
index 65a75447256319e5fe2bea52d4321f4a48997690..0000000000000000000000000000000000000000
--- a/tests/FeedbackSubmittedTest.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php namespace Tests;
-
-class FeedbackSubmitted extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\mod_feedback\event\response_submitted',
-            'objecttable' => 'feedback_completed',
-            'objectid' => 1,
-        ]);
-    }
-}
diff --git a/tests/ModuleViewedTest.php b/tests/ModuleViewedTest.php
deleted file mode 100644
index 36a675721fade3eb7d4da3070018f743ac373774..0000000000000000000000000000000000000000
--- a/tests/ModuleViewedTest.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php namespace Tests;
-
-class ModuleViewedTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'page',
-            'objectid' => 1,
-            'eventname' => '\mod_page\event\course_module_viewed',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/ScormLaunchedTest.php b/tests/ScormLaunchedTest.php
deleted file mode 100644
index 4d8a732a9ad90b72bb26e02892caf44f7a07d377..0000000000000000000000000000000000000000
--- a/tests/ScormLaunchedTest.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php namespace Tests;
-
-class ScormLaunchedTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'objecttable' => 'scorm_scoes',
-            'objectid' => 1,
-            'eventname' => '\mod_scorm\event\sco_launched',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/ScormScorerawTestCase.php b/tests/ScormScorerawTestCase.php
deleted file mode 100644
index 547f60917585972c2ccbdef6049b600bddba5f5c..0000000000000000000000000000000000000000
--- a/tests/ScormScorerawTestCase.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php namespace Tests;
-
-class ScormScorerawTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-          'objecttable' => 'scorm_scoes_track',
-          'objectid' => 1,
-          'contextinstanceid' => 1,
-          'eventname' => '\mod_scorm\event\scoreraw_submitted',
-          'other' => 'a:3:{s:9:"attemptid";i:1;s:10:"cmielement";s:18:"cmi.core.score.raw";s:8:"cmivalue";s:3:"100";}',
-        ]);
-    }
-}
diff --git a/tests/ScormStatusTestCase.php b/tests/ScormStatusTestCase.php
deleted file mode 100644
index 240204cef432723b5cffea93eca8f0502904e310..0000000000000000000000000000000000000000
--- a/tests/ScormStatusTestCase.php
+++ /dev/null
@@ -1,13 +0,0 @@
-<?php namespace Tests;
-
-class ScormStatusTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-          'objecttable' => 'scorm_scoes_track',
-          'objectid' => 1,
-          'contextinstanceid' => 1,
-          'eventname' => '\mod_scorm\event\status_submitted',
-          'other' => 'a:3:{s:9:"attemptid";i:2;s:10:"cmielement";s:22:"cmi.core.lesson_status";s:8:"cmivalue";s:6:"failed";}';
-        ]);
-    }
-}
diff --git a/tests/TestCase.php b/tests/TestCase.php
deleted file mode 100644
index 46233217aed10b61d4ab51b86509150fb43da4b0..0000000000000000000000000000000000000000
--- a/tests/TestCase.php
+++ /dev/null
@@ -1,73 +0,0 @@
-<?php namespace Tests;
-use \PHPUnit_Framework_TestCase as PhpUnitTestCase;
-use \XREmitter\Controller as xapi_controller;
-use \XREmitter\Tests\TestRepository as xapi_repository;
-use \XREmitter\Tests\TestRemoteLrs as xapi_remote_lrs;
-use \MXTranslator\Controller as translator_controller;
-use \LogExpander\Controller as moodle_controller;
-use \LogExpander\Tests\TestRepository as moodle_repository;
-use \Locker\XApi\Statement as LockerStatement;
-use \TinCan\Statement as TinCanStatement;
-
-abstract class TestCase extends PhpUnitTestCase {
-    protected $xapi_controller, $moodle_controller, $translator_controller, $cfg;
-
-    /**
-     * Sets up the tests.
-     * @override PhpUnitTestCase
-     */
-    public function setup() {
-        $this->cfg = (object) [
-            'wwwroot' => 'http://www.example.com',
-            'release' => '1.0.0'
-        ];
-        $this->xapi_controller = new xapi_controller(new xapi_repository(new xapi_remote_lrs('', '1.0.1', '', '')));
-        $this->moodle_controller = new moodle_controller(new moodle_repository((object) [], $this->cfg));
-        $this->translator_controller = new translator_controller();
-    }
-
-    public function testCreateEvent() {
-        $input = $this->constructInput();
-
-        $moodle_events = $this->moodle_controller->createEvents([$input]);
-        $this->assertNotNull($moodle_events, 'Check that the events exist in the expander controller.');
-
-        //Hack to add Moodle plugin config setting for sendmbox - need to make config function
-        $moodle_events = [array_merge(
-            $moodle_events[0],
-            ['sendmbox' => false]
-        )];
-
-        $translatorEvents = $this->translator_controller->createEvents($moodle_events);
-        $this->assertNotNull($translatorEvents, 'Check that the events exist in the translator controller.');
-
-        $xapi_events = $this->xapi_controller->createEvents($translatorEvents);
-        $this->assertNotNull($xapi_events, 'Check that the events exist in the emitter controller.');
-
-        $this->assertOutput($input, $xapi_events);
-    }
-
-    protected function assertOutput($input, $output) {
-        foreach ($output as $outputpart) {
-            $this->assertValidXapiStatement((new TinCanStatement($outputpart))->asVersion('1.0.0'));
-        }
-    }
-
-    protected function assertValidXapiStatement($output) {
-        $errors = LockerStatement::createFromJson(json_encode($output))->validate();
-        $errorsJson = json_encode(array_map(function ($error) {
-            return (string) $error;
-        }, $errors));
-        $this->assertEmpty($errors, $errorsJson);
-    }
-
-    protected function constructInput() {
-        return [
-            'userid' => '1',
-            'relateduserid' => '1',
-            'courseid' => '1',
-            'timecreated' => 1433946701,
-            'eventname' => '\core\event\course_viewed'
-        ];
-    }
-}
diff --git a/tests/UserLoggedInTest.php b/tests/UserLoggedInTest.php
deleted file mode 100644
index 0d5b846d1264f605b11ded4c4b9ec2ca1ab7f21f..0000000000000000000000000000000000000000
--- a/tests/UserLoggedInTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class UserLoggedInTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\core\event\user_loggedin',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/UserLoggedOutTest.php b/tests/UserLoggedOutTest.php
deleted file mode 100644
index c27cb68bf800f129eea10f5d5db5d0701e76c3c8..0000000000000000000000000000000000000000
--- a/tests/UserLoggedOutTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class UserLoggedOutTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\core\event\user_loggedout',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/UserRegisteredTest.php b/tests/UserRegisteredTest.php
deleted file mode 100644
index c74a15e1ef0b0e36f54a5dde7813dd6ed1f3a4eb..0000000000000000000000000000000000000000
--- a/tests/UserRegisteredTest.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?php namespace Tests;
-
-class UserRegisteredTest extends TestCase {
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'eventname' => '\core\event\user_created',
-        ]);
-    }
-}
\ No newline at end of file
diff --git a/tests/assignment_graded_test.php b/tests/assignment_graded_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..28a5b143139f07572b21cd43cdba5fd6e5b3f4cc
--- /dev/null
+++ b/tests/assignment_graded_test.php
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/xapi_testcase.php');
+
+class assignment_graded_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'assign_grades',
+            'objectid' => '1',
+            'eventname' => '\mod_assign\event\submission_graded',
+        ]);
+    }
+}
diff --git a/tests/assignment_submitted_test.php b/tests/assignment_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..b60fea5716379b3fa735260f06c1394a7aa0e158
--- /dev/null
+++ b/tests/assignment_submitted_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class assignment_submitted_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'assign_submission',
+            'objectid' => 1,
+            'eventname' => '\mod_assign\event\assessable_submitted',
+        ]);
+    }
+}
diff --git a/tests/attempt_abandoned_test.php b/tests/attempt_abandoned_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..1ad43e6907cd7b6aac9443927c5585a47dffacff
--- /dev/null
+++ b/tests/attempt_abandoned_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/quiz_attempt_testcase.php');
+
+class attempt_abandonded_test extends quiz_attempt_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\mod_quiz\event\attempt_abandoned',
+        ]);
+    }
+}
diff --git a/tests/attempt_reviewed_test.php b/tests/attempt_reviewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d48e7dfd2dfe11ba20fc8aeae99c7ea5ea438181
--- /dev/null
+++ b/tests/attempt_reviewed_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/quiz_attempt_testcase.php');
+
+class attempt_reviewed_test extends quiz_attempt_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\mod_quiz\event\attempt_reviewed',
+        ]);
+    }
+}
diff --git a/tests/attempt_started_test.php b/tests/attempt_started_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..e4bba8ab2b2a111e7d2505846729b87b5c27f759
--- /dev/null
+++ b/tests/attempt_started_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/quiz_attempt_testcase.php');
+
+class attempt_started_test extends quiz_attempt_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\mod_quiz\event\attempt_preview_started',
+        ]);
+    }
+}
diff --git a/tests/course_completed_test.php b/tests/course_completed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..68bdc35ff8000094772664ed8d99d12ef3703fb2
--- /dev/null
+++ b/tests/course_completed_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class course_completed_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'course_completed',
+            'objectid' => 1,
+            'eventname' => '\core\event\course_completed',
+        ]);
+    }
+}
diff --git a/tests/course_viewed_test.php b/tests/course_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..22a6aaccb00796f3e77449a0f6435b79cf962096
--- /dev/null
+++ b/tests/course_viewed_test.php
@@ -0,0 +1,23 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class course_viewed_test extends xapi_testcase {
+
+}
diff --git a/tests/discussion_viewed_test.php b/tests/discussion_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..2f83d6a8382fcff8fd3944161cad0534d42e35fc
--- /dev/null
+++ b/tests/discussion_viewed_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class discussion_viewed_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'forum_discussions',
+            'objectid' => 1,
+            'eventname' => '\mod_forum\event\discussion_viewed',
+        ]);
+    }
+}
diff --git a/tests/enrolment_created_test.php b/tests/enrolment_created_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..c13747d7ae902a54dde89383671cbd15d57280f6
--- /dev/null
+++ b/tests/enrolment_created_test.php
@@ -0,0 +1,27 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class enrolment_created_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\core\event\user_enrolment_created',
+        ]);
+    }
+}
diff --git a/tests/feedback_submitted_test.php b/tests/feedback_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..fcceabfa1000717e8328b61a9b9727a659f4e5cf
--- /dev/null
+++ b/tests/feedback_submitted_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class feedback_submitted_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\mod_feedback\event\response_submitted',
+            'objecttable' => 'feedback_completed',
+            'objectid' => 1,
+        ]);
+    }
+}
diff --git a/tests/lib/emitter/TestRemoteLrs.php b/tests/lib/emitter/TestRemoteLrs.php
new file mode 100644
index 0000000000000000000000000000000000000000..7e232240302c028cfce3e78e21def33e62893c31
--- /dev/null
+++ b/tests/lib/emitter/TestRemoteLrs.php
@@ -0,0 +1,36 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \TinCan\RemoteLRS as TinCanRemoteLrs;
+
+class TestRemoteLrs extends TinCanRemoteLrs {
+    /**
+     * Creates a statement in the LRS.
+     * @param $statement
+     * @return \TinCan\Statement
+     * @override TinCanRemoteLrs
+     */
+    public function save_statement($statement) {
+        return (object) [
+            'success' => true,
+            'response' => $statement,
+        ];
+    }
+}
diff --git a/tests/lib/emitter/TestRepository.php b/tests/lib/emitter/TestRepository.php
new file mode 100644
index 0000000000000000000000000000000000000000..962e7f810dbab7fcb95c340c961a2daaac5728fd
--- /dev/null
+++ b/tests/lib/emitter/TestRepository.php
@@ -0,0 +1,33 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Repository as EmitterRepository;
+
+class TestRepository extends EmitterRepository {
+
+    /**
+     * Creates events in the store.
+     * @param [string => mixed] $event
+     * @return [string => mixed]
+     */
+    public function create_events(array $events) {
+        return $events;
+    }
+}
diff --git a/tests/lib/emitter/assignment_graded_test.php b/tests/lib/emitter/assignment_graded_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..13f78ff10eca1913ac758e4063c65eae706efb8e
--- /dev/null
+++ b/tests/lib/emitter/assignment_graded_test.php
@@ -0,0 +1,74 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\AssignmentGraded as Event;
+
+class assignment_graded_test extends event_test {
+    protected static $recipename = 'assignment_graded';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_user('graded_user'),
+            [
+                'grade_score_raw' => 47,
+                'grade_score_min' => 0,
+                'grade_score_max' => 100,
+                'grade_score_scaled' => 0.47,
+                'grade_success' => true,
+                'grade_completed' => true,
+                'grade_comment' => 'test comment from instructor'
+            ]
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        $this->assert_user($input, $output['actor'], 'graded_user');
+        $this->assert_object('app', $input, $output['context']['contextActivities']['grouping'][0]);
+        $this->assert_object('source', $input, $output['context']['contextActivities']['category'][0]);
+        $this->assert_log($input, $output);
+        $this->assert_info(
+            $input['context_info'],
+            $output['context']['extensions']['http://lrs.learninglocker.net/define/extensions/info']
+        );
+        $this->assert_valid_xapi_statement($output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/scored', 'received grade for', $output['verb']);
+        $this->assert_object('module', $input, $output['object']);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['parent'][0]);
+        $this->assertEquals($input['grade_score_raw'], $output['result']['score']['raw']);
+        $this->assertEquals($input['grade_score_min'], $output['result']['score']['min']);
+        $this->assertEquals($input['grade_score_max'], $output['result']['score']['max']);
+        $this->assertEquals($input['grade_score_scaled'], $output['result']['score']['scaled']);
+        $this->assertEquals($input['grade_success'], $output['result']['success']);
+        $this->assertEquals($input['grade_completed'], $output['result']['completion']);
+        $this->assertEquals($input['grade_comment'], $output['result']['response']);
+        $this->assert_user($input, $output['context']['instructor'], 'user');
+    }
+}
diff --git a/tests/lib/emitter/assignment_submitted_test.php b/tests/lib/emitter/assignment_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..3f55b68b96a3d91c24d46b84880bfc24145137e7
--- /dev/null
+++ b/tests/lib/emitter/assignment_submitted_test.php
@@ -0,0 +1,48 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\AssignmentSubmitted as Event;
+
+class assignment_submitted_test extends event_test {
+    protected static $recipename = 'assignment_submitted';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
+        $this->assert_object('module', $input, $output['object']);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+    }
+}
diff --git a/tests/lib/emitter/attempt_completed_test.php b/tests/lib/emitter/attempt_completed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..19e6aafd75aa5ea076455172d2e8cc53abcfcc5d
--- /dev/null
+++ b/tests/lib/emitter/attempt_completed_test.php
@@ -0,0 +1,69 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\AttemptCompleted as Event;
+
+class attempt_completed_test extends event_test {
+    protected static $recipename = 'attempt_completed';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_attempt()
+        );
+    }
+
+    protected function construct_attempt() {
+        return array_merge(parent::construct_attempt(), [
+            'attempt_score_raw' => 1,
+            'attempt_score_min' => 0,
+            'attempt_score_max' => 5,
+            'attempt_score_scaled' => 0.2,
+            'attempt_success' => false,
+            'attempt_completed' => true,
+            'attempt_duration' => 'P01DT',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
+        $this->assert_attempt($input, $output['context']['contextActivities']['grouping'][2]);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assert_object('module', $input, $output['object']);
+        $this->assertEquals($input['attempt_score_raw'], $output['result']['score']['raw']);
+        $this->assertEquals($input['attempt_score_min'], $output['result']['score']['min']);
+        $this->assertEquals($input['attempt_score_max'], $output['result']['score']['max']);
+        $this->assertEquals($input['attempt_score_scaled'], $output['result']['score']['scaled']);
+        $this->assertEquals($input['attempt_success'], $output['result']['success']);
+        $this->assertEquals($input['attempt_completed'], $output['result']['completion']);
+        $this->assertEquals($input['attempt_duration'], $output['result']['duration']);
+    }
+}
diff --git a/tests/lib/emitter/attempt_started_test.php b/tests/lib/emitter/attempt_started_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..265cf3bc47a8b47e564892c07fc5fdd0223d07b0
--- /dev/null
+++ b/tests/lib/emitter/attempt_started_test.php
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\AttemptStarted as Event;
+
+class attempt_started_test extends event_test {
+    protected static $recipename = 'attempt_started';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_attempt()
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://activitystrea.ms/schema/1.0/start', 'started', $output['verb']);
+        $this->assert_object('module', $input, $output['context']['contextActivities']['grouping'][2]);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assert_attempt($input, $output['object']);
+    }
+}
diff --git a/tests/lib/emitter/attended_test.php b/tests/lib/emitter/attended_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..105597fb6834ebef1beea1d1d37e2de53723eb4d
--- /dev/null
+++ b/tests/lib/emitter/attended_test.php
@@ -0,0 +1,70 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\Attended as Event;
+
+class attended_test extends event_test {
+    protected static $recipename = 'training_session_attend';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_object('session', 'http://activitystrea.ms/schema/1.0/event'),
+            $this->construct_user('attendee'),
+            [
+                "attempt_duration" => "PT150S",
+                "attempt_completion" => true
+            ]
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        $this->assert_object('app', $input, $output['context']['contextActivities']['grouping'][0]);
+        $this->assert_object('source', $input, $output['context']['contextActivities']['category'][0]);
+        $this->assert_log($input, $output);
+        $this->assert_info(
+            $input['context_info'],
+            $output['context']['extensions']['http://lrs.learninglocker.net/define/extensions/info']
+        );
+        $this->assert_valid_xapi_statement($output);
+        $this->assert_user($input, $output['actor'], 'attendee');
+        $this->assert_user($input, $output['context']['instructor'], 'user');
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/attended', 'attended', $output['verb']);
+        $this->assert_object('session', $input, $output['object']);
+        $this->assert_object('module', $input, $output['context']['contextActivities']['parent'][0]);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assertEquals($input['attempt_duration'], $output['result']['duration']);
+        $this->assertEquals($input['attempt_completion'], $output['result']['completion']);
+        $this->assertEquals(
+            'http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#simple',
+            $output['context']['contextActivities']['category'][1]['id']
+            );
+    }
+}
diff --git a/tests/lib/emitter/course_completed_test.php b/tests/lib/emitter/course_completed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..daf47fd091851a4905b0a9043c7dee2ccbcb9093
--- /dev/null
+++ b/tests/lib/emitter/course_completed_test.php
@@ -0,0 +1,62 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\CourseCompleted as Event;
+
+/**
+ * Class CourseCompletedTest
+ * @package XREmitter\Tests
+ */
+class course_completed_test extends event_test {
+    /**
+     * @var string
+     */
+    protected static $recipename = 'course_completed';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    /**
+     * Construct the input for the test.
+     * @return array
+     */
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course')
+        );
+    }
+
+    /**
+     * Asserts the output is the same as the input.
+     * @param $input
+     * @param $output
+     */
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
+        $this->assert_object('course', $input, $output['object']);
+    }
+}
diff --git a/tests/lib/emitter/course_viewed_test.php b/tests/lib/emitter/course_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ae1c32adf403273a9bcc26edf34b84217393715
--- /dev/null
+++ b/tests/lib/emitter/course_viewed_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\CourseViewed as Event;
+
+class course_viewed_test extends event_test {
+    protected static $recipename = 'course_viewed';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://id.tincanapi.com/verb/viewed', 'viewed', $output['verb']);
+        $this->assert_object('course', $input, $output['object']);
+    }
+}
diff --git a/tests/lib/emitter/discussion_viewed_test.php b/tests/lib/emitter/discussion_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d39457504c12e59518eac99572809da64bf50268
--- /dev/null
+++ b/tests/lib/emitter/discussion_viewed_test.php
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\DiscussionViewed as Event;
+
+class discussion_viewed_test extends event_test {
+    protected static $recipename = 'discussion_viewed';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_discussion()
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://id.tincanapi.com/verb/viewed', 'viewed', $output['verb']);
+        $this->assert_object('discussion', $input, $output['object']);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assert_object('module', $input, $output['context']['contextActivities']['grouping'][2]);
+    }
+}
diff --git a/tests/lib/emitter/enrolment_created_test.php b/tests/lib/emitter/enrolment_created_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..548963dc151bb9fcc0cfa5ebbefa4f920df06314
--- /dev/null
+++ b/tests/lib/emitter/enrolment_created_test.php
@@ -0,0 +1,48 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\EnrolmentCreated as Event;
+
+class enrolment_created_test extends event_test {
+    protected static $recipename = 'enrolment_created';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_user('instructor'),
+            $this->construct_object('course')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://www.tincanapi.co.uk/verbs/enrolled_onto_learning_plan', 'enrolled onto', $output['verb']);
+        $this->assert_object('course', $input, $output['object']);
+        $this->assert_user($input, $output['context']['instructor'], 'instructor');
+    }
+}
diff --git a/tests/lib/emitter/event_enrol_test.php b/tests/lib/emitter/event_enrol_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d880fe62d6137259dec4c13d4f3942b3d8d35044
--- /dev/null
+++ b/tests/lib/emitter/event_enrol_test.php
@@ -0,0 +1,55 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\EventEnrol as Event;
+
+class event_enrol_test extends event_test {
+    protected static $recipename = 'training_session_enrol';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_object('session', 'http://activitystrea.ms/schema/1.0/event')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_user($input, $output['actor'], 'user');
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/registered', 'registered for', $output['verb']);
+        $this->assert_object('session', $input, $output['object']);
+        $this->assert_object('module', $input, $output['context']['contextActivities']['parent'][0]);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assertEquals(
+            'http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#detailed',
+             $output['context']['contextActivities']['category'][1]['id']
+        );
+    }
+}
diff --git a/lib/emitter/tests/EventTest.php b/tests/lib/emitter/event_test.php
similarity index 54%
rename from lib/emitter/tests/EventTest.php
rename to tests/lib/emitter/event_test.php
index 22a513672c32ab9a8270b4d0391a783dc4eb7351..c0985ab9d5cb939f2925525e2794db8267ef7e18 100644
--- a/lib/emitter/tests/EventTest.php
+++ b/tests/lib/emitter/event_test.php
@@ -1,39 +1,62 @@
-<?php namespace XREmitter\Tests;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/../../../vendor/autoload.php');
+
 use \PHPUnit_Framework_TestCase as PhpUnitTestCase;
 use \XREmitter\Events\Event as Event;
 use \Locker\XApi\Statement as Statement;
 
-abstract class EventTest extends PhpUnitTestCase {
-    protected static $xapiType = 'http://lrs.learninglocker.net/define/type/moodle/';
-    protected static $recipeName;
+abstract class event_test extends \advanced_testcase {
+    protected static $xapitype = 'http://lrs.learninglocker.net/define/type/moodle/';
+    protected static $recipename;
 
     /**
      * Sets up the tests.
      * @override PhpUnitTestCase
      */
-    public function setup() {}
+    public function setup() {
+        // Empty.
+    }
 
     /**
      * Tests the read method of the Event.
      */
-    public function testRead() {
-        $input = $this->constructInput();
+    public function test_read() {
+        $input = $this->construct_input();
         $output = $this->event->read($input);
-        $this->assertOutput($input, $output);
-        $this->createExampleFile($output);
+        $this->assert_output($input, $output);
+        $this->create_example_file($output);
     }
 
-    protected function constructInput() {
+    protected function construct_input() {
         return array_merge(
-            $this->constructUser('user'),
-            $this->constructLog(),
-            $this->constructApp(),
-            $this->constructSource(),
-            ['recipe' => static::$recipeName]
+            $this->construct_user('user'),
+            $this->construct_log(),
+            $this->construct_app(),
+            $this->construct_source(),
+            ['recipe' => static::$recipename]
         );
     }
 
-    protected function constructUser($type) {
+    protected function construct_user($type) {
         return [
             $type.'_id' => '1',
             $type.'_url' => 'http://www.example.com/'.$type.'_url',
@@ -41,7 +64,7 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    private function constructLog() {
+    private function construct_log() {
         return [
             'context_lang' => 'en',
             'context_platform' => 'Moodle',
@@ -56,15 +79,15 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    protected function contructObject($type, $xapiType = null) {
-        if (is_null($xapiType)){
-            $xapiType = static::$xapiType.$type;
+    protected function construct_object($type, $xapitype = null) {
+        if (is_null($xapitype)) {
+            $xapitype = static::$xapitype . $type;
         }
         return [
             $type.'_url' => 'http://www.example.com/'.$type.'_url',
             $type.'_name' => 'Test '.$type.'_name',
             $type.'_description' => 'Test '.$type.'_description',
-            $type.'_type' => $xapiType,
+            $type.'_type' => $xapitype,
             $type.'_ext' => [
                 'test_'.$type.'_ext_key' => 'test_'.$type.'_ext_value',
             ],
@@ -72,7 +95,7 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    protected function constructApp() {
+    protected function construct_app() {
         $type = 'app';
         return [
             $type.'_url' => 'http://www.example.com/'.$type.'_url',
@@ -86,7 +109,7 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    protected function constructSource() {
+    protected function construct_source() {
         $type = 'source';
         return [
             $type.'_url' => 'http://www.example.com/'.$type.'_url',
@@ -96,10 +119,10 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    protected function constructAttempt() {
+    protected function construct_attempt() {
         return [
             'attempt_url' => 'http://www.example.com/attempt_url',
-            'attempt_type' => static::$xapiType.'attempt',
+            'attempt_type' => static::$xapitype . 'attempt',
             'attempt_ext' => [
                 'test_attempt_ext_key' => 'test_attempt_ext_value',
             ],
@@ -108,12 +131,12 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    protected function constructDiscussion() {
+    protected function construct_discussion() {
         return [
             'discussion_url' => 'http://www.example.com/discussion_url',
             'discussion_name' => 'A Forum Post',
             'discussion_description' => 'A description of the forum',
-            'discussion_type' => static::$xapiType.'discussion',
+            'discussion_type' => static::$xapitype . 'discussion',
             'discussion_ext_key' => 'http://www.example.com/attempt_ext_key',
             'discussion_ext' => [
                 'discussion_ext_key' => 'discussion_ext_value',
@@ -121,61 +144,61 @@ abstract class EventTest extends PhpUnitTestCase {
         ];
     }
 
-    protected function assertOutput($input, $output) {
-        $this->assertUser($input, $output['actor'], 'user');
-        $this->assertObject('app', $input, $output['context']['contextActivities']['grouping'][0]);
-        $this->assertObject('source', $input, $output['context']['contextActivities']['category'][0]);
-        $this->assertLog($input, $output);
-        $this->assertInfo(
+    protected function assert_output($input, $output) {
+        $this->assert_user($input, $output['actor'], 'user');
+        $this->assert_object('app', $input, $output['context']['contextActivities']['grouping'][0]);
+        $this->assert_object('source', $input, $output['context']['contextActivities']['category'][0]);
+        $this->assert_log($input, $output);
+        $this->assert_info(
             $input['context_info'],
             $output['context']['extensions']['http://lrs.learninglocker.net/define/extensions/info']
         );
-        $this->assertValidXapiStatement($output);
+        $this->assert_valid_xapi_statement($output);
     }
 
-    protected function assertValidXapiStatement($output) {
+    protected function assert_valid_xapi_statement($output) {
         $errors = Statement::createFromJson(json_encode($output))->validate();
-        $errorsJson = json_encode(array_map(function ($error) {
+        $errorsjson = json_encode(array_map(function ($error) {
             return (string) $error;
         }, $errors));
-        $this->assertEmpty($errors, $errorsJson);
+        $this->assertEmpty($errors, $errorsjson);
     }
 
-    protected function assertInfo($input, $output) {
+    protected function assert_info($input, $output) {
         $this->assertEquals(
             $input->{'https://moodle.org/'},
             $output->{'https://moodle.org/'}
         );
     }
 
-    protected function assertUser($input, $output, $type) {
+    protected function assert_user($input, $output, $type) {
         $this->assertEquals($input[$type.'_id'], $output['account']['name']);
         $this->assertEquals($input[$type.'_url'], $output['account']['homePage']);
         $this->assertEquals($input[$type.'_name'], $output['name']);
     }
 
-    protected function assertLog($input, $output) {
-        $actualContext = $output['context'];
-        $this->assertEquals($input['context_lang'], $actualContext['language']);
-        $this->assertEquals($input['context_platform'], $actualContext['platform']);
-        $this->assertArrayHasKey($input['context_ext_key'], $actualContext['extensions']);
-        $this->assertEquals($input['context_ext'], $actualContext['extensions'][$input['context_ext_key']]);
+    protected function assert_log($input, $output) {
+        $actualcontext = $output['context'];
+        $this->assertEquals($input['context_lang'], $actualcontext['language']);
+        $this->assertEquals($input['context_platform'], $actualcontext['platform']);
+        $this->assertArrayHasKey($input['context_ext_key'], $actualcontext['extensions']);
+        $this->assertEquals($input['context_ext'], $actualcontext['extensions'][$input['context_ext_key']]);
         $this->assertEquals($input['time'], $output['timestamp']);
     }
 
-    protected function assertObject($type, $input, $output) {
+    protected function assert_object($type, $input, $output) {
         $this->assertEquals($input[$type.'_url'], $output['id']);
         $this->assertEquals($input[$type.'_name'], $output['definition']['name'][$input['context_lang']]);
         $this->assertEquals($input[$type.'_type'], $output['definition']['type']);
         $this->assertEquals($input[$type.'_description'], $output['definition']['description'][$input['context_lang']]);
     }
 
-    protected function assertVerb($verbId, $verbName, $output) {
-        $this->assertEquals($verbId, $output['id']);
-        $this->assertEquals($verbName, $output['display']['en']);
+    protected function assert_verb($verbid, $verbname, $output) {
+        $this->assertEquals($verbid, $output['id']);
+        $this->assertEquals($verbname, $output['display']['en']);
     }
 
-    protected function assertAttempt($input, $output) {
+    protected function assert_attempt($input, $output) {
         $this->assertEquals($input['attempt_url'], $output['id']);
         $this->assertEquals($input['attempt_name'], $output['definition']['name'][$input['context_lang']]);
         $this->assertEquals($input['attempt_type'], $output['definition']['type']);
@@ -183,25 +206,25 @@ abstract class EventTest extends PhpUnitTestCase {
         $this->assertEquals($input['attempt_ext'], $output['definition']['extensions'][$input['attempt_ext_key']]);
     }
 
-    protected function assertComponentList($input, $output, $lang) {
+    protected function assert_component_list($input, $output, $lang) {
         foreach ($input as $id => $description) {
-            $outputId = 'Matching Id not found.';
-            $outputDescription = null;
-            foreach ($output as $outputItem) {
-                if ($outputItem->id == $id) {
-                    $outputId = $outputItem->id;
-                    $outputDescription = $outputItem->description[$lang];
+            $outputid = 'Matching Id not found.';
+            $outputdescription = null;
+            foreach ($output as $outputitem) {
+                if ($outputitem->id == $id) {
+                    $outputid = $outputitem->id;
+                    $outputdescription = $outputitem->description[$lang];
                 }
             }
-            $this->assertEquals($id, $outputId);
-            $this->assertEquals($description, $outputDescription);
+            $this->assertEquals($id, $outputid);
+            $this->assertEquals($description, $outputdescription);
         }
     }
 
-    protected function createExampleFile($output) {
-        $classArray = explode('\\', get_class($this));
-        $eventName = str_replace('Test', '', array_pop($classArray));
-        $exampleFile = __DIR__.'/../docs/examples/'.$eventName.'.json';
-        file_put_contents($exampleFile, json_encode($output, JSON_PRETTY_PRINT));
+    protected function create_example_file($output) {
+        $classarray = explode('\\', get_class($this));
+        $eventname = str_replace('_test', '', array_pop($classarray));
+        $examplefile = __DIR__ . '/../../../lib/emitter/docs/examples/' . $eventname . '.json';
+        file_put_contents($examplefile, json_encode($output, JSON_PRETTY_PRINT));
     }
 }
diff --git a/tests/lib/emitter/event_unenrol_test.php b/tests/lib/emitter/event_unenrol_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..c1e2b269455526d817c2e034ee332c9ca046dea0
--- /dev/null
+++ b/tests/lib/emitter/event_unenrol_test.php
@@ -0,0 +1,55 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\EventUnenrol as Event;
+
+class event_unenrol_test extends event_test {
+    protected static $recipename = 'training_session_unenrol';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_object('session', 'http://activitystrea.ms/schema/1.0/event')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_user($input, $output['actor'], 'user');
+        $this->assert_verb('http://id.tincanapi.com/verb/unregistered', 'unregistered from', $output['verb']);
+        $this->assert_object('session', $input, $output['object']);
+        $this->assert_object('module', $input, $output['context']['contextActivities']['parent'][0]);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assertEquals(
+            'http://xapi.trainingevidencesystems.com/recipes/attendance/0_0_1#detailed',
+            $output['context']['contextActivities']['category'][1]['id']
+        );
+    }
+}
diff --git a/tests/lib/emitter/module_viewed_test.php b/tests/lib/emitter/module_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..f6f67d683b065877d3ee10c4efa007c1312f91f9
--- /dev/null
+++ b/tests/lib/emitter/module_viewed_test.php
@@ -0,0 +1,48 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\ModuleViewed as Event;
+
+class module_viewed_test extends event_test {
+    protected static $recipename = 'module_viewed';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://id.tincanapi.com/verb/viewed', 'viewed', $output['verb']);
+        $this->assert_object('module', $input, $output['object']);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+    }
+}
diff --git a/tests/lib/emitter/question_answered_test.php b/tests/lib/emitter/question_answered_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..956f5922b28a93e903bc017eac96faea0b32202b
--- /dev/null
+++ b/tests/lib/emitter/question_answered_test.php
@@ -0,0 +1,92 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\QuestionAnswered as Event;
+
+class question_answered_test extends event_test {
+    protected static $recipename = 'attempt_question_completed';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_question(),
+            $this->construct_attempt()
+        );
+    }
+
+    protected function construct_attempt() {
+        return array_merge(parent::construct_attempt(), [
+            'attempt_score_raw' => 1,
+            'attempt_score_min' => 0,
+            'attempt_score_max' => 5,
+            'attempt_score_scaled' => 0.2,
+            'attempt_success' => false,
+            'attempt_completed' => true,
+            'attempt_response' => 'test response',
+        ]);
+    }
+
+    protected function construct_question() {
+        return array_merge(
+            parent::construct_object('question', 'http://adlnet.gov/expapi/activities/cmi.interaction'),
+            [
+                'interaction_type' => 'choice',
+                'interaction_correct_responses' => ['[9,10]'],
+                'interaction_choices' => [
+                    '8' => 'test incorrect choice',
+                    '9' => 'test correct choice 1',
+                    '10' => 'test correct choice 2'
+                ]
+            ]
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/answered', 'answered', $output['verb']);
+        $this->assertEquals($input['attempt_url'], $output['context']['contextActivities']['grouping'][2]['id']);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+        $this->assert_object('module', $input, $output['context']['contextActivities']['parent'][0]);
+        $this->assert_object('question', $input, $output['object']);
+        $this->assertEquals($input['interaction_type'], $output['object']['definition']['interactionType']);
+        $this->assertEquals($input['interaction_correct_responses'], $output['object']['definition']['correctResponsesPattern']);
+        $this->assert_component_list(
+            $input['interaction_choices'],
+            $output['object']['definition']['choices'], $input['context_lang']
+        );
+        $this->assertEquals($input['attempt_score_raw'], $output['result']['score']['raw']);
+        $this->assertEquals($input['attempt_score_min'], $output['result']['score']['min']);
+        $this->assertEquals($input['attempt_score_max'], $output['result']['score']['max']);
+        $this->assertEquals($input['attempt_score_scaled'], $output['result']['score']['scaled']);
+        $this->assertEquals($input['attempt_success'], $output['result']['success']);
+        $this->assertEquals($input['attempt_completed'], $output['result']['completion']);
+        $this->assertEquals($input['attempt_response'], $output['result']['response']);
+    }
+}
diff --git a/tests/lib/emitter/scorm_event_test.php b/tests/lib/emitter/scorm_event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..a7b7a77fe0059e231cbe34520a994005e02e83f3
--- /dev/null
+++ b/tests/lib/emitter/scorm_event_test.php
@@ -0,0 +1,71 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\ScormEvent as Event;
+
+class scorm_event_test extends event_test {
+    protected static $recipename = 'scorm_event';
+
+    /**
+     * Sets up the tests.
+     * @override ModuleViewedTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module'),
+            $this->construct_scorm_tracking(),
+            $this->construct_scorm_scoes()
+        );
+    }
+
+    protected function construct_scorm_tracking() {
+        return [
+            'scorm_score_raw' => 100,
+            'scorm_score_min' => 0,
+            'scorm_score_scaled' => 1,
+            'scorm_score_max' => 100,
+            'scorm_status' => 'completed',
+        ];
+    }
+
+    protected function construct_scorm_scoes() {
+        return [
+            'scorm_scoes_id' => 1,
+            'scorm_scoes_url' => 'http://www.example.com/module_url',
+            'scorm_scoes_type' => static::$xapitype . 'sco',
+            'scorm_scoes_name' => 'Sco name',
+            'scorm_scoes_description' => 'Sco Description',
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        $this->assert_user($input, $output['actor'], 'user');
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][0]);
+        $this->assert_object('module', $input, $output['object']);
+        $this->assert_object('scorm_scoes', $input, $output['context']['contextActivities']['grouping'][1]);
+    }
+
+}
diff --git a/tests/lib/emitter/scorm_launched_test.php b/tests/lib/emitter/scorm_launched_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa504082bc02f41b9a7dd747adab2a9f3315894b
--- /dev/null
+++ b/tests/lib/emitter/scorm_launched_test.php
@@ -0,0 +1,48 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\ScormLaunched as Event;
+
+class scorm_launched_test extends event_test {
+    protected static $recipename = 'scorm_launched';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_object('course'),
+            $this->construct_object('module')
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/launched', 'launched', $output['verb']);
+        $this->assert_object('module', $input, $output['object']);
+        $this->assert_object('course', $input, $output['context']['contextActivities']['grouping'][1]);
+    }
+}
diff --git a/tests/lib/emitter/scorm_score_raw_submitted_test.php b/tests/lib/emitter/scorm_score_raw_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..326eed1877dcfe2028d7f37f4051b7ae7f34dd8f
--- /dev/null
+++ b/tests/lib/emitter/scorm_score_raw_submitted_test.php
@@ -0,0 +1,43 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\ScormScoreRawSubmitted as Event;
+
+class scorm_score_raw_submitted_test extends scorm_event_test {
+    protected static $recipename = 'scorm_scoreraw_submitted';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
+        $this->assertEquals($input['scorm_score_raw'], $output['result']['score']['raw']);
+        $this->assertEquals($input['scorm_score_min'], $output['result']['score']['min']);
+        $this->assertEquals($input['scorm_score_max'], $output['result']['score']['max']);
+        $this->assertEquals($input['scorm_score_scaled'], $output['result']['score']['scaled']);
+        $this->assertEquals($input['scorm_status'], $output['verb']['display']['en']);
+    }
+}
diff --git a/tests/lib/emitter/scorm_status_submitted_test.php b/tests/lib/emitter/scorm_status_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..69f3f5c051644ab6e1e385db215664a01d90f47d
--- /dev/null
+++ b/tests/lib/emitter/scorm_status_submitted_test.php
@@ -0,0 +1,39 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\ScormStatusSubmitted as Event;
+
+class scorm_status_submitted_test extends scorm_event_test {
+    protected static $recipename = 'scorm_status_submitted';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/completed', 'completed', $output['verb']);
+        $this->assertEquals($input['scorm_status'], $output['verb']['display']['en']);
+    }
+}
diff --git a/tests/lib/emitter/user_loggedin_test.php b/tests/lib/emitter/user_loggedin_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..13aaed2e126d8110b38291a2852ef6fbb6d8a919
--- /dev/null
+++ b/tests/lib/emitter/user_loggedin_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\UserLoggedin as Event;
+
+class user_loggedin_test extends event_test {
+    protected static $recipename = 'user_loggedin';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_app()
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('https://brindlewaye.com/xAPITerms/verbs/loggedin/', 'logged in to', $output['verb']);
+        $this->assert_object('app', $input, $output['object']);
+    }
+}
diff --git a/tests/lib/emitter/user_loggedout_test.php b/tests/lib/emitter/user_loggedout_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..5ab3d1b899b8b15afa9f462332a3b72b3ccb1cb2
--- /dev/null
+++ b/tests/lib/emitter/user_loggedout_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\UserLoggedout as Event;
+
+class user_loggedout_test extends event_test {
+    protected static $recipename = 'user_loggedout';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_app()
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('https://brindlewaye.com/xAPITerms/verbs/loggedout/', 'logged out of', $output['verb']);
+        $this->assert_object('app', $input, $output['object']);
+    }
+}
diff --git a/tests/lib/emitter/user_registered_test.php b/tests/lib/emitter/user_registered_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..c8750b31e8c39fc5083d0f6b294a441e38de8668
--- /dev/null
+++ b/tests/lib/emitter/user_registered_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace XREmitter\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \XREmitter\Events\UserRegistered as Event;
+
+class user_registered_test extends event_test {
+    protected static $recipename = 'user_registered';
+
+    /**
+     * Sets up the tests.
+     * @override EventTest
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(
+            parent::construct_input(),
+            $this->construct_app()
+        );
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_verb('http://adlnet.gov/expapi/verbs/registered', 'registered to', $output['verb']);
+        $this->assert_object('app', $input, $output['object']);
+    }
+}
diff --git a/tests/lib/expander/TestRepository.php b/tests/lib/expander/TestRepository.php
new file mode 100644
index 0000000000000000000000000000000000000000..ed47fd1b8ab64398d1eb95281c9c43f29c3f422e
--- /dev/null
+++ b/tests/lib/expander/TestRepository.php
@@ -0,0 +1,108 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Repository as MoodleRepository;
+use \stdClass as PhpObj;
+
+class TestRepository extends MoodleRepository {
+
+    protected $fakemoodledatabase;
+
+    public function __construct($store, PhpObj $cfg) {
+        parent::__construct($store, $cfg);
+        $file = file_get_contents(__DIR__ . "/fakeDB.json");
+        $this->fakemoodledatabase = json_decode($file, true);
+    }
+
+    /**
+     * Reads an object from the store with the given id.
+     * @param string $type
+     * @param [string => mixed] $query
+     * @return php_obj
+     * @override MoodleRepository
+     */
+    protected function read_store_record($type, array $query, $index = 0) {
+        $records = $this->read_store_records($type, $query);
+        if (is_array($records)) {
+            return reset($records);
+        }
+        return $records;
+    }
+
+    /**
+     * Reads an array of objects from the store with the given type and query.
+     * @param String $type
+     * @param [String => Mixed] $query
+     * @return PhpArr
+     * @override MoodleRepository
+     */
+    protected function read_store_records($type, array $query) {
+        $records = $this->fakemoodledatabase[$type];
+        $matchingrecords = [];
+
+        foreach ($records as $record) {
+            foreach ($query as $key => $value) {
+                if ($record[$key] === $value) {
+                    // Required for assertRecord in EventTest.php to pass, but what's the purpose of including and testing this?
+                    $record['type'] = 'object';
+                    $matchingrecords[$record['id']] = (object) $record;
+                }
+            }
+        }
+
+        // If no matching records found, try to create some!
+        if (count($matchingrecords) == 0) {
+            foreach ($records as $record) {
+                $record['type'] = 'object';
+                $id = $record['id'];
+                foreach ($query as $key => $value) {
+                    $record[$key] = $value;
+                }
+                $matchingrecords[$id] = (object) $record;
+            }
+        }
+
+        // Always return at least 2 records.
+        if (count($matchingrecords) == 1) {
+            $newrecord = clone(reset($matchingrecords));
+            $newid = strval(intval($newrecord->id) + 1);
+            $newrecord->id = $newid;
+            $matchingrecords[$newid] = $newrecord;
+        }
+
+        return $matchingrecords;
+    }
+
+    protected function fullname($user) {
+        return "test_fullname";
+    }
+
+    /**
+     * Reads an object from the store with the given id.
+     * @param string $id
+     * @param string $type
+     * @return php_obj
+     */
+    public function read_object($id, $type) {
+        $model = $this->read_store_record($type, ['id' => $id]);
+        $model->id = $id;
+        return $model;
+    }
+}
diff --git a/tests/lib/expander/assignment_graded_test.php b/tests/lib/expander/assignment_graded_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..2eedddc118d867b78696d5b47ee5c1e6af43d02b
--- /dev/null
+++ b/tests/lib/expander/assignment_graded_test.php
@@ -0,0 +1,51 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\AssignmentGraded as Event;
+
+class assignment_graded_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'assign_grades',
+            'objectid' => 1,
+            'eventname' => '\mod_assign\event\submission_graded',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'assign');
+        $this->assert_user(1, $output['graded_user']);
+        $this->assert_record($input['objectid'], $output['grade']);
+        $this->assertEquals(5, $output['grade_items']->gradepass);
+        $this->assertEquals(5, $output['grade_items']->grademax);
+        $this->assertEquals(0, $output['grade_items']->grademin);
+        $this->assertEquals('<p>test comment</p>', $output['grade_comment']);
+    }
+}
diff --git a/tests/lib/expander/assignment_submitted_test.php b/tests/lib/expander/assignment_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..1d96edb4c94089d62bb5953167c88de8bf820c7e
--- /dev/null
+++ b/tests/lib/expander/assignment_submitted_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\AssignmentSubmitted as Event;
+
+class assignment_submitted_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'assign_submission',
+            'objectid' => 1,
+            'eventname' => '\mod_assign\event\assessable_submitted',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'assign');
+        $this->assert_record($input['objectid'], $output['submission']);
+    }
+}
diff --git a/lib/expander/tests/AttemptEventTest.php b/tests/lib/expander/attempt_event_test.php
similarity index 57%
rename from lib/expander/tests/AttemptEventTest.php
rename to tests/lib/expander/attempt_event_test.php
index 91c6dcc6b4f48ecef1da067a60b599eba33dd6f9..71c8e3d8d626dd8d244160b885c745c649ec20a1 100644
--- a/lib/expander/tests/AttemptEventTest.php
+++ b/tests/lib/expander/attempt_event_test.php
@@ -1,42 +1,61 @@
-<?php namespace LogExpander\Tests;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \LogExpander\Events\AttemptEvent as Event;
 
-class AttemptEventTest extends EventTest {
+class attempt_event_test extends event_test {
     /**
      * Sets up the tests.
      * @override TestCase
      */
     public function setup() {
+        parent::setup();
         $this->event = new Event($this->repo);
     }
 
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
             'objecttable' => 'quiz_attempts',
             'objectid' => 1,
             'eventname' => '\mod_quiz\event\attempt_preview_started',
         ]);
     }
 
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertModule(1, $output['module'], 'quiz');
-        $this->assertAttempt($input['objectid'], $output['attempt']);
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'quiz');
+        $this->assert_attempt($input['objectid'], $output['attempt']);
         $this->assertEquals(5, $output['grade_items']->gradepass);
         $this->assertEquals(5, $output['grade_items']->grademax);
         $this->assertEquals(0, $output['grade_items']->grademin);
-        $this->assertQuestionAttempts($output['attempt']->questions);
-        $this->assertQuestions($output['questions']);
-
+        $this->assert_question_attempts($output['attempt']->questions);
+        $this->assert_questions($output['questions']);
     }
 
-    protected function assertQuestionAttempts($output) {
+    protected function assert_question_attempts($output) {
         $this->assertEquals('1', $output['1']->id);
         $this->assertEquals('2', $output['1']->steps['2']->id);
         $this->assertEquals('2', $output['1']->steps['1']->data['2']->id);
     }
 
-    protected function assertQuestions($output) {
+    protected function assert_questions($output) {
         $this->assertEquals('multichoice', $output['1']->qtype);
         $this->assertEquals('1', $output['1']->id);
         $this->assertEquals('1', $output['1']->answers['1']->id);
diff --git a/tests/lib/expander/course_completed_test.php b/tests/lib/expander/course_completed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..1aab9f3142947b267e8f238f8071b1105444cb22
--- /dev/null
+++ b/tests/lib/expander/course_completed_test.php
@@ -0,0 +1,85 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\Event as Event;
+
+/**
+ * Class CourseCompletedTest
+ * @package LogExpander\Tests
+ */
+class course_completed_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    /**
+     * Construct the event, using even name, course_completed
+     * @return array
+     */
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => null,
+            'objectid' => null,
+            'eventname' => '\core\event\course_completed',
+            'action' => 'completed',
+            'target' => 'course',
+            'component' => 'core',
+        ]);
+    }
+
+    /**
+     * Assert output is equal to what we expect.
+     * @param $input
+     * @param $output
+     */
+    protected function assert_output($input, $output) {
+        $this->assert_user($input['userid'], $output['user']);
+        $this->assert_user($input['relateduserid'], $output['relateduser']);
+        $this->assert_course($input['courseid'], $output['course']);
+        $this->assert_site($input, $output['app']);
+        $this->assertEquals($input, $output['event']);
+        $this->assert_info($input, $output['info']);
+    }
+
+    /**
+     * Assert Site is what we expect it to be
+     * @param $input
+     * @param $output
+     */
+    private function assert_site($input, $output) {
+        $this->assertEquals($this->cfg->wwwroot, $output->url);
+        $this->assertEquals('site', $output->type);
+    }
+
+    /**
+     * Assert course is as expected.
+     * @param $input
+     * @param $output
+     */
+    private function assert_course($input, $output) {
+        $this->assert_record($input, $output);
+        $this->assertEquals($this->cfg->wwwroot . '/course/view.php?id=' . $output->id, $output->url);
+    }
+}
diff --git a/tests/lib/expander/discussion_event_test.php b/tests/lib/expander/discussion_event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..95f98c88a2766e12c3329164a362789ae9366858
--- /dev/null
+++ b/tests/lib/expander/discussion_event_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\DiscussionEvent as Event;
+
+class discussion_event_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'forum_discussions',
+            'objectid' => 1,
+            'eventname' => '\mod_forum\event\discussion_viewed',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'forum');
+        $this->assert_discussion($input['objectid'], $output['discussion']);
+    }
+}
diff --git a/tests/lib/expander/event_test.php b/tests/lib/expander/event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..a84d52473eb133cd8800b3686927f242fa108209
--- /dev/null
+++ b/tests/lib/expander/event_test.php
@@ -0,0 +1,118 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/../../../vendor/autoload.php');
+
+use \PHPUnit_Framework_TestCase as PhpUnitTestCase;
+use \LogExpander\Events\Event as Event;
+
+class event_test extends \advanced_testcase {
+    protected $cfg;
+    protected $repo;
+
+    /**
+     * Sets up the tests.
+     * @override PhpUnitTestCase
+     */
+    public function setup() {
+        $this->cfg = (object) [
+            'wwwroot' => 'http://www.example.com',
+            'release' => '1.0.0',
+        ];
+        $this->repo = new TestRepository((object) [], $this->cfg);
+        $this->event = new Event($this->repo);
+    }
+
+    /**
+     * Tests the read method of the Event.
+     */
+    public function test_read() {
+        $input = $this->construct_input();
+        $output = $this->event->read($input);
+        $this->assert_output($input, $output);
+        $this->create_example_file($output);
+    }
+
+    protected function construct_input() {
+        return [
+            'userid' => 1,
+            'relateduserid' => 1,
+            'courseid' => 1,
+            'timecreated' => 1433946701,
+            'eventname' => '\core\event\course_viewed',
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        $this->assert_user($input['userid'], $output['user']);
+        $this->assert_user($input['relateduserid'], $output['relateduser']);
+        $this->assert_course($input['courseid'], $output['course']);
+        $this->assert_site($input, $output['app']);
+        $this->assertEquals($input, $output['event']);
+        $this->assert_info($input, $output['info']);
+    }
+
+    protected function assert_info($input, $output) {
+        $this->assertEquals($this->cfg->release, $output->{'https://moodle.org/'});
+    }
+
+    protected function assert_record($input, $output) {
+        $this->assertEquals($input, $output->id);
+        $this->assertEquals('object', $output->type);
+    }
+
+    protected function assert_user($input, $output) {
+        $this->assert_record($input, $output);
+        $this->assertEquals($this->cfg->wwwroot, $output->url);
+        $this->assertEquals('test_fullname', $output->fullname);
+    }
+
+    private function assert_course($input, $output) {
+        $this->assert_record($input, $output);
+        $this->assertEquals($this->cfg->wwwroot . '/course/view.php?id=' . $output->id, $output->url);
+    }
+
+    private function assert_site($input, $output) {
+        $this->assertEquals($this->cfg->wwwroot, $output->url);
+        $this->assertEquals('site', $output->type);
+    }
+
+    protected function assert_module($input, $output, $type) {
+        $this->assert_record($input, $output);
+        $this->assertEquals($this->cfg->wwwroot . '/mod/'.$type.'/view.php?id=' . $output->id, $output->url);
+    }
+
+    protected function assert_attempt($input, $output) {
+        $this->assert_record($input, $output);
+        $this->assertEquals($this->cfg->wwwroot . '/mod/quiz/attempt.php?attempt=' . $output->id, $output->url);
+    }
+
+    protected function assert_discussion($input, $output) {
+        $this->assert_record($input, $output);
+        $this->assertEquals($this->cfg->wwwroot . '/mod/forum/discuss.php?d=' . $output->id, $output->url);
+    }
+
+    protected function create_example_file($output) {
+        $classarray = explode('\\', get_class($this));
+        $eventname = str_replace('_test', '', array_pop($classarray));
+        $examplefile = __DIR__ . '/../../../lib/expander/docs/examples/' . $eventname . '.json';
+        file_put_contents($examplefile, json_encode($output, JSON_PRETTY_PRINT));
+    }
+}
diff --git a/tests/lib/expander/facetoface_attended_test.php b/tests/lib/expander/facetoface_attended_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..7167c4a3cd79517d111e5d870f46e752bc751080
--- /dev/null
+++ b/tests/lib/expander/facetoface_attended_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\FacetofaceAttended as Event;
+
+class facetoface_attended_test extends facetoface_event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'facetoface_sessions',
+            'objectid' => 1,
+            'eventname' => '\mod_facetoface\event\signup_success',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assertEquals(1, $output['signups'][1]->id);
+        $this->assertEquals(1, $output['signups'][1]->attendee->id);
+    }
+}
diff --git a/tests/lib/expander/facetoface_event_test.php b/tests/lib/expander/facetoface_event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..5873e0dda09e29d0faf27d9af62ed2bacf557ed7
--- /dev/null
+++ b/tests/lib/expander/facetoface_event_test.php
@@ -0,0 +1,46 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\FacetofaceEvent as Event;
+
+class facetoface_event_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'facetoface_sessions',
+            'objectid' => 1,
+            'eventname' => '\mod_facetoface\event\signup_success',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'facetoface');
+        $this->assertEquals(2, $output['session']->dates[2]->id);
+    }
+}
diff --git a/lib/expander/tests/fakeDB.json b/tests/lib/expander/fakeDB.json
similarity index 100%
rename from lib/expander/tests/fakeDB.json
rename to tests/lib/expander/fakeDB.json
diff --git a/tests/lib/expander/feedback_submitted_test.php b/tests/lib/expander/feedback_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..abe493677a95ea4f88c955084412e212c28b65d7
--- /dev/null
+++ b/tests/lib/expander/feedback_submitted_test.php
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\FeedbackSubmitted as Event;
+
+class feedback_submitted_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'feedback_completed',
+            'objectid' => '1',
+            'eventname' => '\mod_feedback\event\response_submitted',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'feedback');
+        $this->assertEquals('test_name', $output['questions'][1]->name);
+        $this->assertEquals('http://www.example.com/mod/feedback/edit_item.php?id=1', $output['questions']['1']->url);
+        $this->assertEquals('test_name', $output['questions'][1]->template->name);
+        $this->assertEquals('http://www.example.com/mod/feedback/complete.php?id=1', $output['attempt']->url);
+        $this->assertEquals('1', $output['attempt']->responses['1']->id);
+    }
+}
diff --git a/tests/lib/expander/module_event_test.php b/tests/lib/expander/module_event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..0df3f334276c27677caffc7a1ed140bd1914dca4
--- /dev/null
+++ b/tests/lib/expander/module_event_test.php
@@ -0,0 +1,45 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\ModuleEvent as Event;
+
+class module_event_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'page',
+            'objectid' => 1,
+            'eventname' => '\mod_page\event\course_module_viewed',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module($input['objectid'], $output['module'], 'page');
+    }
+}
diff --git a/tests/lib/expander/scorm_launched_test.php b/tests/lib/expander/scorm_launched_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d1a1f605f6ee537fa57e857217e3aa654221fd1a
--- /dev/null
+++ b/tests/lib/expander/scorm_launched_test.php
@@ -0,0 +1,50 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\ScormLaunched as Event;
+
+class scorm_launched_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'scorm_scoes',
+            'objectid' => 1,
+            'eventname' => '\mod_scorm\event\sco_launched',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'scorm');
+        $this->assert_scorm(1, $output['scorm_scoes']);
+    }
+
+    protected function assert_scorm($input, $output) {
+        $this->assert_record($input, $output);
+    }
+}
diff --git a/tests/lib/expander/scorm_submitted_test.php b/tests/lib/expander/scorm_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..6af4d914b769a54dec99f9608922c084f4c4ad08
--- /dev/null
+++ b/tests/lib/expander/scorm_submitted_test.php
@@ -0,0 +1,62 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace LogExpander\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \LogExpander\Events\ScormSubmitted as Event;
+
+class scorm_submitted_test extends event_test {
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event($this->repo);
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'scorm_scoes_track',
+            'objectid' => 1,
+            'contextinstanceid' => 1,
+            'eventname' => '\mod_scorm\event\scoreraw_submitted',
+            'other' => 'a:3:{s:9:"attemptid";i:1;s:10:"cmielement";s:18:"cmi.core.score.raw";s:8:"cmivalue";s:3:"100";}',
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module(1, $output['module'], 'scorm');
+        $this->assertEquals(1, $output['scorm_scoes']->id);
+        $this->assert_scorm_scoes_track($output);
+        $this->assert_cmi_data($output);
+    }
+
+    protected function assert_scorm_scoes_track($output) {
+        $this->assertEquals('status', $output['scorm_scoes_track']['status']);
+        $this->assertEquals(100, $output['scorm_scoes_track']['scoremax']);
+        $this->assertEquals(0, $output['scorm_scoes_track']['scoremin']);
+    }
+
+    protected function assert_cmi_data($output) {
+        $this->assertEquals(1, $output['cmi_data']['attemptid']);
+        $this->assertEquals('cmi.core.score.raw', $output['cmi_data']['cmielement']);
+        $this->assertEquals(100, $output['cmi_data']['cmivalue']);
+    }
+}
diff --git a/tests/lib/translator/assignment_graded_test.php b/tests/lib/translator/assignment_graded_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d3a39fd1e609248d388379d61832bad685389b8d
--- /dev/null
+++ b/tests/lib/translator/assignment_graded_test.php
@@ -0,0 +1,72 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\AssignmentGraded as Event;
+
+class assignment_graded_test extends module_viewed_test {
+    protected static $recipename = 'assignment_graded';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'grade' => (object) [
+                'grade' => 1,
+            ],
+            'graded_user' => $this->construct_user(),
+            'grade_items' => $this->construct_grade_items(),
+            'grade_comment' => "test comment"
+        ]);
+    }
+
+    private function construct_grade_items() {
+        return (object) [
+            'grademin' => 0,
+            'grademax' => 5,
+            'gradepass' => 5
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assertEquals($input['grade']->grade, $output['grade_score_raw']);
+        $this->assertEquals($input['grade_comment'], $output['grade_comment']);
+        $this->assertEquals(true, $output['grade_completed']);
+        $this->assert_grade_items($input, $output);
+        $this->assert_user($input['graded_user'], $output, 'graded_user');
+    }
+
+    protected function assert_grade_items($input, $output) {
+        $this->assertEquals((float) $input['grade_items']->grademin, $output['grade_score_min']);
+        $this->assertEquals((float) $input['grade_items']->grademax, $output['grade_score_max']);
+        $this->assertEquals(($input['grade']->grade >= $input['grade_items']->gradepass), $output['grade_success']);
+        if ($output['grade_score_scaled'] >= 0) {
+            $this->assertEquals($output['grade_score_scaled'], $output['grade_score_raw'] / $output['grade_score_max']);
+        } else {
+            $this->assertEquals($output['grade_score_scaled'], $output['grade_score_raw'] / $output['grade_score_min']);
+        }
+    }
+}
diff --git a/tests/lib/translator/assignment_submitted_test.php b/tests/lib/translator/assignment_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..58c199d0a7b931dd24a8cca2537da0f0c398ad40
--- /dev/null
+++ b/tests/lib/translator/assignment_submitted_test.php
@@ -0,0 +1,39 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\AssignmentSubmitted as Event;
+
+class assignment_submitted_test extends module_viewed_test {
+    protected static $recipename = 'assignment_submitted';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'submission' => (object) [],
+        ]);
+    }
+}
diff --git a/tests/lib/translator/attempt_abandoned_test.php b/tests/lib/translator/attempt_abandoned_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..534d1d3b0141f486d0e0399f917776cd3e264bb6
--- /dev/null
+++ b/tests/lib/translator/attempt_abandoned_test.php
@@ -0,0 +1,34 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\AttemptAbandoned as Event;
+
+class attempt_abandoned_test extends attempt_reviewed_test {
+    protected static $recipename = 'attempt_abandoned';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+}
diff --git a/tests/lib/translator/attempt_reviewed_test.php b/tests/lib/translator/attempt_reviewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..7eb292f65c97da1b8887e2985da0900dfa07ba75
--- /dev/null
+++ b/tests/lib/translator/attempt_reviewed_test.php
@@ -0,0 +1,71 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\AttemptReviewed as Event;
+
+class attempt_reviewed_test extends attempt_started_test {
+    protected static $recipename = 'attempt_completed';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'grade_items' => $this->construct_grade_items()
+        ]);
+    }
+
+    private function construct_grade_items() {
+        return (object) [
+            'grademin' => 0,
+            'grademax' => 5,
+            'gradepass' => 5
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_attempt($input['attempt'], $output);
+        $this->assert_grade_items($input, $output);
+    }
+
+    protected function assert_attempt($input, $output) {
+        parent::assert_attempt($input, $output);
+        $this->assertEquals((float) $input->sumgrades, $output['attempt_score_raw']);
+        $this->assertEquals($input->state === 'finished', $output['attempt_completed']);
+    }
+
+    protected function assert_grade_items($input, $output) {
+        $this->assertEquals((float) $input['grade_items']->grademin, $output['attempt_score_min']);
+        $this->assertEquals((float) $input['grade_items']->grademax, $output['attempt_score_max']);
+        $this->assertEquals(($input['attempt']->sumgrades >= $input['grade_items']->gradepass), $output['attempt_success']);
+        if ($output['attempt_score_scaled'] >= 0) {
+            $this->assertEquals($output['attempt_score_scaled'], $output['attempt_score_raw'] / $output['attempt_score_max']);
+        } else {
+            $this->assertEquals($output['attempt_score_scaled'], $output['attempt_score_raw'] / $output['attempt_score_min']);
+        }
+    }
+}
diff --git a/tests/lib/translator/attempt_started_test.php b/tests/lib/translator/attempt_started_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..13964ba1f1bca60ffb36fa80217cc7ccfc4a5abb
--- /dev/null
+++ b/tests/lib/translator/attempt_started_test.php
@@ -0,0 +1,66 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\AttemptStarted as Event;
+
+class attempt_started_test extends module_viewed_test {
+    protected static $recipename = 'attempt_started';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'attempt' => $this->construct_attempt(),
+        ]);
+    }
+
+    private function construct_attempt() {
+        return (object) [
+            'url' => 'http://www.example.com/attempt_url',
+            'name' => 'Test attempt_name',
+            'type' => 'moodle_attempt',
+            'timestart' => 1433946701,
+            'timefinish' => 1433946701,
+            'sumgrades' => 1,
+            'state' => 'finished',
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_attempt($input['attempt'], $output);
+    }
+
+    protected function assert_attempt($input, $output) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_attempt';
+        $this->assertEquals($input->url, $output['attempt_url']);
+        $this->assertEquals($input->name, $output['attempt_name']);
+        $this->assertEquals(static::$xapitype.$input->type, $output['attempt_type']);
+        $this->assertEquals($input, $output['attempt_ext']);
+        $this->assertEquals($extkey, $output['attempt_ext_key']);
+    }
+}
diff --git a/tests/lib/translator/course_completed_test.php b/tests/lib/translator/course_completed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..d51bc98007e8159022b52045ea55d10aff58482b
--- /dev/null
+++ b/tests/lib/translator/course_completed_test.php
@@ -0,0 +1,73 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\CourseCompleted as Event;
+
+/**
+ * Class CourseCompletedTest
+ * @package MXTranslator\Tests
+ */
+class course_completed_test extends event_test {
+    /**
+     * @var string
+     */
+    protected static $recipename = 'course_completed';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    /**
+     * Constructs the Input with course completed
+     * @return array
+     */
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'event' => $this->construct_event('\core\event\course_completed'),
+        ]);
+    }
+
+    /**
+     * Constructs the event with the given event name
+     * @param $eventname
+     * @return array
+     */
+    private function construct_event($eventname) {
+        return [
+            'eventname' => $eventname,
+            'timecreated' => 1433946701,
+        ];
+    }
+
+    /**
+     * Assets that the input is the same as the output.
+     * @param $input
+     * @param $output
+     */
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_course($input['course'], $output, 'course');
+    }
+}
diff --git a/tests/lib/translator/course_viewed_test.php b/tests/lib/translator/course_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..7180520fb0cdec116f5f618174bebd509efff659
--- /dev/null
+++ b/tests/lib/translator/course_viewed_test.php
@@ -0,0 +1,38 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\CourseViewed as Event;
+
+class course_viewed_test extends user_event_test {
+    protected static $recipename = 'course_viewed';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_course($input['course'], $output, 'course');
+    }
+}
diff --git a/tests/lib/translator/discussion_viewed_test.php b/tests/lib/translator/discussion_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..331878c2845f8517192d033d3f7ebf5c20d3a65e
--- /dev/null
+++ b/tests/lib/translator/discussion_viewed_test.php
@@ -0,0 +1,65 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\DiscussionViewed as Event;
+
+class discussion_viewed_test extends module_viewed_test {
+    protected static $recipename = 'discussion_viewed';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'discussion' => $this->construct_discussion(),
+        ]);
+    }
+
+    private function construct_discussion() {
+        return (object) [
+            'url' => 'http://www.example.com/discussion_url',
+            'name' => 'Test discussion_name',
+            'type' => 'moodle_discussion',
+            'ext' => 'discussion_ext',
+            'ext_key' => 'http://lrs.learninglocker.net/define/extensions/moodle_discussion',
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_discussion($input['discussion'], $output, 'discussion');
+    }
+
+    private function assert_discussion($input, $output, $type) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_discussion';
+        $this->assertEquals($input->url, $output[$type.'_url']);
+        $this->assertEquals($input->name, $output[$type.'_name']);
+        $this->assertEquals('A Moodle discussion.', $output[$type.'_description']);
+        $this->assertEquals(static::$xapitype.$input->type, $output[$type.'_type']);
+        $this->assertEquals($input, $output[$type.'_ext']);
+        $this->assertEquals($extkey, $output[$type.'_ext_key']);
+    }
+}
diff --git a/tests/lib/translator/enrolment_created_test.php b/tests/lib/translator/enrolment_created_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..09a83b65e8c5da18b0feeef6f559399673e3e590
--- /dev/null
+++ b/tests/lib/translator/enrolment_created_test.php
@@ -0,0 +1,41 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\EnrolmentCreated as Event;
+
+class enrolment_created_test extends event_test {
+    protected static $recipename = 'enrolment_created';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_user($input['user'], $output, 'instructor');
+        $this->assert_user($input['relateduser'], $output, 'user');
+        $this->assert_course($input['course'], $output, 'course');
+    }
+}
diff --git a/tests/lib/translator/event_test.php b/tests/lib/translator/event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..14349b6a79ed756c041ee24fb25fe3c44e891c8a
--- /dev/null
+++ b/tests/lib/translator/event_test.php
@@ -0,0 +1,192 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/../../../vendor/autoload.php');
+
+use \PHPUnit_Framework_TestCase as PhpUnitTestCase;
+use \MXTranslator\Events\Event as Event;
+
+abstract class event_test extends \advanced_testcase {
+    protected static $xapitype = 'http://lrs.learninglocker.net/define/type/moodle/';
+    protected static $recipename;
+
+    /**
+     * Sets up the tests.
+     * @override PhpUnitTestCase
+     */
+    public function setup() {
+        $this->event = new Event();
+    }
+
+    /**
+     * Tests the read method of the Event.
+     */
+    public function test_read() {
+        $input = $this->construct_input();
+        $outputs = $this->event->read($input);
+        $this->assert_outputs($input, $outputs);
+        foreach ($outputs as $output) {
+            $input = $this->construct_input();
+            $this->assert_output($input, $output);
+            $this->create_example_file($output);
+        }
+    }
+
+    protected function construct_input() {
+        return [
+            'user' => $this->construct_user(),
+            'relateduser' => $this->construct_user(),
+            'course' => $this->construct_course(),
+            'app' => $this->construct_app(),
+            'source' => $this->construct_source(),
+            'event' => $this->construct_event('\core\event\course_viewed'),
+            'info' => $this->construct_info(),
+            'sendmbox' => true
+        ];
+    }
+
+    protected function construct_info() {
+        return (object) [
+            'https://moodle.org/' => '1.0.0'
+        ];
+    }
+
+    protected function construct_user() {
+        return (object) [
+            'id' => 1,
+            'url' => 'http://www.example.com/user_url',
+            'fullname' => 'Test user_name',
+            'email' => 'test@test.com',
+        ];
+    }
+
+    private function construct_event($eventname) {
+        return [
+            'eventname' => $eventname,
+            'timecreated' => 1433946701,
+        ];
+    }
+
+    protected function construct_course() {
+        return (object) [
+            'url' => 'http://www.example.com/course_url',
+            'fullname' => 'Test course_fullname',
+            'summary' => '<p>Test course_summary</p>',
+            'lang' => 'en',
+            'type' => 'moodle_course',
+        ];
+    }
+
+    protected function construct_app() {
+        return (object) [
+            'url' => 'http://www.example.com',
+            'fullname' => 'Test site_fullname',
+            'summary' => '<p>Test site_summary</p>',
+            'lang' => 'en',
+            'type' => 'moodle_site',
+        ];
+    }
+
+    protected function construct_source() {
+        return (object) [
+            'url' => 'http://moodle.org',
+            'fullname' => 'Moodle',
+            'summary' => 'Moodle is a open source learning platform designed to provide educators,'
+                .' administrators and learners with a single robust, secure and integrated system'
+                .' to create personalised learning environments.',
+            'lang' => 'en',
+            'type' => 'moodle_source',
+        ];
+    }
+
+    protected function assert_outputs($input, $output) {
+        // Output is an associative array.
+        $this->assertEquals(0, count(array_filter(array_keys($output), 'is_string')));
+        // Length of output is 1. Overwrite this function if a different value is needed.
+        $this->assertEquals(1 , count($output));
+    }
+
+    protected function assert_output($input, $output) {
+        $this->assert_app($input['app'], $output, 'app');
+        $this->assert_event($input['event'], $output);
+        $this->assertEquals(static::$recipename, $output['recipe']);
+        $this->assert_info($input['info'], $output['context_info']);
+    }
+
+    protected function assert_user($input, $output, $type) {
+        $this->assertEquals($input->id, $output[$type.'_id']);
+        $this->assertEquals($input->url, $output[$type.'_url']);
+        $this->assertEquals($input->fullname, $output[$type.'_name']);
+    }
+
+    protected function assert_course($input, $output, $type) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_course';
+        $this->assertEquals($input->lang, $output['context_lang']);
+        $this->assertEquals($input->url, $output[$type.'_url']);
+        $this->assertEquals($input->fullname, $output[$type.'_name']);
+        $this->assertEquals(strip_tags($input->summary), $output[$type.'_description']);
+        $this->assertEquals(static::$xapitype.$input->type, $output[$type.'_type']);
+        $this->assertEquals($input, $output[$type.'_ext']);
+        $this->assertEquals($extkey, $output[$type.'_ext_key']);
+    }
+
+    protected function assert_app($input, $output, $type) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_course';
+        $apptype = 'http://id.tincanapi.com/activitytype/site';
+        $this->assertEquals($input->lang, $output['context_lang']);
+        $this->assertEquals($input->url, $output[$type.'_url']);
+        $this->assertEquals($input->fullname, $output[$type.'_name']);
+        $this->assertEquals(strip_tags($input->summary), $output[$type.'_description']);
+        $this->assertEquals($apptype, $output[$type.'_type']);
+        $this->assertEquals($input, $output[$type.'_ext']);
+        $this->assertEquals($extkey, $output[$type.'_ext_key']);
+    }
+
+    protected function assert_source($input, $output, $type) {
+        $apptype = 'http://id.tincanapi.com/activitytype/source';
+        $this->assertEquals($input->lang, $output['context_lang']);
+        $this->assertEquals($input->url, $output[$type.'_url']);
+        $this->assertEquals($input->fullname, $output[$type.'_name']);
+        $this->assertEquals(strip_tags($input->summary), $output[$type.'_description']);
+        $this->assertEquals($apptype, $output[$type.'_type']);
+    }
+
+    private function assert_event($input, $output) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_logstore_standard_log';
+        $this->assertEquals('Moodle', $output['context_platform']);
+        $this->assertEquals($input, $output['context_ext']);
+        $this->assertEquals($extkey, $output['context_ext_key']);
+        $this->assertEquals(date('c', $input['timecreated']), $output['time']);
+    }
+
+    private function assert_info($input, $output) {
+        $this->assertEquals(
+            $input->{'https://moodle.org/'},
+            $output->{'https://moodle.org/'}
+        );
+    }
+
+    protected function create_example_file($output) {
+        $classarray = explode('\\', get_class($this));
+        $eventname = str_replace('_test', '', array_pop($classarray));
+        $examplefile = __DIR__ . '/../../../lib/translator/docs/examples/' . $eventname . '.json';
+        file_put_contents($examplefile, json_encode($output, JSON_PRETTY_PRINT));
+    }
+}
diff --git a/tests/lib/translator/facetoface_attended_test.php b/tests/lib/translator/facetoface_attended_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..e51893b86de03dd7a0ba60de30f35476f724057a
--- /dev/null
+++ b/tests/lib/translator/facetoface_attended_test.php
@@ -0,0 +1,113 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\FacetofaceAttend as Event;
+
+class facetoface_attend_test extends facetoface_enrol_test {
+    protected static $recipename = 'training_session_attend';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'signups' => [
+                "1" => $this->construct_signup("1"),
+                "2" => $this->construct_signup("2")
+            ]
+        ]);
+    }
+
+    private function construct_signup($facetofaceid) {
+        $signups = (object) [
+            "id" => $facetofaceid,
+            "sessionid" => "1",
+            "userid" => "1",
+            "mailedreminder" => "0",
+            "discountcode" => null,
+            "notificationtype" => "3",
+            "statuses" => [
+                "1" => $this->construct_status("1"),
+                "2" => $this->construct_status("2"),
+                "3" => $this->construct_final_status("3"),
+            ],
+            "attendee" => $this->construct_user()
+        ];
+
+        return $signups;
+    }
+
+    private function construct_status($facetofaceid) {
+        return (object) [
+            "id" => $facetofaceid,
+            "signupid" => "4",
+            "statuscode" => "90",
+            "superceded" => "1",
+            "grade" => "50.00000",
+            "note" => "",
+            "advice" => null,
+            "createdby" => "1",
+            "timecreated" => "143394660" . $facetofaceid // Earlier than the final status.
+        ];
+    }
+
+    private function construct_final_status($facetofaceid) {
+        return (object) [
+            "id" => $facetofaceid,
+            "signupid" => "4",
+            "statuscode" => "100",
+            "superceded" => "0",
+            "grade" => "100.00000",
+            "note" => "",
+            "advice" => null,
+            "createdby" => "1",
+            "timecreated" => "1433946701" // Must be the same as timecreated in EventTest.php.
+        ];
+    }
+
+    protected function assert_outputs($input, $output) {
+        // Output is an associative array.
+        $this->assertEquals(0, count(array_filter(array_keys($output), 'is_string')));
+        // Length of output is 3.
+        $this->assertEquals(2 , count($output));
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assertEquals($input['signups']['1']->attendee->id, $output['attendee_id']);
+        $this->assertEquals($input['signups']['1']->attendee->url, $output['attendee_url']);
+        $this->assertEquals($input['signups']['1']->attendee->fullname, $output['attendee_name']);
+
+        $sessionduration = 0;
+        foreach ($input['session']->dates as $index => $date) {
+            $sessionduration -= $date->timestart;
+            $sessionduration += $date->timefinish;
+        }
+
+        $this->assertEquals("PT" . $sessionduration . "S", $output['attempt_duration']);
+        $this->assertEquals(true, $output['attempt_completion']);
+    }
+}
diff --git a/tests/lib/translator/facetoface_enrol_test.php b/tests/lib/translator/facetoface_enrol_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..e21cd68900c71d1a22ec3e5e1957c836b2d09c99
--- /dev/null
+++ b/tests/lib/translator/facetoface_enrol_test.php
@@ -0,0 +1,75 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\FacetofaceEnrol as Event;
+
+class facetoface_enrol_test extends module_viewed_test {
+    protected static $recipename = 'training_session_enrol';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'session' => $this->construct_session()
+        ]);
+    }
+
+    private function construct_session() {
+        return (object) [
+            "id" => "1",
+            "facetoface" => "1",
+            "capacity" => "10",
+            "allowoverbook" => "0",
+            "details" => "",
+            "datetimeknown" => "0",
+            "duration" => "0",
+            "normalcost" => "0",
+            "discountcost" => "0",
+            "timecreated" => "1464179438",
+            "timemodified" => "0",
+            "type" => "facetoface_sessions",
+            "dates" => [
+                "1" => (object) [
+                    "id" => "1",
+                    "sessionid" => "1",
+                    "timestart" => "1464176400",
+                    "timefinish" => "1464179400"
+                ]
+            ],
+            'url' => 'http://www.example.com/session_url'
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assertEquals($input['session']->url, $output['session_url']);
+        $sessionname = 'Session '.$input['session']->id.' of '.$input['module']->name;
+        $this->assertEquals($sessionname, $output['session_name']);
+        $this->assertEquals($sessionname, $output['session_description']);
+        $this->assertEquals('http://activitystrea.ms/schema/1.0/event', $output['session_type']);
+    }
+}
diff --git a/tests/lib/translator/facetoface_unenrol_test.php b/tests/lib/translator/facetoface_unenrol_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..04b11c786c21270656a637db81a4f13b4f7f46e1
--- /dev/null
+++ b/tests/lib/translator/facetoface_unenrol_test.php
@@ -0,0 +1,34 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\FacetofaceUnenrol as Event;
+
+class facetoface_unenrol_test extends facetoface_enrol_test {
+    protected static $recipename = 'training_session_unenrol';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+}
diff --git a/tests/lib/translator/feedback_question_submitted_test.php b/tests/lib/translator/feedback_question_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..be03c3c2da3e9279e532e01308374b32ea481941
--- /dev/null
+++ b/tests/lib/translator/feedback_question_submitted_test.php
@@ -0,0 +1,61 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\FeedbackQuestionSubmitted as Event;
+
+class feedback_question_submitted_test extends feedback_submitted_test {
+    protected static $recipename = 'attempt_question_completed';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+
+        $questions = $input['questions'];
+        $questionsarr = (array) $questions;
+
+        $responses = $input['attempt']->responses;
+        $responsesarr = (array) $responses;
+
+        $this->assertEquals($questionsarr['1']->name, $output['question_name']);
+        $this->assertEquals($questionsarr['1']->name, $output['question_description']);
+        $this->assertEquals($questionsarr['1']->url, $output['question_url']);
+        $this->assertEquals($responsesarr['2']->value, $output['attempt_response']);
+        $this->assertEquals(null, $output['interaction_correct_responses']);
+        $this->assertEquals('likert', $output['interaction_type']);
+        $this->assertEquals((object) [
+            "0" => "Not selected",
+            '1' => "incorrect",
+            '2' => "correct"
+        ], $output['interaction_scale']);
+    }
+
+    protected function assert_attempt($input, $output) {
+        // Overides parent and does nothing.
+    }
+
+}
diff --git a/lib/translator/tests/FeedbackSubmittedTest.php b/tests/lib/translator/feedback_submitted_test.php
similarity index 54%
rename from lib/translator/tests/FeedbackSubmittedTest.php
rename to tests/lib/translator/feedback_submitted_test.php
index e81b05fca11d98926df2b9a7e5c1b2a103f3dc7a..ad00c65fd2c91ff75a869e7a924802359cb943bb 100644
--- a/lib/translator/tests/FeedbackSubmittedTest.php
+++ b/tests/lib/translator/feedback_submitted_test.php
@@ -1,25 +1,45 @@
-<?php namespace MXTranslator\Tests;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \MXTranslator\Events\FeedbackSubmitted as Event;
 
-class FeedbackSubmittedTest extends ModuleViewedTest {
-    protected static $recipeName = 'attempt_completed';
+class feedback_submitted_test extends module_viewed_test {
+    protected static $recipename = 'attempt_completed';
 
     /**
      * Sets up the tests.
      * @override TestCase
      */
     public function setup() {
+        parent::setup();
         $this->event = new Event();
     }
 
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
-            'attempt' => $this->constructAttempt(),
-            'questions' => $this->constructQuestions()
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'attempt' => $this->construct_attempt(),
+            'questions' => $this->construct_questions()
         ]);
     }
 
-    private function constructAttempt() {
+    private function construct_attempt() {
         return (object) [
             'url' => 'http://www.example.com/attempt_url',
             'name' => 'Test attempt_name',
@@ -35,7 +55,7 @@ class FeedbackSubmittedTest extends ModuleViewedTest {
         ];
     }
 
-    private function constructQuestions() {
+    private function construct_questions() {
         return (object) [
             "1" => (object) [
                 "id" => "1",
@@ -56,9 +76,9 @@ class FeedbackSubmittedTest extends ModuleViewedTest {
         ];
     }
 
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
-        $this->assertAttempt($input['attempt'], $output);
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_attempt($input['attempt'], $output);
         $this->assertEquals(0, $output['attempt_score_min']);
         $this->assertEquals(1, $output['attempt_score_max']);
         $this->assertEquals(1, $output['attempt_score_scaled']);
@@ -67,13 +87,13 @@ class FeedbackSubmittedTest extends ModuleViewedTest {
         $this->assertEquals(null, $output['attempt_duration']);
     }
 
-    protected function assertAttempt($input, $output) {
-        $extKey = 'http://lrs.learninglocker.net/define/extensions/moodle_feedback_attempt';
+    protected function assert_attempt($input, $output) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_feedback_attempt';
         $this->assertEquals($input->url, $output['attempt_url']);
         $this->assertEquals($input->name, $output['attempt_name']);
-        $this->assertEquals(static::$xapiType.$input->type, $output['attempt_type']);
+        $this->assertEquals(static::$xapitype.$input->type, $output['attempt_type']);
         $this->assertEquals($input, $output['attempt_ext']);
-        $this->assertEquals($extKey, $output['attempt_ext_key']);
+        $this->assertEquals($extkey, $output['attempt_ext_key']);
     }
 
 }
diff --git a/tests/lib/translator/module_viewed_test.php b/tests/lib/translator/module_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..4bb486809c0d20a0e83c609cd079e2c3fcb15955
--- /dev/null
+++ b/tests/lib/translator/module_viewed_test.php
@@ -0,0 +1,64 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\ModuleViewed as Event;
+
+class module_viewed_test extends course_viewed_test {
+    protected static $recipename = 'module_viewed';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'module' => $this->construct_module(),
+        ]);
+    }
+
+    private function construct_module() {
+        return (object) [
+            'url' => 'http://www.example.com/module_url',
+            'name' => 'Test module_name',
+            'intro' => 'Test module_intro',
+            'type' => 'moodle_module',
+        ];
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_module($input['module'], $output, 'module');
+    }
+
+    private function assert_module($input, $output, $type) {
+        $extkey = 'http://lrs.learninglocker.net/define/extensions/moodle_module';
+        $this->assertEquals($input->url, $output[$type.'_url']);
+        $this->assertEquals($input->name, $output[$type.'_name']);
+        $this->assertEquals($input->intro, $output[$type.'_description']);
+        $this->assertEquals(static::$xapitype.$input->type, $output[$type.'_type']);
+        $this->assertEquals($input, $output[$type.'_ext']);
+        $this->assertEquals($extkey, $output[$type.'_ext_key']);
+    }
+}
diff --git a/lib/translator/tests/QuestionSubmittedTest.php b/tests/lib/translator/question_submitted_test.php
similarity index 68%
rename from lib/translator/tests/QuestionSubmittedTest.php
rename to tests/lib/translator/question_submitted_test.php
index 9b230fdc0363ac6c6e99cc6906f84cc0408897b2..8a738038d3a2cf88e31738db1e791124d5fb58e1 100644
--- a/lib/translator/tests/QuestionSubmittedTest.php
+++ b/tests/lib/translator/question_submitted_test.php
@@ -1,45 +1,65 @@
-<?php namespace MXTranslator\Tests;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \MXTranslator\Events\QuestionSubmitted as Event;
 
-class QuestionSubmittedTest extends AttemptStartedTest {
-    protected static $recipeName = 'attempt_question_completed';
+class question_submitted_test extends attempt_started_test {
+    protected static $recipename = 'attempt_question_completed';
 
     /**
      * Sets up the tests.
      * @override TestCase
      */
     public function setup() {
+        parent::setup();
         $this->event = new Event();
     }
 
-    protected function constructInput() {
-        $input = array_merge(parent::constructInput(), [
-            'questions' => $this->constructQuestions()
+    protected function construct_input() {
+        $input = array_merge(parent::construct_input(), [
+            'questions' => $this->construct_questions()
         ]);
-        $input['attempt']->questions = $this->constructQuestionAttempts();
+        $input['attempt']->questions = $this->construct_question_attempts();
 
         return $input;
     }
 
-    private function constructQuestionAttempts() {
+    private function construct_question_attempts() {
         return [
-            $this->constructQuestionAttempt(0, 'truefalse'),
-            $this->constructQuestionAttempt(1, 'multichoice'),
-            $this->constructQuestionAttempt(2, 'calculated'),
-            $this->constructQuestionAttempt(3, 'calculatedmulti'),
-            $this->constructQuestionAttempt(4, 'calculatedsimple'),
-            $this->constructQuestionAttempt(5, 'randomsamatch'),
-            $this->constructQuestionAttempt(6, 'match'),
-            $this->constructQuestionAttempt(7, 'shortanswer'),
-            $this->constructQuestionAttempt(8, 'somecustomquestiontypethatsnotstandardinmoodle'),
-            $this->constructQuestionAttempt(9, 'someothertypewithnoanswers'),
-            $this->constructQuestionAttempt(10, 'shortanswer'),
-            $this->constructQuestionAttempt(11, 'numerical')
+            $this->construct_question_attempt(0, 'truefalse'),
+            $this->construct_question_attempt(1, 'multichoice'),
+            $this->construct_question_attempt(2, 'calculated'),
+            $this->construct_question_attempt(3, 'calculatedmulti'),
+            $this->construct_question_attempt(4, 'calculatedsimple'),
+            $this->construct_question_attempt(5, 'randomsamatch'),
+            $this->construct_question_attempt(6, 'match'),
+            $this->construct_question_attempt(7, 'shortanswer'),
+            $this->construct_question_attempt(8, 'somecustomquestiontypethatsnotstandardinmoodle'),
+            $this->construct_question_attempt(9, 'someothertypewithnoanswers'),
+            $this->construct_question_attempt(10, 'shortanswer'),
+            $this->construct_question_attempt(11, 'numerical')
         ];
     }
 
-    private function constructQuestionAttempt($index, $qtype) {
-         $questionAttempt = (object) [
+    private function construct_question_attempt($index, $qtype) {
+        $questionattempt = (object) [
             'id' => $index,
             'questionid' => $index,
             'maxmark' => '5.0000000',
@@ -80,57 +100,57 @@ class QuestionSubmittedTest extends AttemptStartedTest {
         ];
 
         if (in_array($qtype, $matchtypes)) {
-            $questionAttempt->responsesummary = 'test question -> test answer; test question 2 -> test answer 4';
-            $questionAttempt->rightanswer = 'test question -> test answer; test question 2 -> test answer 4';
+            $questionattempt->responsesummary = 'test question -> test answer; test question 2 -> test answer 4';
+            $questionattempt->rightanswer = 'test question -> test answer; test question 2 -> test answer 4';
         } else if (in_array($qtype, $choicetypes)) {
-            $questionAttempt->responsesummary = 'test answer; test answer 2';
-            $questionAttempt->rightanswer = 'test answer; test answer 2';
+            $questionattempt->responsesummary = 'test answer; test answer 2';
+            $questionattempt->rightanswer = 'test answer; test answer 2';
         } else if (in_array($qtype, $numerictypes)) {
-            $questionAttempt->responsesummary = '5';
-            $questionAttempt->rightanswer = '5';
+            $questionattempt->responsesummary = '5';
+            $questionattempt->rightanswer = '5';
         } else if ($qtype == 'truefalse') {
-            $questionAttempt->responsesummary = 'True';
-            $questionAttempt->rightanswer = 'True';
+            $questionattempt->responsesummary = 'True';
+            $questionattempt->rightanswer = 'True';
         }
 
-        return $questionAttempt;
+        return $questionattempt;
     }
 
-    private function constructQuestions() {
+    private function construct_questions() {
         return [
-            $this->constructQuestion('00', 'truefalse'),
-            $this->constructQuestion('01', 'multichoice'),
-            $this->constructQuestion('02', 'calculated'),
-            $this->constructQuestion('03', 'calculatedmulti'),
-            $this->constructQuestion('04', 'calculatedsimple'),
-            $this->constructQuestion('05', 'randomsamatch'),
-            $this->constructQuestion('06', 'match'),
-            $this->constructQuestion('07', 'shortanswer'),
-            $this->constructQuestion('08', 'somecustomquestiontypethatsnotstandardinmoodle'),
-            $this->constructQuestion('09', 'someothertypewithnoanswers'),
-            $this->constructQuestion('10', 'shortanswer'),
-            $this->constructQuestion('11', 'numerical')
+            $this->construct_question('00', 'truefalse'),
+            $this->construct_question('01', 'multichoice'),
+            $this->construct_question('02', 'calculated'),
+            $this->construct_question('03', 'calculatedmulti'),
+            $this->construct_question('04', 'calculatedsimple'),
+            $this->construct_question('05', 'randomsamatch'),
+            $this->construct_question('06', 'match'),
+            $this->construct_question('07', 'shortanswer'),
+            $this->construct_question('08', 'somecustomquestiontypethatsnotstandardinmoodle'),
+            $this->construct_question('09', 'someothertypewithnoanswers'),
+            $this->construct_question('10', 'shortanswer'),
+            $this->construct_question('11', 'numerical')
         ];
     }
 
-    private function constructQuestion($index, $qtype) {
+    private function construct_question($index, $qtype) {
         $question = (object) [
             'id' => $index,
             'name' => 'test question '.$index,
             'questiontext' => 'test question',
             'url' => 'http://localhost/moodle/question/question.php?id='.$index,
             'answers' => [
-                '1'=> (object)[
+                '1' => (object)[
                     'id' => '1',
                     'answer' => 'test answer',
                     'fraction' => '0.50'
                 ],
-                '2'=> (object)[
+                '2' => (object)[
                     'id' => '2',
                     'answer' => 'test answer 2',
                     'fraction' => '0.50'
                 ],
-                '3'=> (object)[
+                '3' => (object)[
                     'id' => '3',
                     'answer' => 'wrong test answer',
                     'fraction' => '0.00'
@@ -142,13 +162,13 @@ class QuestionSubmittedTest extends AttemptStartedTest {
         if ($question->qtype == 'numerical') {
             $question->numerical = (object)[
                 'answers' => [
-                    '1'=> (object)[
+                    '1' => (object)[
                         'id' => '1',
                         'question' => $index,
                         'answer' => '1',
                         'tolerance' => '1'
                     ],
-                    '2'=> (object)[
+                    '2' => (object)[
                         'id' => '2',
                         'question' => $index,
                         'answer' => '2',
@@ -157,12 +177,12 @@ class QuestionSubmittedTest extends AttemptStartedTest {
                 ]
             ];
             $question->answers = [
-                '1'=> (object)[
+                '1' => (object)[
                     'id' => '1',
                     'answer' => '5',
                     'fraction' => '1.00'
                 ],
-                '2'=> (object)[
+                '2' => (object)[
                     'id' => '2',
                     'answer' => '10',
                     'fraction' => '0.00'
@@ -171,12 +191,12 @@ class QuestionSubmittedTest extends AttemptStartedTest {
         } else if ($question->qtype == 'match') {
             $question->match = (object)[
                 'subquestions' => [
-                    '1'=> (object)[
+                    '1' => (object)[
                         'id' => '1',
                         'questiontext' => '<p>test question</p>',
                         'answertext' => '<p>test answer</p>'
                     ],
-                    '2'=> (object)[
+                    '2' => (object)[
                         'id' => '4',
                         'questiontext' => '<p>test question 2</p>',
                         'answertext' => '<p>test answer 4</p>'
@@ -186,13 +206,13 @@ class QuestionSubmittedTest extends AttemptStartedTest {
         } else if (strpos($question->qtype, 'calculated') === 0) {
             $question->calculated = (object)[
                 'answers' => [
-                    '1'=> (object)[
+                    '1' => (object)[
                         'id' => '1',
                         'question' => $index,
                         'answer' => '1',
                         'tolerance' => '1'
                     ],
-                    '2'=> (object)[
+                    '2' => (object)[
                         'id' => '2',
                         'question' => $index,
                         'answer' => '2',
@@ -201,12 +221,12 @@ class QuestionSubmittedTest extends AttemptStartedTest {
                 ]
             ];
             $question->answers = [
-                '1'=> (object)[
+                '1' => (object)[
                     'id' => '1',
                     'answer' => '5',
                     'fraction' => '1.00'
                 ],
-                '2'=> (object)[
+                '2' => (object)[
                     'id' => '2',
                     'answer' => '10',
                     'fraction' => '0.00'
@@ -224,12 +244,12 @@ class QuestionSubmittedTest extends AttemptStartedTest {
             $question->answers = [];
         } else if ($question->qtype == 'truefalse') {
             $question->answers = [
-                '1'=> (object)[
+                '1' => (object)[
                     'id' => '1',
                     'answer' => 'True',
                     'fraction' => '1.00'
                 ],
-                '2'=> (object)[
+                '2' => (object)[
                     'id' => '2',
                     'answer' => 'False',
                     'fraction' => '0.00'
@@ -240,7 +260,7 @@ class QuestionSubmittedTest extends AttemptStartedTest {
         if ($index == '10') {
             $question->questiontext = 'test question 2';
             $question->answers = [
-                '1'=> (object)[
+                '1' => (object)[
                     'id' => '4',
                     'answer' => 'test answer 4',
                     'fraction' => '1.00'
@@ -250,29 +270,29 @@ class QuestionSubmittedTest extends AttemptStartedTest {
         return $question;
     }
 
-    protected function assertOutputs($input, $output) {
-        //output is an associative array
+    protected function assert_outputs($input, $output) {
+        // Output is an associative array.
         $this->assertEquals(0, count(array_filter(array_keys($output), 'is_string')));
         $this->assertEquals(count($input['questions']) , count($output));
     }
 
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
         $questionindex = intval(substr($output['question_name'], 14, 2), 10);
-        $attemptQuestions = $input['attempt']->questions[$questionindex];
+        $attemptquestions = $input['attempt']->questions[$questionindex];
 
-        $this->assertAttempt($input['attempt'], $output);
-        $this->assertQuestion($input['questions'][$questionindex], $output);
-        $this->assertQuestionAttempt($attemptQuestions, $output, $input['questions'][$questionindex]);
+        $this->assert_attempt($input['attempt'], $output);
+        $this->assert_question($input['questions'][$questionindex], $output);
+        $this->assert_question_attempt($attemptquestions, $output, $input['questions'][$questionindex]);
     }
 
-    protected function assertAttempt($input, $output) {
+    protected function assert_attempt($input, $output) {
         $this->assertEquals($input->url, $output['attempt_url']);
         $this->assertEquals($input->name, $output['attempt_name']);
-        $this->assertEquals(static::$xapiType.$input->type, $output['attempt_type']);
+        $this->assertEquals(static::$xapitype.$input->type, $output['attempt_type']);
     }
 
-    protected function assertQuestionAttempt($input, $output, $question) {
+    protected function assert_question_attempt($input, $output, $question) {
         $this->assertEquals((float) $input->maxmark, $output['attempt_score_max']);
         $this->assertEquals(0, $output['attempt_score_min']);
         $this->assertEquals((float) $input->steps[1]->fraction, $output['attempt_score_scaled']);
@@ -302,29 +322,30 @@ class QuestionSubmittedTest extends AttemptStartedTest {
 
         if (in_array($question->qtype, $matchtypes)) {
             $this->assertEquals(
-                'moodle_quiz_question_source_1[.]moodle_quiz_question_target_1[,]moodle_quiz_question_source_4[.]moodle_quiz_question_target_4',
+                'moodle_quiz_question_source_1[.]moodle_quiz_question_target_1[,]' .
+                'moodle_quiz_question_source_4[.]moodle_quiz_question_target_4',
                 $output['interaction_correct_responses'][0]
             );
         } else if (in_array($question->qtype, $numerictypes)) {
              $this->assertEquals('4[:]6', $output['interaction_correct_responses'][0]);
         } else if (in_array($question->qtype, $fillintypes)) {
             $this->assertEquals(
-                '{case_matters=false}'.$question->answers['1']->answer, 
+                '{case_matters=false}'.$question->answers['1']->answer,
                 $output['interaction_correct_responses'][0]
             );
         } else if ($question->qtype == 'truefalse') {
             $this->assertEquals(
-                strtolower($question->answers['1']->answer), 
+                strtolower($question->answers['1']->answer),
                 $output['interaction_correct_responses'][0]
             );
         } else if (!in_array($question->qtype, $noanswer)) {
-            // Multichoice
+            // Multichoice.
             $this->assertEquals(
                 'moodle_quiz_question_answer_1[,]moodle_quiz_question_answer_2',
                 $output['interaction_correct_responses'][0]
             );
         } else {
-            // Default
+            // Default.
             $this->assertEquals($input->rightanswer, $output['interaction_correct_responses'][0]);
         }
 
@@ -337,8 +358,7 @@ class QuestionSubmittedTest extends AttemptStartedTest {
 
     }
 
-    protected function assertQuestion($input, $output) {
-        
+    protected function assert_question($input, $output) {
         if (strpos($input->qtype, 'calculated') === 0) {
             $this->assertEquals($input->url.'&variant=1', $output['question_url']);
             $this->assertEquals($input->name . ' - variant 1', $output['question_name']);
@@ -372,7 +392,7 @@ class QuestionSubmittedTest extends AttemptStartedTest {
 
         if (in_array($input->qtype, $matchtypes)) {
             $this->assertEquals(
-                'test question', 
+                'test question',
                 $output['interaction_target']['moodle_quiz_question_target_1']
             );
             $this->assertEquals(
@@ -380,7 +400,7 @@ class QuestionSubmittedTest extends AttemptStartedTest {
                 $output['interaction_source']['moodle_quiz_question_source_1']
             );
             $this->assertEquals(
-                'test question 2', 
+                'test question 2',
                 $output['interaction_target']['moodle_quiz_question_target_4']
             );
             $this->assertEquals(
diff --git a/tests/lib/translator/scorm_event_test.php b/tests/lib/translator/scorm_event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..64615c55a30df3905ee980b60ab6467f4e11d8e5
--- /dev/null
+++ b/tests/lib/translator/scorm_event_test.php
@@ -0,0 +1,58 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\ScormEvent as Event;
+
+class scorm_event_test extends module_viewed_test {
+    protected static $recipename = 'scorm_event';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'scorm_scoes_track' => [
+                'status' => 'completed',
+            ],
+            'cmi_data' => [
+                'cmivalue' => 'completed',
+                'cmielement' => 'cmi.core.lesson_status',
+                'attemptid' => 2,
+            ],
+            'scorm_scoes' => $this->construct_scorm_scoes(),
+        ]);
+    }
+
+    protected function construct_scorm_scoes() {
+        return (object)[
+            'id' => 1,
+            'scorm' => 1,
+            'scormtype' => 'sco',
+            'title' => 'Sco title'
+        ];
+    }
+}
+
diff --git a/tests/lib/translator/scorm_launched_test.php b/tests/lib/translator/scorm_launched_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..f2b91e367473aff5718d5059ff18faa64968bd1c
--- /dev/null
+++ b/tests/lib/translator/scorm_launched_test.php
@@ -0,0 +1,34 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\ScormLaunched as Event;
+
+class scorm_launched_test extends module_viewed_test {
+    protected static $recipename = 'scorm_launched';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+}
diff --git a/lib/translator/tests/ScormScoreRawSubmittedTest.php b/tests/lib/translator/scorm_score_raw_submitted_test.php
similarity index 53%
rename from lib/translator/tests/ScormScoreRawSubmittedTest.php
rename to tests/lib/translator/scorm_score_raw_submitted_test.php
index 17cb72c11057a2c5c3824301bc617983e8eda7b7..8bcaa836e62bcb25b55f7265d0609566bcf12052 100644
--- a/lib/translator/tests/ScormScoreRawSubmittedTest.php
+++ b/tests/lib/translator/scorm_score_raw_submitted_test.php
@@ -1,19 +1,39 @@
-<?php namespace MXTranslator\Tests;
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
 use \MXTranslator\Events\ScormScoreRawSubmitted as Event;
 
-class ScormScoreRawSubmittedTest extends ScormEventTest {
-    protected static $recipeName = 'scorm_scoreraw_submitted';
+class scorm_score_raw_submitted_test extends scorm_event_test {
+    protected static $recipename = 'scorm_scoreraw_submitted';
 
     /**
      * Sets up the tests.
      * @override TestCase
      */
     public function setup() {
+        parent::setup();
         $this->event = new Event();
     }
 
-    protected function constructInput() {
-        return array_merge(parent::constructInput(), [
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
             'scorm_scoes_track' => [
                 'scoremax' => 100,
                 'scoremin' => 0,
@@ -24,12 +44,12 @@ class ScormScoreRawSubmittedTest extends ScormEventTest {
                 'cmielement' => 'cmi.core.score.raw',
                 'attemptid' => 1,
             ],
-            'scorm_scoes' => $this->constructScormScoes()
+            'scorm_scoes' => $this->construct_scorm_scoes()
         ]);
     }
 
-    protected function assertOutput($input, $output) {
-        parent::assertOutput($input, $output);
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
         $this->assertEquals($input['module']->name, $output['scorm_name']);
         $this->assertEquals($input['module']->url, $output['scorm_url']);
         $this->assertEquals($input['module']->url, $output['scorm_scoes_url']);
diff --git a/tests/lib/translator/scorm_status_submitted_test.php b/tests/lib/translator/scorm_status_submitted_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..55d38e6c997b1fd2deff62790633ee8751b40e30
--- /dev/null
+++ b/tests/lib/translator/scorm_status_submitted_test.php
@@ -0,0 +1,58 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\ScormStatusSubmitted as Event;
+
+class scorm_status_submitted_test extends scorm_event_test {
+    protected static $recipename = 'scorm_status_submitted';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'scorm_scoes_track' => [
+                'status' => 'completed',
+            ],
+            'cmi_data' => [
+                'cmivalue' => 'completed',
+                'cmielement' => 'cmi.core.lesson_status',
+                'attemptid' => 2,
+            ],
+            'scorm_scoes' => $this->construct_scorm_scoes()
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assertEquals($input['module']->name, $output['scorm_name']);
+        $this->assertEquals($input['module']->url, $output['scorm_url']);
+        $this->assertEquals($input['scorm_scoes_track']['status'], $output['scorm_status']);
+        $this->assertEquals($input['cmi_data']['cmivalue'], $output['scorm_status']);
+        $this->assertEquals($input['cmi_data']['attemptid'], $output['scorm_attempt']);
+    }
+}
diff --git a/tests/lib/translator/user_event_test.php b/tests/lib/translator/user_event_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..f3f584d716ecebfdaef6784cb1494d1edb4abe4c
--- /dev/null
+++ b/tests/lib/translator/user_event_test.php
@@ -0,0 +1,35 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\Event as Event;
+
+abstract class user_event_test extends event_test {
+
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'user' => $this->construct_user(),
+        ]);
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_user($input['user'], $output, 'user');
+    }
+}
diff --git a/tests/lib/translator/user_loggedin_test.php b/tests/lib/translator/user_loggedin_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..b6350f5011d76006598109556db82592806dbc40
--- /dev/null
+++ b/tests/lib/translator/user_loggedin_test.php
@@ -0,0 +1,34 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\UserLoggedin as Event;
+
+class user_loggedin_test extends user_event_test {
+    protected static $recipename = 'user_loggedin';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+}
diff --git a/tests/lib/translator/user_loggedout_test.php b/tests/lib/translator/user_loggedout_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..db03f17738dd6e896219b27f31fc9479c7e7c408
--- /dev/null
+++ b/tests/lib/translator/user_loggedout_test.php
@@ -0,0 +1,34 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\UserLoggedout as Event;
+
+class user_loggedout_test extends user_event_test {
+    protected static $recipename = 'user_loggedout';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+}
diff --git a/tests/lib/translator/user_registered_test.php b/tests/lib/translator/user_registered_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d28397864d47687dffafaae827d2218c4b31367
--- /dev/null
+++ b/tests/lib/translator/user_registered_test.php
@@ -0,0 +1,39 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace MXTranslator\Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+use \MXTranslator\Events\UserRegistered as Event;
+
+class user_registered_test extends event_test {
+    protected static $recipename = 'user_registered';
+
+    /**
+     * Sets up the tests.
+     * @override TestCase
+     */
+    public function setup() {
+        parent::setup();
+        $this->event = new Event();
+    }
+
+    protected function assert_output($input, $output) {
+        parent::assert_output($input, $output);
+        $this->assert_user($input['relateduser'], $output, 'user');
+    }
+}
diff --git a/tests/module_viewed_test.php b/tests/module_viewed_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..772bb202c61cf20726156381645ab64c93720221
--- /dev/null
+++ b/tests/module_viewed_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class module_viewed_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'page',
+            'objectid' => 1,
+            'eventname' => '\mod_page\event\course_module_viewed',
+        ]);
+    }
+}
diff --git a/tests/quiz_attempt_testcase.php b/tests/quiz_attempt_testcase.php
new file mode 100644
index 0000000000000000000000000000000000000000..efe1ce3fafc7b8b043de2afba6960fd9dcff807d
--- /dev/null
+++ b/tests/quiz_attempt_testcase.php
@@ -0,0 +1,28 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+abstract class quiz_attempt_testcase extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'quiz_attempts',
+            'objectid' => 1,
+        ]);
+    }
+}
diff --git a/tests/scorm_launched_test.php b/tests/scorm_launched_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd3a29fe1bbe5c75b7bf59735395054fd0ddb866
--- /dev/null
+++ b/tests/scorm_launched_test.php
@@ -0,0 +1,29 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class scorm_launched_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'objecttable' => 'scorm_scoes',
+            'objectid' => 1,
+            'eventname' => '\mod_scorm\event\sco_launched',
+        ]);
+    }
+}
diff --git a/tests/scorm_score_raw_testcase.php b/tests/scorm_score_raw_testcase.php
new file mode 100644
index 0000000000000000000000000000000000000000..630026954b53fe58d5fc8b66e02c9bd62f12c7ba
--- /dev/null
+++ b/tests/scorm_score_raw_testcase.php
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class scorm_score_raw_testcase extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+          'objecttable' => 'scorm_scoes_track',
+          'objectid' => 1,
+          'contextinstanceid' => 1,
+          'eventname' => '\mod_scorm\event\scoreraw_submitted',
+          'other' => 'a:3:{s:9:"attemptid";i:1;s:10:"cmielement";s:18:"cmi.core.score.raw";s:8:"cmivalue";s:3:"100";}',
+        ]);
+    }
+}
diff --git a/tests/scorm_status_testcase.php b/tests/scorm_status_testcase.php
new file mode 100644
index 0000000000000000000000000000000000000000..2fb981905f4cf86998609d9d397141937dad06b1
--- /dev/null
+++ b/tests/scorm_status_testcase.php
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class scorm_status_testcase extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+          'objecttable' => 'scorm_scoes_track',
+          'objectid' => 1,
+          'contextinstanceid' => 1,
+          'eventname' => '\mod_scorm\event\status_submitted',
+          'other' => 'a:3:{s:9:"attemptid";i:2;s:10:"cmielement";s:22:"cmi.core.lesson_status";s:8:"cmivalue";s:6:"failed";}';
+        ]);
+    }
+}
diff --git a/tests/user_loggedin_test.php b/tests/user_loggedin_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..f0a356c1511d5e9d250005ab61b269e052925003
--- /dev/null
+++ b/tests/user_loggedin_test.php
@@ -0,0 +1,27 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class user_loggedin_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\core\event\user_loggedin',
+        ]);
+    }
+}
diff --git a/tests/user_loggedout_test.php b/tests/user_loggedout_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..fa9254efa279ba49f7ea882c15b34bc61e9f7f15
--- /dev/null
+++ b/tests/user_loggedout_test.php
@@ -0,0 +1,27 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class user_loggedout_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\core\event\user_loggedout',
+        ]);
+    }
+}
diff --git a/tests/user_registered_test.php b/tests/user_registered_test.php
new file mode 100644
index 0000000000000000000000000000000000000000..3b028d623ccd48d388c33bad821d8177f0c1fbcf
--- /dev/null
+++ b/tests/user_registered_test.php
@@ -0,0 +1,27 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+class user_registered_test extends xapi_testcase {
+    protected function construct_input() {
+        return array_merge(parent::construct_input(), [
+            'eventname' => '\core\event\user_created',
+        ]);
+    }
+}
diff --git a/tests/xapi_testcase.php b/tests/xapi_testcase.php
new file mode 100644
index 0000000000000000000000000000000000000000..35ac569ca1d3c8416ef4c900b80f568378f8fee2
--- /dev/null
+++ b/tests/xapi_testcase.php
@@ -0,0 +1,93 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+namespace Tests;
+
+defined('MOODLE_INTERNAL') || die();
+
+require_once(__DIR__ . '/../vendor/autoload.php');
+
+use \XREmitter\Controller as xapi_controller;
+use \XREmitter\Tests\TestRepository as xapi_repository;
+use \XREmitter\Tests\TestRemoteLrs as xapi_remote_lrs;
+use \MXTranslator\Controller as translator_controller;
+use \LogExpander\Controller as moodle_controller;
+use \LogExpander\Tests\TestRepository as moodle_repository;
+use \Locker\XApi\Statement as LockerStatement;
+use \TinCan\Statement as TinCanStatement;
+
+abstract class xapi_testcase extends \advanced_testcase {
+    protected $xapicontroller, $moodlecontroller, $translatorcontroller, $cfg;
+
+    /**
+     * Sets up the tests.
+     * @override PhpUnitTestCase
+     */
+    public function setup() {
+        $this->cfg = (object) [
+            'wwwroot' => 'http://www.example.com',
+            'release' => '1.0.0'
+        ];
+        $this->xapicontroller = new xapi_controller(new xapi_repository(new xapi_remote_lrs('', '1.0.1', '', '')));
+        $this->moodlecontroller = new moodle_controller(new moodle_repository((object) [], $this->cfg));
+        $this->translatorcontroller = new translator_controller();
+    }
+
+    public function test_create_event() {
+        $input = $this->construct_input();
+
+        $moodleevents = $this->moodlecontroller->create_events([$input]);
+        $this->assertNotNull($moodleevents, 'Check that the events exist in the expander controller.');
+
+        // Hack to add Moodle plugin config setting for sendmbox - need to make config function.
+        $moodleevents = [array_merge(
+            $moodleevents[0],
+            ['sendmbox' => false]
+        )];
+
+        $translatorevents = $this->translatorcontroller->create_events($moodleevents);
+        $this->assertNotNull($translatorevents, 'Check that the events exist in the translator controller.');
+
+        $xapievents = $this->xapicontroller->create_events($translatorevents);
+        $this->assertNotNull($xapievents, 'Check that the events exist in the emitter controller.');
+
+        $this->assert_output($input, $xapievents);
+    }
+
+    protected function assert_output($input, $output) {
+        foreach ($output as $outputpart) {
+            $this->assert_valid_xapi_statement((new TinCanStatement($outputpart))->asVersion('1.0.0'));
+        }
+    }
+
+    protected function assert_valid_xapi_statement($output) {
+        $errors = LockerStatement::createFromJson(json_encode($output))->validate();
+        $errorsjson = json_encode(array_map(function ($error) {
+            return (string) $error;
+        }, $errors));
+        $this->assertEmpty($errors, $errorsjson);
+    }
+
+    protected function construct_input() {
+        return [
+            'userid' => '1',
+            'relateduserid' => '1',
+            'courseid' => '1',
+            'timecreated' => 1433946701,
+            'eventname' => '\core\event\course_viewed'
+        ];
+    }
+}