diff --git a/CHANGELOG.md b/CHANGELOG.md index d101486..1928317 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +### Date: 2024-November-25 +### Release: v2024112501 + +#### Fixed a bug with Anonymous Marking + +Previously, if a student submitted with anonymous marking enabled for the assignment, their email would sometimes be visible when viewing the online similarity report. This has now been fixed. + +#### Streamlined Eula Workflow + +In line with our other plagiarism plugin we have removed the Eula decline button, simplifying the Eula acceptance workflow. + +#### Added Userlist Provider for Privacy Compliance + +Previously we were missing a userlist provider for this plugin. We have now added this. + +--- + ### Date: 2023-June-29 ### Release: v2023062901 (Moodle Integration Only graphic) diff --git a/README.md b/README.md index 3a82ffe..27fef9f 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Useful Links Installation - -Before installing this plugin firstly make sure you are logged in as an Administrator and that you are using Moodle 3.5 or higher. +Before installing this plugin firstly make sure you are logged in as an Administrator and that you are using Moodle 4.1 or higher. To install, all you need to do is copy all the files into the plagiarism/turnitinsim directory on your Moodle installation. You should then go to `"Site Administration" > "Notifications"` and follow the on screen instructions. diff --git a/amd/build/eula_response.min.js b/amd/build/eula_response.min.js index 1a43ea2..b1b0749 100644 --- a/amd/build/eula_response.min.js +++ b/amd/build/eula_response.min.js @@ -1,2 +1,2 @@ -define ("plagiarism_turnitinsim/eula_response",["jquery","core/str"],function(a,b){return{eulaResponse:function eulaResponse(){a(document).ready(function(){if(a("#turnitinsim_eulacontainer").length){a("input[name=submitbutton]").prop("disabled","disabled")}});a(document).on("click","#turnitinsim_eula_accept",function(){a("input[name=submitbutton]").prop("disabled","");a.ajax({type:"POST",url:M.cfg.wwwroot+"/plagiarism/turnitinsim/ajax/eula_response.php",dataType:"text",data:{action:"accept_eula",sesskey:M.cfg.sesskey},success:function success(){b.get_string("eulaaccepted","plagiarism_turnitinsim").done(function(c){a(".turnitinsim_eulacontainer").hide().html(c).fadeIn();b.get_string("submissiondisplaystatus:queued","plagiarism_turnitinsim").done(function(b){a(".tii_status_text").html(b)})})}})});a(document).on("click","#turnitinsim_eula_decline",function(){b.get_string("euladeclined","plagiarism_turnitinsim").done(function(b){a(".turnitinsim_eulacontainer").hide().html(b).fadeIn()});a("input[name=submitbutton]").prop("disabled","")})}}}); -//# sourceMappingURL=eula_response.min.js.map +define(["jquery","core/str"],function($,str){return{eulaResponse:function(){$(document).ready(function(){$("#turnitinsim_eulacontainer").length&&($("input[name=submitbutton]").prop("disabled","disabled"),$(".editsubmissionform").hide(),$(".mform").hide())}),$(document).on("click","#turnitinsim_eula_accept",function(){$("input[name=submitbutton]").prop("disabled",""),$.ajax({type:"POST",url:M.cfg.wwwroot+"/plagiarism/turnitinsim/ajax/eula_response.php",dataType:"text",data:{action:"accept_eula",sesskey:M.cfg.sesskey},success:function(){str.get_string("eulaaccepted","plagiarism_turnitinsim").done(function(text){$(".turnitinsim_eulacontainer").hide().html(text).fadeIn(),str.get_string("submissiondisplaystatus:queued","plagiarism_turnitinsim").done(function(text){$(".tii_status_text").html(text),$(".editsubmissionform").show(),$(".mform").show()})})}})}),$(document).on("click","#turnitinsim_eula_decline",function(){str.get_string("euladeclined","plagiarism_turnitinsim").done(function(text){$(".turnitinsim_eulacontainer").hide().html(text).fadeIn()}),$("input[name=submitbutton]").prop("disabled","")})}}}); +//# sourceMappingURL=eula_response.min.js.map \ No newline at end of file diff --git a/amd/build/eula_response.min.js.map b/amd/build/eula_response.min.js.map index b95491c..ceb0ac3 100644 --- a/amd/build/eula_response.min.js.map +++ b/amd/build/eula_response.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/eula_response.js"],"names":["define","$","str","eulaResponse","document","ready","length","prop","on","ajax","type","url","M","cfg","wwwroot","dataType","data","action","sesskey","success","get_string","done","text","hide","html","fadeIn"],"mappings":"AA4BAA,OAAM,wCAAC,CAAC,QAAD,CAAW,UAAX,CAAD,CAAyB,SAASC,CAAT,CAAYC,CAAZ,CAAiB,CAC5C,MAAO,CACHC,YAAY,CAAE,uBAAW,CACrBF,CAAC,CAACG,QAAD,CAAD,CAAYC,KAAZ,CAAkB,UAAW,CACzB,GAAIJ,CAAC,CAAC,4BAAD,CAAD,CAAgCK,MAApC,CAA4C,CACxCL,CAAC,CAAC,0BAAD,CAAD,CAA8BM,IAA9B,CAAmC,UAAnC,CAA+C,UAA/C,CACH,CACJ,CAJD,EAMAN,CAAC,CAACG,QAAD,CAAD,CAAYI,EAAZ,CAAe,OAAf,CAAwB,0BAAxB,CAAoD,UAAW,CAC3DP,CAAC,CAAC,0BAAD,CAAD,CAA8BM,IAA9B,CAAmC,UAAnC,CAA+C,EAA/C,EAGAN,CAAC,CAACQ,IAAF,CAAO,CACHC,IAAI,CAAE,MADH,CAEHC,GAAG,CAAEC,CAAC,CAACC,GAAF,CAAMC,OAAN,CAAgB,gDAFlB,CAGHC,QAAQ,CAAE,MAHP,CAIHC,IAAI,CAAE,CAACC,MAAM,CAAE,aAAT,CAAwBC,OAAO,CAAEN,CAAC,CAACC,GAAF,CAAMK,OAAvC,CAJH,CAKHC,OAAO,CAAE,kBAAW,CAChBjB,CAAG,CAACkB,UAAJ,CAAe,cAAf,CAA+B,wBAA/B,EAAyDC,IAAzD,CAA8D,SAASC,CAAT,CAAe,CACzErB,CAAC,CAAC,4BAAD,CAAD,CAAgCsB,IAAhC,GAAuCC,IAAvC,CAA4CF,CAA5C,EAAkDG,MAAlD,GAEAvB,CAAG,CAACkB,UAAJ,CAAe,gCAAf,CAAiD,wBAAjD,EAA2EC,IAA3E,CAAgF,SAASC,CAAT,CAAe,CAC3FrB,CAAC,CAAC,kBAAD,CAAD,CAAsBuB,IAAtB,CAA2BF,CAA3B,CACH,CAFD,CAGH,CAND,CAOH,CAbE,CAAP,CAeH,CAnBD,EAqBArB,CAAC,CAACG,QAAD,CAAD,CAAYI,EAAZ,CAAe,OAAf,CAAwB,2BAAxB,CAAqD,UAAW,CAC5DN,CAAG,CAACkB,UAAJ,CAAe,cAAf,CAA+B,wBAA/B,EAAyDC,IAAzD,CAA8D,SAASC,CAAT,CAAe,CACzErB,CAAC,CAAC,4BAAD,CAAD,CAAgCsB,IAAhC,GAAuCC,IAAvC,CAA4CF,CAA5C,EAAkDG,MAAlD,EACH,CAFD,EAIAxB,CAAC,CAAC,0BAAD,CAAD,CAA8BM,IAA9B,CAAmC,UAAnC,CAA+C,EAA/C,CACH,CAND,CAOH,CApCE,CAsCV,CAvCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Javascript controller for handling the EULA response.\n *\n * @package plagiarism_turnitinsim\n * @copyright 2018 Turnitin\n * @author John McGettrick \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * @module plagiarism_turnitinsim/handleEulaResponse\n */\n\ndefine(['jquery', 'core/str'], function($, str) {\n return {\n eulaResponse: function() {\n $(document).ready(function() {\n if ($(\"#turnitinsim_eulacontainer\").length) {\n $('input[name=submitbutton]').prop('disabled', 'disabled');\n }\n });\n\n $(document).on('click', '#turnitinsim_eula_accept', function() {\n $('input[name=submitbutton]').prop('disabled', '');\n\n // Hide the EULA link.\n $.ajax({\n type: \"POST\",\n url: M.cfg.wwwroot + \"/plagiarism/turnitinsim/ajax/eula_response.php\",\n dataType: \"text\",\n data: {action: \"accept_eula\", sesskey: M.cfg.sesskey},\n success: function() {\n str.get_string('eulaaccepted', 'plagiarism_turnitinsim').done(function(text) {\n $('.turnitinsim_eulacontainer').hide().html(text).fadeIn();\n\n str.get_string('submissiondisplaystatus:queued', 'plagiarism_turnitinsim').done(function(text) {\n $('.tii_status_text').html(text);\n });\n });\n }\n });\n });\n\n $(document).on('click', '#turnitinsim_eula_decline', function() {\n str.get_string('euladeclined', 'plagiarism_turnitinsim').done(function(text) {\n $('.turnitinsim_eulacontainer').hide().html(text).fadeIn();\n });\n\n $('input[name=submitbutton]').prop('disabled', '');\n });\n }\n };\n});"],"file":"eula_response.min.js"} \ No newline at end of file +{"version":3,"sources":["amd/src/eula_response.js"],"names":["define","$","str","eulaResponse","document","ready","length","prop","hide","on","ajax","type","url","M","cfg","wwwroot","dataType","data","action","sesskey","success","get_string","done","text","html","fadeIn","show"],"mappings":"AA4BAA,OAAO,CAAC,SAAU,YAAa,SAASC,EAAGC,KACvC,MAAO,CACHC,aAAc,WACVF,EAAEG,QAAQ,EAAEC,MAAM,WACVJ,EAAE,4BAA4B,EAAEK,SAChCL,EAAE,0BAA0B,EAAEM,KAAK,WAAY,UAAU,EACzDN,EAAE,qBAAqB,EAAEO,KAAK,EAC9BP,EAAE,QAAQ,EAAEO,KAAK,EAEzB,CAAC,EAEDP,EAAEG,QAAQ,EAAEK,GAAG,QAAS,2BAA4B,WAChDR,EAAE,0BAA0B,EAAEM,KAAK,WAAY,EAAE,EAGjDN,EAAES,KAAK,CACHC,KAAM,OACNC,IAAKC,EAAEC,IAAIC,QAAU,iDACrBC,SAAU,OACVC,KAAM,CAACC,OAAQ,cAAeC,QAASN,EAAEC,IAAIK,OAAO,EACpDC,QAAS,WACLlB,IAAImB,WAAW,eAAgB,wBAAwB,EAAEC,KAAK,SAASC,MACnEtB,EAAE,4BAA4B,EAAEO,KAAK,EAAEgB,KAAKD,IAAI,EAAEE,OAAO,EAEzDvB,IAAImB,WAAW,iCAAkC,wBAAwB,EAAEC,KAAK,SAASC,MACrFtB,EAAE,kBAAkB,EAAEuB,KAAKD,IAAI,EAC/BtB,EAAE,qBAAqB,EAAEyB,KAAK,EAC9BzB,EAAE,QAAQ,EAAEyB,KAAK,CACrB,CAAC,CACL,CAAC,CACL,CACJ,CAAC,CACL,CAAC,EAEDzB,EAAEG,QAAQ,EAAEK,GAAG,QAAS,4BAA6B,WACjDP,IAAImB,WAAW,eAAgB,wBAAwB,EAAEC,KAAK,SAASC,MACnEtB,EAAE,4BAA4B,EAAEO,KAAK,EAAEgB,KAAKD,IAAI,EAAEE,OAAO,CAC7D,CAAC,EAEDxB,EAAE,0BAA0B,EAAEM,KAAK,WAAY,EAAE,CACrD,CAAC,CACL,CACJ,CACJ,CAAC"} \ No newline at end of file diff --git a/amd/src/eula_response.js b/amd/src/eula_response.js index 318df68..6470254 100644 --- a/amd/src/eula_response.js +++ b/amd/src/eula_response.js @@ -32,6 +32,8 @@ define(['jquery', 'core/str'], function($, str) { $(document).ready(function() { if ($("#turnitinsim_eulacontainer").length) { $('input[name=submitbutton]').prop('disabled', 'disabled'); + $('.editsubmissionform').hide(); + $('.mform').hide(); } }); @@ -50,6 +52,8 @@ define(['jquery', 'core/str'], function($, str) { str.get_string('submissiondisplaystatus:queued', 'plagiarism_turnitinsim').done(function(text) { $('.tii_status_text').html(text); + $('.editsubmissionform').show(); + $('.mform').show(); }); }); } diff --git a/backup/moodle2/backup_plagiarism_turnitinsim_plugin.class.php b/backup/moodle2/backup_plagiarism_turnitinsim_plugin.class.php index b5e434d..5972951 100644 --- a/backup/moodle2/backup_plagiarism_turnitinsim_plugin.class.php +++ b/backup/moodle2/backup_plagiarism_turnitinsim_plugin.class.php @@ -38,6 +38,8 @@ class backup_plagiarism_turnitinsim_plugin extends backup_plagiarism_plugin { * @throws base_element_struct_exception */ protected function define_module_plugin_structure() { + global $DB; + $plugin = $this->get_plugin_element(); $pluginelement = new backup_nested_element($this->get_recommended_name()); @@ -71,18 +73,23 @@ protected function define_module_plugin_structure() { $pluginelement->add_child($submissions); $submissions->add_child($submission); - // Get submission details along with contenthash from files table. - $submission->set_source_sql( + // Get submission details + $submissiondetails = $DB->get_records_sql( 'SELECT PTS.userid, PTS.turnitinid, PTS.status, PTS.identifier, PTS.itemid, PTS.type, PTS.submittedtime, PTS.togenerate, PTS.generationtime, PTS.overallscore, PTS.requestedtime, - PTS.errormessage, F.contenthash + PTS.errormessage FROM {plagiarism_turnitinsim_sub} PTS - LEFT JOIN {files} F - ON PTS.identifier = F.pathnamehash WHERE PTS.cm = ? ', array(backup::VAR_PARENTID) ); + // Use file API to get content hash + $fs = get_file_storage(); + $file = $fs->get_file_by_hash($submissiondetails->identifier); + $submissiondetails['contenthash'] = $file->contenthash; + + $submission->set_source_array($submissiondetails); + // Backup users who have submitted to this module. $users = new backup_nested_element('turnitinsim_usrs'); $user = new backup_nested_element( diff --git a/classes/defaults_form.class.php b/classes/defaults_form.class.php index 23b84fb..850897f 100644 --- a/classes/defaults_form.class.php +++ b/classes/defaults_form.class.php @@ -43,7 +43,7 @@ public function definition () { $mform =& $this->_form; $plugin = new plagiarism_plugin_turnitinsim(); - $plugin->get_form_elements_module($mform, context_system::instance()); + $plugin->add_elements_to_settings_form($mform, context_system::instance()); $this->add_action_buttons(true); } diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index c1442d8..febf8ae 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -28,8 +28,10 @@ defined('MOODLE_INTERNAL') || die(); use core_privacy\local\metadata\collection; +use core_privacy\local\request\approved_userlist; use core_privacy\local\request\contextlist; use core_privacy\local\request\helper; +use core_privacy\local\request\userlist; use core_privacy\local\request\writer; /** @@ -38,6 +40,7 @@ class provider implements // This plugin does store personal user data. \core_privacy\local\metadata\provider, + \core_privacy\local\request\core_userlist_provider, \core_plagiarism\privacy\plagiarism_provider { // This trait must be included to provide the relevant polyfill for the metadata provider. @@ -204,4 +207,71 @@ public static function _delete_plagiarism_for_user($userid, \context $context) { $DB->delete_records('plagiarism_turnitinsim_sub', ['userid' => $userid]); $DB->delete_records('plagiarism_turnitinsim_users', ['userid' => $userid]); } + + /** + * Get a list of users who have data within a context. + * + * @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination. + */ + public static function get_users_in_context(userlist $userlist) { + $context = $userlist->get_context(); + + if ($context->contextlevel != CONTEXT_MODULE) { + return; + } + + $sql = "SELECT pts.userid + FROM {plagiarism_turnitinsim_sub} pts + JOIN {course_modules} c + ON pts.cm = c.id + JOIN {modules} m + ON m.id = c.module AND m.name = :modname + WHERE c.id = :cmid"; + + $params = [ + 'modname' => 'plagiarism_turnitinsim', + 'cmid' => $context->instanceid + ]; + + $userlist->add_from_sql('userid', $sql, $params); + } + + /** + * Delete data for multiple users within a single context. + * + * @param approved_userlist $userlist The approved context and user information to delete information for. + */ + public static function delete_data_for_users(approved_userlist $userlist) { + global $DB; + + $context = $userlist->get_context(); + + if ($context->contextlevel != CONTEXT_MODULE) { + return; + } + + $userids = $userlist->get_userids(); + + list($insql, $inparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED); + + $sql1 = "SELECT pts.id + FROM {plagiarism_turnitinsim_sub} pts + JOIN {course_modules} c + ON pts.cm = c.id + JOIN {modules} m + ON m.id = c.module AND m.name = :modname + WHERE pts.userid $insql + AND c.id = :cmid"; + + $params = [ + 'modname' => 'plagiarism_turnitinsim', + 'cmid' => $context->instanceid + ]; + + $params = array_merge($params, $inparams); + + $attempt = $DB->get_fieldset_sql($sql1, $params); + + $DB->delete_records_list('plagiarism_turnitinsim_sub', 'id', array_values($attempt)); + } } \ No newline at end of file diff --git a/classes/quiz.class.php b/classes/quiz.class.php index 99f1b4f..c4f96e5 100644 --- a/classes/quiz.class.php +++ b/classes/quiz.class.php @@ -57,7 +57,7 @@ public function get_onlinetext($itemid) { public function get_itemid($params) { global $DB; - $item = $DB->get_record_sql('SELECT DISTINCT(q.id) FROM {question_attempt_steps} s + $item = $DB->get_record_sql('SELECT DISTINCT(q.uniqueid) FROM {question_attempt_steps} s RIGHT JOIN {question_attempts} a ON s.questionattemptid = a.id RIGHT JOIN {quiz_attempts} q @@ -69,7 +69,7 @@ public function get_itemid($params) { array($params->moduleid, $params->userid, $params->onlinetext, 'finished') ); - return ($item) ? $item->id : 0; + return ($item) ? $item->uniqueid : 0; } /** diff --git a/classes/submission.class.php b/classes/submission.class.php index 2fd0332..78ec735 100644 --- a/classes/submission.class.php +++ b/classes/submission.class.php @@ -140,6 +140,11 @@ class plagiarism_turnitinsim_submission { */ public $tsrequest; + /** + * @var object The plugin object. + */ + public $plugin; + /** * plagiarism_turnitinsim_submission constructor. * @@ -152,7 +157,7 @@ public function __construct(plagiarism_turnitinsim_request $tsrequest = null, $i $this->setid($id); $this->tsrequest = ($tsrequest) ? $tsrequest : new plagiarism_turnitinsim_request(); - $this->plagiarism_plugin_turnitinsim = new plagiarism_plugin_turnitinsim(); + $this->plugin = new plagiarism_plugin_turnitinsim(); if (!empty($id)) { $submission = $DB->get_record('plagiarism_turnitinsim_sub', array('id' => $id)); @@ -209,7 +214,7 @@ public function calculate_generation_time($generated = false) { return; } - $plagiarismsettings = $this->plagiarism_plugin_turnitinsim->get_settings($cm->id); + $plagiarismsettings = $this->plugin->get_settings($cm->id); // Create module object. $moduleclass = 'plagiarism_turnitinsim_'.$cm->modname; @@ -290,7 +295,7 @@ public function build_user_array_entry($user) { $userdata = array('id' => $tsuser->get_turnitinid()); - if (!get_config('plagiarism_turnitinsim', 'turnitinhideidentity')) { + if (!$this->is_submission_anonymous()) { $userdata["family_name"] = $user->lastname; $userdata["given_name"] = $user->firstname; $userdata["email"] = $user->email; @@ -737,8 +742,7 @@ public function send_digital_receipts($filename) { */ public function request_turnitin_report_generation($regenerateonduedate = false) { // Get module settings. - $plugin = new plagiarism_plugin_turnitinsim(); - $modulesettings = $plugin->get_settings($this->getcm()); + $modulesettings = $this->plugin->get_settings($this->getcm()); $cm = get_coursemodule_from_id('', $this->getcm()); // Create module helper object. @@ -967,7 +971,7 @@ public function create_report_viewer_permissions() { return array( 'may_view_submission_full_source' => (!empty($turnitinviewerviewfullsource)) ? true : false, 'may_view_match_submission_info' => (!empty($turnitinviewermatchsubinfo)) && - !$this->is_submission_anonymous() ? true : false, + !$this->is_submission_anonymous(), 'may_view_save_viewer_changes' => (!empty($turnitinviewersavechanges)) ? true : false ); } @@ -1060,18 +1064,13 @@ public function is_submission_anonymous() { $cm = get_coursemodule_from_id('', $this->getcm()); $moduledata = $DB->get_record($cm->modname, array('id' => $cm->instance)); - $blindmarkingon = !empty($moduledata->blindmarking); - $identitiesrevealed = !empty($moduledata->revealidentities); - - // Return true if hide identities is on, otherwise go by module blind marking settings. + // Check if Hide Student's Identity is set at the plugin settings level, otherwise go by module blind marking settings. $turnitinhideidentity = get_config('plagiarism_turnitinsim', 'turnitinhideidentity'); - if ($turnitinhideidentity) { - $anon = true; - } else { - $anon = $blindmarkingon && !$identitiesrevealed; - } - return $anon; + // Check if blind marking is on and revealidentities is not set yet. + $blindon = (!empty($moduledata->blindmarking) && empty($moduledata->revealidentities)); + + return $blindon || $turnitinhideidentity; } /** diff --git a/classes/task.class.php b/classes/task.class.php index 1019cc4..7abc7a9 100644 --- a/classes/task.class.php +++ b/classes/task.class.php @@ -51,6 +51,8 @@ class plagiarism_turnitinsim_task { * @var plagiarism_turnitinsim_settings Settings object. */ public $tssettings; + + protected $tseula; /** * plagiarism_turnitinsim_task constructor. @@ -273,14 +275,14 @@ public function check_latest_eula_version() { $neweulaurl = (empty($response->url)) ? '' : $response->url; // Update EULA version and url if necessary. - if ($currenteulaversion != $neweulaversion) { + if (!empty($response->version) && $currenteulaversion != $neweulaversion) { set_config('turnitin_eula_version', $response->version, 'plagiarism_turnitinsim'); set_config('turnitin_eula_url', $response->url, 'plagiarism_turnitinsim'); // Notify all users linked to Turnitin that there is a new EULA to accept. $message = new new_eula(); $message->send_message(); - } else if ($currenteulaurl != $neweulaurl){ + } else if (!empty($response->url) && $currenteulaurl != $neweulaurl){ // This runs if there is no new EULA version, but a user still needs an updated EULA URL for their supported language. // We do not want to notify all users that there is a new EULA url for the translation. set_config('turnitin_eula_version', $response->version, 'plagiarism_turnitinsim'); diff --git a/lib.php b/lib.php index 0198d80..d64dc79 100644 --- a/lib.php +++ b/lib.php @@ -45,22 +45,16 @@ class plagiarism_plugin_turnitinsim extends plagiarism_plugin { /** - * Get the fields to be used in the form to configure each module's Turnitin settings. - * - * TODO: This code needs to be moved for 4.3 as the method will be completely removed from core. - * See https://tracker.moodle.org/browse/MDL-67526 + * Add settings form elements to either defaults form or assignment settings form * * @param object $mform - Moodle form * @param object $context - current context * @param string $modulename - Name of the module - * @return void of settings fields. + * @return void * @throws coding_exception * @throws dml_exception */ - public function get_form_elements_module($mform, $context, $modulename = "") { - // This is a bit of a hack and untidy way to ensure the form elements aren't displayed twice. - // TODO: Remove once this method is removed. - + public function add_elements_to_settings_form($mform, $context, $modulename = "") { $canconfigureplugin = false; static $hassettings; @@ -137,30 +131,10 @@ public function get_form_elements_module($mform, $context, $modulename = "") { $mform->setDefault($element, $value); } } - // TODO: Remove once this method is removed. + $hassettings = true; } - /** - * Save the data associated with the plugin from the module's mod_form. - * - * TODO: This code needs to be moved for 4.3 as the method will be completely removed from core. - * See https://tracker.moodle.org/browse/MDL-67526 - * - * @param object $data the form data to save - * @throws dml_exception - */ - public function save_form_elements($data) { - - $moduletiienabled = $moduletiienabled = get_config('plagiarism_turnitinsim', 'turnitinmodenabled'.$data->modulename); - if (empty($moduletiienabled)) { - return; - } - - $form = new plagiarism_turnitinsim_settings(); - $form->save_module_settings($data); - } - /** * Hook to allow report score and link to be displayed beside a submission. * @@ -510,7 +484,7 @@ public function print_disclosure($cmid, $submissiontype = 'file') { array('class' => 'turnitinsim_eulacontainer', 'id' => 'turnitinsim_eulaaccepted') ); } - + if (!(bool)$features->tenant->require_eula) { return html_writer::tag( 'div', @@ -536,19 +510,13 @@ public function print_disclosure($cmid, $submissiontype = 'file') { array('class' => 'btn btn-primary', 'id' => 'turnitinsim_eula_accept') ); - // Button to allow the user to decline the Turnitin EULA. - $euladeclinebtn = html_writer::tag('span', - get_string('euladecline', 'plagiarism_turnitinsim'), - array('class' => 'btn btn-secondary', 'id' => 'turnitinsim_eula_decline') - ); - // Output EULA container. $output = html_writer::tag( 'div', html_writer::tag( 'p', $eulalink - ).$eulaacceptbtn.$euladeclinebtn, + ).$eulaacceptbtn, array('class' => 'turnitinsim_eulacontainer', 'id' => 'turnitinsim_eulacontainer') ); @@ -556,15 +524,6 @@ public function print_disclosure($cmid, $submissiontype = 'file') { } } - /** - * Hook to allow status of submitted files to be updated - called on grading/report pages. - * - * @param object $course - full Course object - * @param object $cm - full cm object - */ - public function update_status($course, $cm) { - } - /** * Get the Turnitin settings for a module. * @@ -991,7 +950,7 @@ public static function plugin_enabled() { function plagiarism_turnitinsim_coursemodule_standard_elements($formwrapper, $mform) { $context = context_course::instance($formwrapper->get_course()->id); - (new plagiarism_plugin_turnitinsim())->get_form_elements_module( + (new plagiarism_plugin_turnitinsim())->add_elements_to_settings_form( $mform, $context, isset($formwrapper->get_current()->modulename) ? 'mod_'.$formwrapper->get_current()->modulename : '' @@ -1005,7 +964,13 @@ function plagiarism_turnitinsim_coursemodule_standard_elements($formwrapper, $mf * @param stdClass $course The course the call is made from. */ function plagiarism_turnitinsim_coursemodule_edit_post_actions($data, $course) { - (new plagiarism_plugin_turnitinsim())->save_form_elements($data); + $moduletiienabled = $moduletiienabled = get_config('plagiarism_turnitinsim', 'turnitinmodenabled'.$data->modulename); + if (empty($moduletiienabled)) { + return $data; + } + + $form = new plagiarism_turnitinsim_settings(); + $form->save_module_settings($data); return $data; } diff --git a/tests/classes/eula.class_test.php b/tests/classes/eula.class_test.php index 5a79019..e161544 100644 --- a/tests/classes/eula.class_test.php +++ b/tests/classes/eula.class_test.php @@ -167,7 +167,7 @@ public function test_accept_eula_saves_eula_and_updates_submissions() { // Check the results. $userresult = $DB->get_record('plagiarism_turnitinsim_users', array('userid' => $user->userid)); $this->assertEquals('v1beta', $userresult->lasteulaaccepted); - $this->assertGreaterThan('lasteulaacceptedtime', time() - 60); + $this->assertGreaterThan(time() - 60, $userresult->lasteulaacceptedtime); $this->assertEquals('en-US', $userresult->lasteulaacceptedlang); $submissionresult = $DB->get_records( @@ -189,6 +189,8 @@ public function test_get_eula_status_for_student() { $featuresenabled = file_get_contents(__DIR__ . '/../fixtures/get_features_enabled_success.json'); set_config('turnitin_features_enabled', $featuresenabled, 'plagiarism_turnitinsim'); set_config('turnitin_eula_version', 'v1-beta', 'plagiarism_turnitinsim'); + set_config('turnitin_eula_url', 'https://dev-integrations.turnitin.org/api/v1/eula/v1beta/view', 'plagiarism_turnitinsim'); + set_config('turnitinapiurl', 'https://dev-integrations.turnitin.org', 'plagiarism_turnitinsim'); // Create a course. $this->course = $this->getDataGenerator()->create_course(); @@ -225,7 +227,21 @@ public function test_get_eula_status_for_student() { // Get course module data. $cm = get_coursemodule_from_instance('assign', $module->id); - $tseula = new plagiarism_turnitinsim_eula(); + // Get the response for a failed EULA version retrieval. + $response = file_get_contents(__DIR__ . '/../fixtures/get_latest_eula_version_success.json'); + + // Mock API request class. + $tsrequest = $this->getMockBuilder(plagiarism_turnitinsim_request::class) + ->setMethods(['send_request']) + ->setConstructorArgs([TURNITINSIM_ENDPOINT_GET_LATEST_EULA]) + ->getMock(); + + // Mock API send request method. + $tsrequest->expects($this->once()) + ->method('send_request') + ->willReturn($response); + + $tseula = new plagiarism_turnitinsim_eula( $tsrequest ); $result = $tseula->get_eula_status($cm->id, 'file', $this->student->id); handle_deprecation::assertcontains($this, @@ -287,7 +303,21 @@ public function test_get_eula_status_for_instructor() { // Get course module data. $cm = get_coursemodule_from_instance('assign', $module->id); - $tseula = new plagiarism_turnitinsim_eula(); + // Get the response for a failed EULA version retrieval. + $response = file_get_contents(__DIR__ . '/../fixtures/get_latest_eula_version_success.json'); + + // Mock API request class. + $tsrequest = $this->getMockBuilder(plagiarism_turnitinsim_request::class) + ->setMethods(['send_request']) + ->setConstructorArgs([TURNITINSIM_ENDPOINT_GET_LATEST_EULA]) + ->getMock(); + + // Mock API send request method. + $tsrequest->expects($this->once()) + ->method('send_request') + ->willReturn($response); + + $tseula = new plagiarism_turnitinsim_eula($tsrequest); $result = $tseula->get_eula_status($cm->id, 'file', $this->instructor->id); handle_deprecation::assertcontains($this, diff --git a/tests/classes/quiz.class_test.php b/tests/classes/quiz.class_test.php index b40ac20..88a664a 100644 --- a/tests/classes/quiz.class_test.php +++ b/tests/classes/quiz.class_test.php @@ -117,7 +117,7 @@ public function test_get_itemid_returns_correct_itemid() { $params->onlinetext = self::QUIZ_ANSWER_TEXT; $result = $tsquiz->get_itemid($params); - $this->assertEquals($result, $quizattempt->id); + $this->assertEquals($result, $quizattempt->uniqueid); } /** diff --git a/tests/classes/request_class_test.php b/tests/classes/request_class_test.php index 549ff5b..96addd7 100644 --- a/tests/classes/request_class_test.php +++ b/tests/classes/request_class_test.php @@ -147,7 +147,7 @@ public function test_get_language() { $this->assertEquals('de-DE', $lang->localecode); // Test that English is returned for an unsupported language. - $SESSION->lang = 'fr'; + $SESSION->lang = 'zh'; $lang = $tsrequest->get_language(); $this->assertEquals('en', $lang->langcode); diff --git a/tests/lib_test.php b/tests/lib_test.php index 41bdf67..b9a8956 100644 --- a/tests/lib_test.php +++ b/tests/lib_test.php @@ -51,6 +51,16 @@ class plagiarism_turnitinsim_lib_testcase extends advanced_testcase { */ const TURNITINSIM_API_KEY = '123456'; + protected $plugin; + protected $course; + protected $student1; + protected $student1ts; + protected $instructor; + protected $tseula; + protected $eulaurl; + protected $cm; + protected $assign; + /** * Get a list of activity modules that support plagiarism plugins. * @@ -489,7 +499,7 @@ public function test_print_disclosure_display_latest() { // Get locale. $tsrequest = new plagiarism_turnitinsim_request(); $lang = $tsrequest->get_language(); - $eulaurl = $this->eulaurl."?lang=".$lang->localecode; + $eulaurl = $this->eulaurl; // Verify EULA is output. $plagiarismturnitinsim = new plagiarism_plugin_turnitinsim(); diff --git a/tests/privacy/provider_test.php b/tests/privacy/provider_test.php index 118985d..0381664 100644 --- a/tests/privacy/provider_test.php +++ b/tests/privacy/provider_test.php @@ -39,6 +39,9 @@ */ class plagiarism_turnitinsim_privacy_provider_testcase extends advanced_testcase { + protected $turnitinsim_generator; + protected $submission; + /** * Setup method that runs before each test. */ diff --git a/vendor/katzgrau/klogger/src/Logger.php b/vendor/katzgrau/klogger/src/Logger.php index c3add8c..f54d05d 100755 --- a/vendor/katzgrau/klogger/src/Logger.php +++ b/vendor/katzgrau/klogger/src/Logger.php @@ -305,7 +305,7 @@ private function getTimestamp() { $originalTime = microtime(true); $micro = sprintf("%06d", ($originalTime - floor($originalTime)) * 1000000); - $date = new DateTime(date('Y-m-d H:i:s.'.$micro, $originalTime)); + $date = new DateTime(date('Y-m-d H:i:s.'.$micro, (int)$originalTime)); return $date->format($this->options['dateFormat']); } diff --git a/version.php b/version.php index 61c1d6f..7b67669 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023062901; +$plugin->version = 2024112501; $plugin->release = "v1.2"; $plugin->requires = 2017051500; $plugin->component = 'plagiarism_turnitinsim';