diff --git a/CHANGELOG.md b/CHANGELOG.md index 68280c6..73047de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +### Date: 2021-March-02 +### Release: v2021030201 + +#### :zap: What's new + +--- + +#### API URLs will self-correct when inputted incorrectly + +When configuring the plug-in, the API URL used should end in /API. However, some users have copied just the first part of the URL into the field, which will cause the configuration to fail. We now proactively check for instances where the URL has not been configured correctly and self-correct them so that the configuration will succeed. + +#### :wrench: Fixes and enhancements + +--- + +#### Default value change for quizanswer filed in submissions table + +We have updated the default value for a database field in the submissions table (quizanswer) from null to 0. This could potentially cause automatic integration problems. Thank you to OpenLMS for letting us know about the problem. It’s now been fixed. + +#### Missing User ID - various fixes + +We’ve performed a thorough investigation into an issue where Moodle does not pass a user ID to Turnitin, which can present in various ways. These include: + +* The annotate PDF module attempts to save a submission for when a PDF is annotated. +* If a student who has not accepted our EULA tries to view the inbox after submissions have begun but before the instructor has viewed it. +* Text-submissions for group assignments would not save correctly if Turnitin was enabled after the submission was made. + +All of these issues are fixed in this release. + +--- + ### Date: 2021-January-18 ### Release: v2021011801 diff --git a/classes/request.class.php b/classes/request.class.php index c9700ee..ab2b2e3 100644 --- a/classes/request.class.php +++ b/classes/request.class.php @@ -123,10 +123,6 @@ public function send_request($endpoint, $requestbody, $method, $requesttype = 'g $tiiurl = $this->get_apiurl(); - if ($requesttype === 'logging') { - $tiiurl = str_replace('/api', '', $this->get_apiurl()); - } - if ($this->logger) { $this->logger->info('[' . $method . '] Request to: ' . $tiiurl . $endpoint); $this->logger->info('Headers: ', $this->headers); @@ -244,7 +240,10 @@ public function send_request($endpoint, $requestbody, $method, $requesttype = 'g */ public function test_connection($apiurl, $apikey) { - $validurlregex = '/.+\.(turnitin\.com|turnitinuk\.com|turnitin\.dev|turnitin\.org|tii-sandbox\.com)\/api$/m'; + // Strip any trailing / chars from api url. + $apiurl = rtrim($apiurl, '/'); + + $validurlregex = '/.+\.(turnitin\.com|turnitinuk\.com|turnitin\.dev|turnitin\.org|tii-sandbox\.com)(\/api)?$/m'; if (empty($apikey) || empty($apiurl)) { $data["connection_status"] = TURNITINSIM_HTTP_BAD_REQUEST; @@ -260,6 +259,8 @@ public function test_connection($apiurl, $apikey) { return json_encode($data); } + $apiurl = str_replace("/api", '', $apiurl); + $this->set_apiurl($apiurl); $this->set_apikey($apikey); $this->set_headers(); diff --git a/classes/setup_form.class.php b/classes/setup_form.class.php index fbd6f8a..1a0db3a 100644 --- a/classes/setup_form.class.php +++ b/classes/setup_form.class.php @@ -171,7 +171,22 @@ public function save($data) { } } - $turnitinapiurl = (!empty($data->turnitinapiurl)) ? $data->turnitinapiurl : ''; + $validurlregexwithapi = '/.+\.(turnitin\.com|turnitinuk\.com|turnitin\.dev|turnitin\.org|tii-sandbox\.com)\/api$/m'; + + if ((!empty($data->turnitinapiurl))) { + // Strip any trailing / chars from api url. + $apiurl = rtrim($data->turnitinapiurl, '/'); + if (preg_match($validurlregexwithapi, $apiurl)) { + $logger = new plagiarism_turnitinsim_logger(); + $logger->info('Stripping /api from Turnitin URL on save: ', array($apiurl)); + $turnitinapiurl = str_replace("/api", '', $apiurl); + } else { + $turnitinapiurl = $apiurl; + } + } else { + $turnitinapiurl = ''; + } + $turnitinapikey = (!empty($data->turnitinapikey)) ? $data->turnitinapikey : ''; $turnitinenablelogging = (!empty($data->turnitinenablelogging)) ? $data->turnitinenablelogging : 0; $turnitinenableremotelogging = (!empty($data->turnitinenableremotelogging)) ? $data->turnitinenableremotelogging : 0; diff --git a/classes/user.class.php b/classes/user.class.php index 5069c23..d04cf86 100644 --- a/classes/user.class.php +++ b/classes/user.class.php @@ -70,6 +70,10 @@ class plagiarism_turnitinsim_user { public function __construct($userid) { global $DB; + if (empty($userid)) { + return; + } + $this->set_userid($userid); // If there is no user record then create one. diff --git a/db/upgrade.php b/db/upgrade.php index fe4bc10..fad110e 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -28,7 +28,7 @@ /** * Database upgrade script for plagiarism_turnitinsim component. * - * @param int $oldversion The version that is currently installed. + * @param int $oldversion The version that is currently installed. (The version being upgraded from) * @return bool true if upgrade was successful. * @throws ddl_exception * @throws ddl_table_missing_exception @@ -304,5 +304,22 @@ function xmldb_plagiarism_turnitinsim_upgrade($oldversion) { upgrade_plugin_savepoint(true, 2020092301, 'plagiarism', 'turnitinsim'); } + // Remove "/api" from the Turnitin URL as its been added to the endpoint constants. + // Update field defaults for quizanswer to match install.xml. + if ($oldversion < 2021030201) { + (new handle_deprecation)->unset_turnitinsim_use(); + + $turnitinapiurl = get_config('plagiarism_turnitinsim', 'turnitinapiurl'); + + set_config('turnitinapiurl', str_replace("/api", '', $turnitinapiurl), 'plagiarism_turnitinsim'); + + $table = new xmldb_table('plagiarism_turnitinsim_sub'); + $field = new xmldb_field('quizanswer', XMLDB_TYPE_CHAR, '32', null, false, null, 0, 'tiiretrytime'); + + $dbman->change_field_default($table, $field); + + upgrade_plugin_savepoint(true, 2021030201, 'plagiarism', 'turnitinsim'); + } + return true; } \ No newline at end of file diff --git a/lib.php b/lib.php index 4d6386c..aa4d69b 100644 --- a/lib.php +++ b/lib.php @@ -161,15 +161,19 @@ public function save_form_elements($data) { * @throws moodle_exception */ public function get_links($linkarray) { - global $DB, $OUTPUT, $PAGE; + global $DB, $OUTPUT, $PAGE, $USER; // Require the relevant JS modules. Only include once. static $jsloaded; if (empty($jsloaded)) { $jsloaded = true; $PAGE->requires->string_for_js('submissiondisplaystatus:queued', 'plagiarism_turnitinsim'); + $PAGE->requires->string_for_js('eulaaccepted', 'plagiarism_turnitinsim'); + $PAGE->requires->string_for_js('euladeclined', 'plagiarism_turnitinsim'); + $PAGE->requires->string_for_js('submissiondisplaystatus:queued', 'plagiarism_turnitinsim'); $PAGE->requires->js_call_amd('plagiarism_turnitinsim/cv_launch', 'openCv'); $PAGE->requires->js_call_amd('plagiarism_turnitinsim/resend_submission', 'resendSubmission'); + $PAGE->requires->js_call_amd('plagiarism_turnitinsim/eula_response', 'eulaResponse'); } $output = ''; @@ -177,8 +181,11 @@ public function get_links($linkarray) { if (!empty($linkarray["file"])) { $file = $linkarray["file"]; $filearea = $file->get_filearea(); + $nonsubmittingareas = array("feedback_files", "introattachment"); - if (in_array($filearea, $nonsubmittingareas)) { + $allowedcomponents = array("assignsubmission_file", "mod_assign", "mod_forum", "mod_workshop", "question"); + + if ((in_array($filearea, $nonsubmittingareas)) || !in_array($file->get_component(), $allowedcomponents)) { return $output; } } @@ -235,6 +242,7 @@ public function get_links($linkarray) { if ((!empty($linkarray['file'])) || (!empty($linkarray['content']))) { $submissionid = ''; $eulaconfirm = ''; + $status = ''; $showresubmitlink = false; $submission = null; @@ -338,7 +346,13 @@ public function get_links($linkarray) { break; } - } else { + } else if ($linkarray['userid'] != null) { + if ($instructor && $linkarray['userid'] === "0") { + return $output; + } else { + $linkarray['userid'] = $USER->id; + } + // If the plugin was enabled after a submission was made then it will not have been sent to Turnitin. Queue it. $moduleclass = 'plagiarism_turnitinsim_'.$cm->modname; $moduleobject = new $moduleclass; @@ -351,7 +365,7 @@ public function get_links($linkarray) { if ($plagiarismfile->status === TURNITINSIM_SUBMISSION_STATUS_EULA_NOT_ACCEPTED) { $eula = new plagiarism_turnitinsim_eula(); - $statusset = $eula->get_eula_status($cm->id, $submission->gettype()); + $statusset = $eula->get_eula_status($cm->id, $plagiarismfile->type); $status = $statusset['eula-status']; $eulaconfirm = $statusset['eula-confirm']; } else { diff --git a/utilities/constants.php b/utilities/constants.php index f484ac8..4018c54 100644 --- a/utilities/constants.php +++ b/utilities/constants.php @@ -57,15 +57,15 @@ define('TURNITINSIM_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS', 451); // API Endpoints. -define('TURNITINSIM_ENDPOINT_CREATE_SUBMISSION', '/v1/submissions'); -define('TURNITINSIM_ENDPOINT_GET_SUBMISSION_INFO', '/v1/submissions/{{submission_id}}'); -define('TURNITINSIM_ENDPOINT_UPLOAD_SUBMISSION', '/v1/submissions/{{submission_id}}/original'); -define('TURNITINSIM_ENDPOINT_SIMILARITY_REPORT', '/v1/submissions/{{submission_id}}/similarity'); -define('TURNITINSIM_ENDPOINT_CV_LAUNCH', '/v1/submissions/{{submission_id}}/viewer-url'); -define('TURNITINSIM_ENDPOINT_WEBHOOKS', '/v1/webhooks'); -define('TURNITINSIM_ENDPOINT_GET_WEBHOOK', '/v1/webhooks/{{webhook_id}}'); -define('TURNITINSIM_ENDPOINT_GET_LATEST_EULA', '/v1/eula/latest'); -define('TURNITINSIM_ENDPOINT_GET_FEATURES_ENABLED', '/v1/features-enabled'); +define('TURNITINSIM_ENDPOINT_CREATE_SUBMISSION', '/api/v1/submissions'); +define('TURNITINSIM_ENDPOINT_GET_SUBMISSION_INFO', '/api/v1/submissions/{{submission_id}}'); +define('TURNITINSIM_ENDPOINT_UPLOAD_SUBMISSION', '/api/v1/submissions/{{submission_id}}/original'); +define('TURNITINSIM_ENDPOINT_SIMILARITY_REPORT', '/api/v1/submissions/{{submission_id}}/similarity'); +define('TURNITINSIM_ENDPOINT_CV_LAUNCH', '/api/v1/submissions/{{submission_id}}/viewer-url'); +define('TURNITINSIM_ENDPOINT_WEBHOOKS', '/api/v1/webhooks'); +define('TURNITINSIM_ENDPOINT_GET_WEBHOOK', '/api/v1/webhooks/{{webhook_id}}'); +define('TURNITINSIM_ENDPOINT_GET_LATEST_EULA', '/api/v1/eula/latest'); +define('TURNITINSIM_ENDPOINT_GET_FEATURES_ENABLED', '/api/v1/features-enabled'); define('TURNITINSIM_ENDPOINT_LOGGING', '/remote-logging/api/log'); // URLs. diff --git a/version.php b/version.php index 11593e6..554de8c 100644 --- a/version.php +++ b/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021011801; +$plugin->version = 2021030201; $plugin->release = "v1.2"; $plugin->requires = 2017051500; $plugin->component = 'plagiarism_turnitinsim';