From 42d712bdd5569eeefbccff80c58eb7ba4c7d55a4 Mon Sep 17 00:00:00 2001 From: Max Pomazuev Date: Mon, 31 Oct 2016 23:20:32 +0500 Subject: [PATCH] Initial commit --- README.md | 9 ++ classes/condition.php | 78 ++++++++++ classes/frontend.php | 22 +++ db/events.php | 14 ++ db/install.xml | 25 +++ db/services.php | 51 +++++++ entry.php | 23 +++ externallib.php | 144 ++++++++++++++++++ lang/en/availability_examus.php | 8 + version.php | 9 ++ ...oodle-availability_examus-form-coverage.js | 6 + .../moodle-availability_examus-form-debug.js | 35 +++++ .../moodle-availability_examus-form-min.js | 1 + .../moodle-availability_examus-form.js | 35 +++++ yui/src/form/build.json | 10 ++ yui/src/form/js/form.js | 31 ++++ yui/src/form/meta/form.json | 10 ++ 17 files changed, 511 insertions(+) create mode 100644 README.md create mode 100644 classes/condition.php create mode 100644 classes/frontend.php create mode 100644 db/events.php create mode 100644 db/install.xml create mode 100644 db/services.php create mode 100644 entry.php create mode 100644 externallib.php create mode 100644 lang/en/availability_examus.php create mode 100644 version.php create mode 100644 yui/build/moodle-availability_examus-form/moodle-availability_examus-form-coverage.js create mode 100644 yui/build/moodle-availability_examus-form/moodle-availability_examus-form-debug.js create mode 100644 yui/build/moodle-availability_examus-form/moodle-availability_examus-form-min.js create mode 100644 yui/build/moodle-availability_examus-form/moodle-availability_examus-form.js create mode 100644 yui/src/form/build.json create mode 100644 yui/src/form/js/form.js create mode 100644 yui/src/form/meta/form.json diff --git a/README.md b/README.md new file mode 100644 index 0000000..b5cad4d --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +#EXAMUS MOODLE PLUGIN + +## Installation +1. Download zip, open `Administration→Plugins→Install plugins`, put zip there +2. Go to `Administration→WebServices→Manage Tokens`, Add token for service Examus for Admin User. Examus will use this token for integration + +## Usage +1. In course editing mode, `Edit settings` for module, scroll down to `Restrict access` +2. Choose `Add restrictions... → Examus` to enable proctoring for this module. diff --git a/classes/condition.php b/classes/condition.php new file mode 100644 index 0000000..6485010 --- /dev/null +++ b/classes/condition.php @@ -0,0 +1,78 @@ +contextinstanceid; + $DB->delete_records('availability_examus', array('cmid' => $cmid)); + } + + public static function course_module_updated(\core\event\course_module_updated $event) + { + global $DB; + $cmid = $event->contextinstanceid; + $course = get_course($event->courseid); + $modinfo = get_fast_modinfo($course); + $cm = $modinfo->get_cm($cmid); + + if (strpos($cm->availability, '"c":[{"type":"examus"}]') !== false) { + $users = get_enrolled_users($event->get_context()); + foreach ($users as $user) { + $entry = $DB->get_record('availability_examus', array( + 'userid' => $user->id, 'courseid' => $event->courseid, 'cmid' => $cmid)); + if (!$entry) { + $entry = new stdClass(); + $entry->userid = $user->id; + $entry->courseid = $event->courseid; + $entry->cmid = $cmid; + $entry->accesscode = md5(uniqid(rand(), 1)); + $entry->status = 'not_inited'; + $DB->insert_record('availability_examus', $entry); + } + + } + } + } + +} \ No newline at end of file diff --git a/classes/frontend.php b/classes/frontend.php new file mode 100644 index 0000000..c1f9d8e --- /dev/null +++ b/classes/frontend.php @@ -0,0 +1,22 @@ + '\core\event\course_module_deleted', + 'callback' => '\availability_examus\condition::course_module_deleted' + ], + [ + 'eventname' => '\core\event\course_module_updated', + 'callback' => '\availability_examus\condition::course_module_updated' + ] +]; diff --git a/db/install.xml b/db/install.xml new file mode 100644 index 0000000..0eca3c7 --- /dev/null +++ b/db/install.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/db/services.php b/db/services.php new file mode 100644 index 0000000..5a83d4f --- /dev/null +++ b/db/services.php @@ -0,0 +1,51 @@ +. + +/** + * Web service local plugin template external functions and service definitions. + * + * @package localwstemplate + * @copyright 2011 Jerome Mouneyrac + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// We defined the web service functions to install. +$functions = array( + 'availability_examus_user_proctored_modules' => array( + 'classname' => 'availability_examus_external', + 'methodname' => 'user_proctored_modules', + 'classpath' => 'availability/condition/examus/externallib.php', + 'description' => 'Returns modules exams for user', + 'type' => 'write', + 'services' => 'Examus', + ), + 'availability_examus_submit_proctoring_review' => array( + 'classname' => 'availability_examus_external', + 'methodname' => 'submit_proctoring_review', + 'classpath' => 'availability/condition/examus/externallib.php', + 'description' => 'Accepts review for proctoring session', + 'type' => 'write', + 'services' => 'Examus', + ) +); + +// We define the services to install as pre-build services. A pre-build service is not editable by administrator. +$services = array( + 'Examus' => array( + 'functions' => array ('availability_examus_user_proctored_modules', 'availability_examus_submit_proctoring_review'), + 'restrictedusers' => 0, + 'enabled'=>1, + ) +); diff --git a/entry.php b/entry.php new file mode 100644 index 0000000..91b7fc8 --- /dev/null +++ b/entry.php @@ -0,0 +1,23 @@ +get_record('availability_examus', array('accesscode' => $accesscode)); + +if ($entry) { + $entry->status = 'started'; + $DB->update_record('availability_examus', $entry); + $cmid = $entry->cmid; + + $_SESSION['examus'] = True; + + list($course, $cm) = get_course_and_cm_from_cmid($cmid); + + redirect($cm->url->out(false)); +} + +die; \ No newline at end of file diff --git a/externallib.php b/externallib.php new file mode 100644 index 0000000..279e29a --- /dev/null +++ b/externallib.php @@ -0,0 +1,144 @@ +libdir . "/externallib.php"); + +class availability_examus_external extends external_api +{ + + /** + * Returns description of method parameters + * @return external_function_parameters + */ + public static function user_proctored_modules_parameters() + { + return new external_function_parameters( + array('useremail' => new external_value(PARAM_TEXT, 'User Email')) + ); + } + + /** + * Returns welcome message + * @return string welcome message + */ + public static function user_proctored_modules($useremail) + { + global $USER; + global $DB; + + $params = self::validate_parameters(self::user_proctored_modules_parameters(), + array('useremail' => $useremail)); + + $context = get_context_instance(CONTEXT_USER, $USER->id); + self::validate_context($context); + + //Capability checking + //OPTIONAL but in most web service it should present + if (!has_capability('moodle/user:viewdetails', $context)) { + throw new moodle_exception('cannotviewprofile'); + } + + $user = $DB->get_record('user', array('email' => $useremail)); + + $entries = $DB->get_records('availability_examus', array('userid' => $user->id)); + + $answer = array(); + foreach ($entries as $entry) { + $course = get_course($entry->courseid); + $modinfo = get_fast_modinfo($course); + $cm = $modinfo->get_cm($entry->cmid); + $url = new moodle_url( + '/availability/condition/examus/entry.php', + array('accesscode' => $entry->accesscode)); + array_push($answer, + array( + 'id' => $entry->id, + 'name' => $cm->get_formatted_name(), + 'url' => $url->out(), + 'course_name' => $course->fullname, + 'course_id' => $course->id, + 'is_proctored' => True, + 'time_limit_mins' => 60, +// 'start' => new external_value(PARAM_TEXT, 'exam start', VALUE_OPTIONAL), +// 'end' => new external_value(PARAM_TEXT, 'exam end', VALUE_OPTIONAL), + ) + ); + } + + return array('modules' => $answer); + } + + /** + * Returns description of method result value + * @return external_description + */ + public static function user_proctored_modules_returns() + { + return new external_single_structure( + array('modules' => new external_multiple_structure( + new external_single_structure( + array( + 'id' => new external_value(PARAM_INT, 'exam id'), + 'name' => new external_value(PARAM_TEXT, 'exam name'), + 'url' => new external_value(PARAM_TEXT, 'exam url'), + 'course_name' => new external_value(PARAM_TEXT, 'exam course name', VALUE_OPTIONAL), + 'time_limit_mins' => new external_value(PARAM_INT, 'exxam duration', VALUE_OPTIONAL), + 'is_proctored' => new external_value(PARAM_BOOL, 'exam proctored'), + 'start' => new external_value(PARAM_TEXT, 'exam start', VALUE_OPTIONAL), + 'end' => new external_value(PARAM_TEXT, 'exam end', VALUE_OPTIONAL), + ), 'module') + ),) + ); + } + + + /** + * Returns description of method parameters + * @return external_function_parameters + */ + public static function submit_proctoring_review_parameters() + { + return new external_function_parameters( + array('accesscode' => new external_value(PARAM_TEXT, 'Access Code'), + 'review_link' => new external_value(PARAM_TEXT, 'Link to review page'), + 'status' => new external_value(PARAM_TEXT, 'Status of review')) + ); + } + + /** + * Returns welcome message + * @return string welcome message + */ + public static function submit_proctoring_review($accesscode, $review_link, $status) + { + global $DB; + + $params = self::validate_parameters(self::submit_proctoring_review_parameters(), + array('accesscode' => $accesscode, 'review_link' => $review_link, 'status' => $status)); + + $entry = $DB->get_record('availability_examus', array('accesscode' => $accesscode)); + + if ($entry) { + $entry->review_link = $review_link; + $entry->status = $status; + + $DB->update_record('availability_examus', $entry); + return array('success' => True, 'error'=>null); + } + return array('success' => False, 'error'=>'Entry was not found'); + + } + + /** + * Returns description of method result value + * @return external_description + */ + public static function submit_proctoring_review_returns() + { + return new external_single_structure( + array( + 'success' => new external_value(PARAM_BOOL, 'request success status'), + 'error' => new external_value(PARAM_TEXT, 'error message') + ) + ); + } +} diff --git a/lang/en/availability_examus.php b/lang/en/availability_examus.php new file mode 100644 index 0000000..94b5059 --- /dev/null +++ b/lang/en/availability_examus.php @@ -0,0 +1,8 @@ +component = 'availability_examus'; +$plugin->version = 2016103100; +$plugin->release = 'v3.1-r1'; +$plugin->requires = 2016052300; +$plugin->maturity = MATURITY_STABLE; diff --git a/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-coverage.js b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-coverage.js new file mode 100644 index 0000000..2810548 --- /dev/null +++ b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-coverage.js @@ -0,0 +1,6 @@ +if (typeof __coverage__ === 'undefined') { __coverage__ = {}; } +if (!__coverage__['build/moodle-availability_examus-form/moodle-availability_examus-form.js']) { + __coverage__['build/moodle-availability_examus-form/moodle-availability_examus-form.js'] = {"path":"build/moodle-availability_examus-form/moodle-availability_examus-form.js","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0},"b":{"1":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":43},"end":{"line":1,"column":62}}},"2":{"name":"(anonymous_2)","line":21,"loc":{"start":{"line":21,"column":37},"end":{"line":21,"column":52}}},"3":{"name":"(anonymous_3)","line":29,"loc":{"start":{"line":29,"column":39},"end":{"line":29,"column":61}}},"4":{"name":"(anonymous_4)","line":32,"loc":{"start":{"line":32,"column":40},"end":{"line":32,"column":63}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":35,"column":90}},"2":{"start":{"line":9,"column":0},"end":{"line":9,"column":52}},"3":{"start":{"line":11,"column":0},"end":{"line":11,"column":66}},"4":{"start":{"line":21,"column":0},"end":{"line":27,"column":2}},"5":{"start":{"line":22,"column":4},"end":{"line":22,"column":44}},"6":{"start":{"line":23,"column":4},"end":{"line":23,"column":56}},"7":{"start":{"line":24,"column":4},"end":{"line":24,"column":60}},"8":{"start":{"line":26,"column":4},"end":{"line":26,"column":16}},"9":{"start":{"line":29,"column":0},"end":{"line":30,"column":2}},"10":{"start":{"line":32,"column":0},"end":{"line":33,"column":2}}},"branchMap":{"1":{"line":9,"type":"binary-expr","locations":[{"start":{"line":9,"column":24},"end":{"line":9,"column":45}},{"start":{"line":9,"column":49},"end":{"line":9,"column":51}}]}},"code":["(function () { YUI.add('moodle-availability_examus-form', function (Y, NAME) {","","/*global M*/","/**"," * JavaScript for form editing profile conditions."," *"," * @module moodle-availability_examus-form"," */","M.availability_examus = M.availability_examus || {};","","M.availability_examus.form = Y.Object(M.core_availability.plugin);","","// M.availability_examus.form.initInner = function(param) {","// // The 'param' variable is the parameter passed through from PHP (you","// // can have more than one if required).","//","// // Using the PHP code above it'll show 'The param was: frog'.","// console.log('The param was: ' + param);","// };","","M.availability_examus.form.getNode = function(json) {"," var strings = M.str.availability_examus;"," var html = '';"," var node = Y.Node.create(' ' + html + ' ');",""," return node;","};","","M.availability_examus.form.fillValue = function(value, node) {","};","","M.availability_examus.form.fillErrors = function(errors, node) {","};","","}, '@VERSION@', {\"requires\": [\"base\", \"node\", \"event\", \"moodle-core_availability-form\"]});","","}());"]}; +} +var __cov_VkxrC3bnPgMAADDnSvyZqQ = __coverage__['build/moodle-availability_examus-form/moodle-availability_examus-form.js']; +__cov_VkxrC3bnPgMAADDnSvyZqQ.s['1']++;YUI.add('moodle-availability_examus-form',function(Y,NAME){__cov_VkxrC3bnPgMAADDnSvyZqQ.f['1']++;__cov_VkxrC3bnPgMAADDnSvyZqQ.s['2']++;M.availability_examus=(__cov_VkxrC3bnPgMAADDnSvyZqQ.b['1'][0]++,M.availability_examus)||(__cov_VkxrC3bnPgMAADDnSvyZqQ.b['1'][1]++,{});__cov_VkxrC3bnPgMAADDnSvyZqQ.s['3']++;M.availability_examus.form=Y.Object(M.core_availability.plugin);__cov_VkxrC3bnPgMAADDnSvyZqQ.s['4']++;M.availability_examus.form.getNode=function(json){__cov_VkxrC3bnPgMAADDnSvyZqQ.f['2']++;__cov_VkxrC3bnPgMAADDnSvyZqQ.s['5']++;var strings=M.str.availability_examus;__cov_VkxrC3bnPgMAADDnSvyZqQ.s['6']++;var html='';__cov_VkxrC3bnPgMAADDnSvyZqQ.s['7']++;var node=Y.Node.create(' '+html+' ');__cov_VkxrC3bnPgMAADDnSvyZqQ.s['8']++;return node;};__cov_VkxrC3bnPgMAADDnSvyZqQ.s['9']++;M.availability_examus.form.fillValue=function(value,node){__cov_VkxrC3bnPgMAADDnSvyZqQ.f['3']++;};__cov_VkxrC3bnPgMAADDnSvyZqQ.s['10']++;M.availability_examus.form.fillErrors=function(errors,node){__cov_VkxrC3bnPgMAADDnSvyZqQ.f['4']++;};},'@VERSION@',{'requires':['base','node','event','moodle-core_availability-form']}); diff --git a/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-debug.js b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-debug.js new file mode 100644 index 0000000..1ed0ca0 --- /dev/null +++ b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-debug.js @@ -0,0 +1,35 @@ +YUI.add('moodle-availability_examus-form', function (Y, NAME) { + +/*global M*/ +/** + * JavaScript for form editing profile conditions. + * + * @module moodle-availability_examus-form + */ +M.availability_examus = M.availability_examus || {}; + +M.availability_examus.form = Y.Object(M.core_availability.plugin); + +// M.availability_examus.form.initInner = function(param) { +// // The 'param' variable is the parameter passed through from PHP (you +// // can have more than one if required). +// +// // Using the PHP code above it'll show 'The param was: frog'. +// console.log('The param was: ' + param); +// }; + +M.availability_examus.form.getNode = function(json) { + var strings = M.str.availability_examus; + var html = ''; + var node = Y.Node.create(' ' + html + ' '); + + return node; +}; + +M.availability_examus.form.fillValue = function(value, node) { +}; + +M.availability_examus.form.fillErrors = function(errors, node) { +}; + +}, '@VERSION@', {"requires": ["base", "node", "event", "moodle-core_availability-form"]}); diff --git a/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-min.js b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-min.js new file mode 100644 index 0000000..8938282 --- /dev/null +++ b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form-min.js @@ -0,0 +1 @@ +YUI.add("moodle-availability_examus-form",function(e,t){M.availability_examus=M.availability_examus||{},M.availability_examus.form=e.Object(M.core_availability.plugin),M.availability_examus.form.getNode=function(t){var n=M.str.availability_examus,r="",i=e.Node.create(" "+r+" ");return i},M.availability_examus.form.fillValue=function(e,t){},M.availability_examus.form.fillErrors=function(e,t){}},"@VERSION@",{requires:["base","node","event","moodle-core_availability-form"]}); diff --git a/yui/build/moodle-availability_examus-form/moodle-availability_examus-form.js b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form.js new file mode 100644 index 0000000..1ed0ca0 --- /dev/null +++ b/yui/build/moodle-availability_examus-form/moodle-availability_examus-form.js @@ -0,0 +1,35 @@ +YUI.add('moodle-availability_examus-form', function (Y, NAME) { + +/*global M*/ +/** + * JavaScript for form editing profile conditions. + * + * @module moodle-availability_examus-form + */ +M.availability_examus = M.availability_examus || {}; + +M.availability_examus.form = Y.Object(M.core_availability.plugin); + +// M.availability_examus.form.initInner = function(param) { +// // The 'param' variable is the parameter passed through from PHP (you +// // can have more than one if required). +// +// // Using the PHP code above it'll show 'The param was: frog'. +// console.log('The param was: ' + param); +// }; + +M.availability_examus.form.getNode = function(json) { + var strings = M.str.availability_examus; + var html = ''; + var node = Y.Node.create(' ' + html + ' '); + + return node; +}; + +M.availability_examus.form.fillValue = function(value, node) { +}; + +M.availability_examus.form.fillErrors = function(errors, node) { +}; + +}, '@VERSION@', {"requires": ["base", "node", "event", "moodle-core_availability-form"]}); diff --git a/yui/src/form/build.json b/yui/src/form/build.json new file mode 100644 index 0000000..c4af34d --- /dev/null +++ b/yui/src/form/build.json @@ -0,0 +1,10 @@ +{ + "name": "moodle-availability_examus-form", + "builds": { + "moodle-availability_examus-form": { + "jsfiles": [ + "form.js" + ] + } + } +} \ No newline at end of file diff --git a/yui/src/form/js/form.js b/yui/src/form/js/form.js new file mode 100644 index 0000000..8b6b340 --- /dev/null +++ b/yui/src/form/js/form.js @@ -0,0 +1,31 @@ +/*global M*/ +/** + * JavaScript for form editing profile conditions. + * + * @module moodle-availability_examus-form + */ +M.availability_examus = M.availability_examus || {}; + +M.availability_examus.form = Y.Object(M.core_availability.plugin); + +// M.availability_examus.form.initInner = function(param) { +// // The 'param' variable is the parameter passed through from PHP (you +// // can have more than one if required). +// +// // Using the PHP code above it'll show 'The param was: frog'. +// console.log('The param was: ' + param); +// }; + +M.availability_examus.form.getNode = function(json) { + var strings = M.str.availability_examus; + var html = ''; + var node = Y.Node.create(' ' + html + ' '); + + return node; +}; + +M.availability_examus.form.fillValue = function(value, node) { +}; + +M.availability_examus.form.fillErrors = function(errors, node) { +}; \ No newline at end of file diff --git a/yui/src/form/meta/form.json b/yui/src/form/meta/form.json new file mode 100644 index 0000000..f8e5d18 --- /dev/null +++ b/yui/src/form/meta/form.json @@ -0,0 +1,10 @@ +{ + "moodle-availability_examus-form": { + "requires": [ + "base", + "node", + "event", + "moodle-core_availability-form" + ] + } +} \ No newline at end of file