Compare commits
23 Commits
Author | SHA1 | Date |
---|---|---|
Jane Adelmann | faaca3e8ac | |
Jane Adelmann | 6208bf4ff3 | |
Jane Adelmann | aa44efdf0b | |
Jane Adelmann | 04a22a1d3d | |
Jane Adelmann | 830b77e6f7 | |
Jane Adelmann | dd15b4983d | |
Jane Adelmann | 8c3f615f7d | |
Jane Adelmann | 45634d8a3e | |
Jane Adelmann | a46f7043e5 | |
Llewelyn Williams | 87f8af6563 | |
Jane Adelmann | 8862dc050a | |
Jane Adelmann | 99b58f8e27 | |
Jane Adelmann | 987a4b8674 | |
Jane Adelmann | 0803af58ea | |
Jane Adelmann | e198855544 | |
Jane Adelmann | 28a2132625 | |
Jane Adelmann | c511214aed | |
Jane Adelmann | c0a0533b10 | |
Jane Adelmann | 74a67bce5f | |
PlagiarismCheck | fb0b80b495 | |
Leon Stringer | 1d568254bf | |
Jane Adelmann | 5a44f324ae | |
Jane Adelmann | c071dae607 |
|
@ -1,2 +1,2 @@
|
|||
.idea
|
||||
|
||||
.vscode
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<?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/>.
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
class backup_plagiarism_pchkorg_plugin extends backup_plagiarism_plugin {
|
||||
/**
|
||||
* define_module_plugin_structure
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function define_module_plugin_structure() {
|
||||
// Define the virtual plugin element without conditions as the global class checks already.
|
||||
$plugin = $this->get_plugin_element();
|
||||
|
||||
// Create one standard named plugin element (the visible container).
|
||||
$pluginwrapper = new backup_nested_element($this->get_recommended_name());
|
||||
|
||||
// Connect the visible container ASAP.
|
||||
$plugin->add_child($pluginwrapper);
|
||||
|
||||
$configs = new backup_nested_element('pchkorg_activities_configs');
|
||||
$config = new backup_nested_element('pchkorg_activities_config', array('id'), array('name', 'value'));
|
||||
$pluginwrapper->add_child($configs);
|
||||
$configs->add_child($config);
|
||||
$config->set_source_table('plagiarism_pchkorg_config', array('cm' => backup::VAR_PARENTID));
|
||||
|
||||
// Now information about files to module.
|
||||
$files = new backup_nested_element('pchkorg_files');
|
||||
$file = new backup_nested_element('pchkorg_file', array('id'), array(
|
||||
'cm', 'fileid', 'userid',
|
||||
'state', 'score', 'created_at',
|
||||
'textid', 'reportid', 'signature',
|
||||
'attempt', 'itemid'
|
||||
));
|
||||
|
||||
$pluginwrapper->add_child($files);
|
||||
$files->add_child($file);
|
||||
|
||||
// To know if we are including userinfo.
|
||||
$userinfo = $this->get_setting_value('userinfo');
|
||||
if ($userinfo) {
|
||||
$file->set_source_table('plagiarism_pchkorg_files', array('cm' => backup::VAR_PARENTID));
|
||||
}
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* define_course_plugin_structure
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function define_course_plugin_structure() {
|
||||
$plugin = $this->get_plugin_element();
|
||||
$pluginwrapper = new backup_nested_element($this->get_recommended_name());
|
||||
$plugin->add_child($pluginwrapper);
|
||||
|
||||
$configs = new backup_nested_element('pchkorg_configs');
|
||||
$config = new backup_nested_element('pchkorg_config', array('id'), array('plugin', 'name', 'value'));
|
||||
$pluginwrapper->add_child($configs);
|
||||
$configs->add_child($config);
|
||||
$config->set_source_table('config_plugins', array(
|
||||
'name' => backup::VAR_PARENTID, 'plugin' => backup_helper::is_sqlparam('plagiarism'),
|
||||
));
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
}
|
|
@ -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/>.
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
class restore_plagiarism_pchkorg_plugin extends restore_plagiarism_plugin {
|
||||
|
||||
public function process_pchkorg_config($data) {
|
||||
$data = (object) $data;
|
||||
|
||||
set_config($this->task->get_courseid(), $data->value, $data->plugin);
|
||||
}
|
||||
|
||||
|
||||
public function process_pchkorgconfigmod($data) {
|
||||
global $DB;
|
||||
|
||||
$data = (object) $data;
|
||||
$data->cm = $this->task->get_moduleid();
|
||||
|
||||
$DB->insert_record('plagiarism_pchkorg_config', $data);
|
||||
}
|
||||
|
||||
public function process_pchkorgfiles($data) {
|
||||
global $DB;
|
||||
|
||||
$data = (object) $data;
|
||||
$data->cm = $this->task->get_moduleid();
|
||||
$data->userid = $this->get_mappingid('user', $data->userid);
|
||||
|
||||
$DB->insert_record('plagiarism_pchkorg_files', $data);
|
||||
}
|
||||
|
||||
|
||||
protected function define_course_plugin_structure() {
|
||||
$paths = array();
|
||||
|
||||
$elename = 'pchkorg_config';
|
||||
$elepath = $this->get_pathfor('/pchkorg_configs/pchkorg_config');
|
||||
|
||||
$paths[] = new restore_path_element($elename, $elepath);
|
||||
|
||||
return $paths; // And we return the interesting paths.
|
||||
}
|
||||
|
||||
|
||||
protected function define_module_plugin_structure() {
|
||||
$paths = array();
|
||||
|
||||
$elename = 'pchkorgconfigmod';
|
||||
$elepath = $this->get_pathfor('/pchkorg_activities_configs/pchkorg_activities_config');
|
||||
$paths[] = new restore_path_element($elename, $elepath);
|
||||
|
||||
$elename = 'pchkorgfiles';
|
||||
$elepath = $this->get_pathfor('/pchkorg_file/pchkorg_file');
|
||||
$paths[] = new restore_path_element($elename, $elepath);
|
||||
|
||||
return $paths;
|
||||
}
|
||||
}
|
|
@ -177,13 +177,10 @@ class plagiarism_pchkorg_api_provider {
|
|||
$content,
|
||||
$mime,
|
||||
$filename,
|
||||
$filters,
|
||||
$filters
|
||||
),
|
||||
array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
'CURLOPT_FOLLOWLOCATION' => true,
|
||||
'CURLOPT_SSL_VERIFYHOST' => false,
|
||||
'CURLOPT_SSL_VERIFYPEER' => false,
|
||||
'CURLOPT_HTTPHEADER' => array(
|
||||
'X-API-TOKEN: ' . $this->generate_api_token(),
|
||||
'Content-Type: multipart/form-data; boundary=' . $boundary
|
||||
|
@ -299,13 +296,10 @@ class plagiarism_pchkorg_api_provider {
|
|||
$content,
|
||||
$mime,
|
||||
$filename,
|
||||
$filters,
|
||||
$filters
|
||||
),
|
||||
array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
'CURLOPT_FOLLOWLOCATION' => true,
|
||||
'CURLOPT_SSL_VERIFYHOST' => false,
|
||||
'CURLOPT_SSL_VERIFYPEER' => false,
|
||||
'CURLOPT_POST' => true,
|
||||
'CURLOPT_HTTPHEADER' => array(
|
||||
'X-API-TOKEN: ' . $this->generate_api_token(),
|
||||
|
@ -347,9 +341,6 @@ class plagiarism_pchkorg_api_provider {
|
|||
'',
|
||||
array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
'CURLOPT_FOLLOWLOCATION' => true,
|
||||
'CURLOPT_SSL_VERIFYHOST' => false,
|
||||
'CURLOPT_SSL_VERIFYPEER' => false,
|
||||
'CURLOPT_POST' => true,
|
||||
'CURLOPT_HTTPHEADER' => array(
|
||||
'X-API-TOKEN: ' . $token,
|
||||
|
@ -455,7 +446,7 @@ class plagiarism_pchkorg_api_provider {
|
|||
*/
|
||||
public function user_email_to_hash($email) {
|
||||
// We don't send raw user email to the service.
|
||||
return hash('sha256', $this->token . $email);
|
||||
return hash('sha256', $this->token . strtolower($email));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -489,11 +480,8 @@ class plagiarism_pchkorg_api_provider {
|
|||
'hash' => $this->user_email_to_hash($email)
|
||||
), array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
'CURLOPT_FOLLOWLOCATION' => true,
|
||||
'CURLOPT_SSL_VERIFYHOST' => false,
|
||||
'CURLOPT_SSL_VERIFYPEER' => false,
|
||||
// The maximum number of seconds to allow cURL functions to execute.
|
||||
'CURLOPT_TIMEOUT' => 2
|
||||
'CURLOPT_TIMEOUT' => 8
|
||||
));
|
||||
|
||||
if ($json = json_decode($response)) {
|
||||
|
@ -506,6 +494,82 @@ class plagiarism_pchkorg_api_provider {
|
|||
return $resultmap[$email];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that user belongs to group when it is group account.
|
||||
* And Receive auto_registration_option.
|
||||
*
|
||||
* @param string $email
|
||||
* @return object
|
||||
*/
|
||||
public function get_group_member_response($email = '') {
|
||||
if (!$this->is_group_token()) {
|
||||
$result = new \stdClass;
|
||||
$result->is_member = true;
|
||||
$result->is_auto_registration_enabled = false;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
static $resultmap = array();
|
||||
|
||||
if (!array_key_exists($email, $resultmap)) {
|
||||
//default result. For case when we can not receive response.
|
||||
$result = new \stdClass;
|
||||
$result->is_member = false;
|
||||
$result->is_auto_registration_enabled = false;
|
||||
$resultmap[$email] = $result;
|
||||
|
||||
$curl = new curl();
|
||||
$response = $curl->post($this->endpoint . '/lms/moodle/is-group-member/', array(
|
||||
'token' => $this->token,
|
||||
'hash' => $this->user_email_to_hash($email)
|
||||
), array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
// The maximum number of seconds to allow cURL functions to execute.
|
||||
'CURLOPT_TIMEOUT' => 8
|
||||
));
|
||||
|
||||
if ($json = json_decode($response)) {
|
||||
$result->is_member = $json->is_member;
|
||||
$result->is_auto_registration_enabled = $json->is_auto_registration_enabled;
|
||||
$resultmap[$email] = $result;
|
||||
}
|
||||
}
|
||||
|
||||
return $resultmap[$email];
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto registration is enabled for this university,
|
||||
* so we registrate a user and user can check submissions.
|
||||
*
|
||||
* @param $name
|
||||
* @param $email
|
||||
* @param $role
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function auto_registrate_member($name, $email, $role) {
|
||||
$curl = new curl();
|
||||
$response = $curl->post($this->endpoint . '/lms/moodle/auto-registration/', array(
|
||||
'token' => $this->token,
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'role' => $role,
|
||||
), array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
// The maximum number of seconds to allow cURL functions to execute.
|
||||
'CURLOPT_TIMEOUT' => 8
|
||||
));
|
||||
|
||||
|
||||
if ($json = json_decode($response)) {
|
||||
return $json->success;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check status of document.
|
||||
* If document has been checked, state is 5.
|
||||
|
@ -519,12 +583,10 @@ class plagiarism_pchkorg_api_provider {
|
|||
// It uses different auth.
|
||||
return $this->group_check_text($textid);
|
||||
}
|
||||
|
||||
$curl = new curl();
|
||||
$response = $curl->get($this->endpoint . '/api/v1/text/' . $textid, array(), array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
'CURLOPT_FOLLOWLOCATION' => true,
|
||||
'CURLOPT_SSL_VERIFYHOST' => false,
|
||||
'CURLOPT_SSL_VERIFYPEER' => false,
|
||||
'CURLOPT_POST' => false,
|
||||
'CURLOPT_HTTPHEADER' => array(
|
||||
'X-API-TOKEN: ' . $this->generate_api_token(),
|
||||
|
@ -533,7 +595,12 @@ class plagiarism_pchkorg_api_provider {
|
|||
));
|
||||
if ($json = json_decode($response)) {
|
||||
if (isset($json->data) && 5 == $json->data->state) {
|
||||
return $json->data->report;
|
||||
$result = new stdClass;
|
||||
$result->id = $json->data->report->id;
|
||||
$result->percent = $json->data->report->percent;
|
||||
$result->percent_ai = $json->data->ai_report->processed_percent;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -553,9 +620,6 @@ class plagiarism_pchkorg_api_provider {
|
|||
'token' => $this->token
|
||||
), array(
|
||||
'CURLOPT_RETURNTRANSFER' => true,
|
||||
'CURLOPT_FOLLOWLOCATION' => true,
|
||||
'CURLOPT_SSL_VERIFYHOST' => false,
|
||||
'CURLOPT_SSL_VERIFYPEER' => false,
|
||||
'CURLOPT_POST' => false,
|
||||
'CURLOPT_HTTPHEADER' => array(
|
||||
'Content-Type: application/x-www-form-urlencoded'
|
||||
|
@ -563,7 +627,12 @@ class plagiarism_pchkorg_api_provider {
|
|||
));
|
||||
if ($json = json_decode($response)) {
|
||||
if (isset($json->data) && 5 == $json->data->state) {
|
||||
return $json->data->report;
|
||||
$result = new stdClass;
|
||||
$result->id = $json->data->report->id;
|
||||
$result->percent = $json->data->report->percent;
|
||||
$result->percent_ai = $json->data->ai_report->processed_percent;
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -589,7 +658,7 @@ class plagiarism_pchkorg_api_provider {
|
|||
global $USER;
|
||||
|
||||
if ($this->is_group_token()) {
|
||||
return $this->token . '::' . hash('sha256', $this->token . $USER->email);
|
||||
return $this->token . '::' . hash('sha256', $this->token . strtolower($USER->email));
|
||||
}
|
||||
|
||||
return $this->token;
|
||||
|
@ -603,13 +672,13 @@ class plagiarism_pchkorg_api_provider {
|
|||
*/
|
||||
public function is_supported_mime($mime) {
|
||||
return in_array($mime, array(
|
||||
'application/msword',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/rtf',
|
||||
'application/vnd.oasis.opendocument.text',
|
||||
'text/plain',
|
||||
'plain/text',
|
||||
'application/pdf',
|
||||
'application/msword',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'application/rtf',
|
||||
'application/vnd.oasis.opendocument.text',
|
||||
'text/plain',
|
||||
'application/pdf'
|
||||
), true);
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,16 @@ namespace plagiarism_pchkorg\privacy;
|
|||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\userlist;
|
||||
use core_privacy\local\request\approved_userlist;
|
||||
|
||||
if (interface_exists('\core_privacy\local\request\userlist')) {
|
||||
interface my_userlist extends \core_privacy\local\request\userlist{}
|
||||
} else {
|
||||
interface my_userlist {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Class provider
|
||||
|
@ -33,8 +43,10 @@ use core_privacy\local\metadata\collection;
|
|||
* @package plagiarism_pchkorg\privacy
|
||||
*/
|
||||
class provider implements
|
||||
my_userlist,
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\plugin\provider {
|
||||
\core_privacy\local\request\plugin\provider,
|
||||
\core_privacy\local\request\core_userlist_provider {
|
||||
|
||||
// This trait must be included.
|
||||
use \core_privacy\local\legacy_polyfill;
|
||||
|
@ -59,6 +71,7 @@ class provider implements
|
|||
'userid' => 'privacy:metadata:plagiarism_pchkorg_files:userid',
|
||||
'state' => 'privacy:metadata:plagiarism_pchkorg_files:state',
|
||||
'score' => 'privacy:metadata:plagiarism_pchkorg_files:score',
|
||||
'scoreai' => 'privacy:metadata:plagiarism_pchkorg_files:scoreai',
|
||||
'created_at' => 'privacy:metadata:plagiarism_pchkorg_files:created_at',
|
||||
'textid' => 'privacy:metadata:plagiarism_pchkorg_files:textid',
|
||||
'reportid' => 'privacy:metadata:plagiarism_pchkorg_files:reportid',
|
||||
|
@ -91,4 +104,80 @@ class provider implements
|
|||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid The user to search.
|
||||
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
|
||||
*/
|
||||
public static function _get_contexts_for_userid(int $userid) : contextlist {
|
||||
$contextlist = new contextlist();
|
||||
$sql = "SELECT DISTINCT cm FROM {plagiarism_pchkorg_files} WHERE userid = :userid";
|
||||
$params = [
|
||||
'userid' => $userid
|
||||
];
|
||||
$contextlist->add_from_sql($sql, $params);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the 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 instanceof \context_module) {
|
||||
return;
|
||||
}
|
||||
$params = [
|
||||
'cm' => $context->instanceid,
|
||||
];
|
||||
$sql = "SELECT DISTINCT userid FROM {plagiarism_pchkorg_files} WHERE cm = :cm";
|
||||
$userlist->add_from_sql('userid', $sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function _export_user_data(approved_contextlist $contextlist) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete 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) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Export all user preferences for the plugin.
|
||||
*
|
||||
* @param int $userid The userid of the user whose data is to be exported.
|
||||
*/
|
||||
public static function _export_user_preferences(int $userid) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param context $context The specific context to delete data for.
|
||||
*/
|
||||
public static function _delete_data_for_all_users_in_context(\context $context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
public static function _delete_data_for_user(approved_contextlist $contextlist) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="state" TYPE="int" LENGTH="3" NOTNULL="false" SEQUENCE="false"/>
|
||||
<FIELD NAME="score" TYPE="float" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
|
||||
<FIELD NAME="scoreai" TYPE="number" LENGTH="4" NOTNULL="false" SEQUENCE="false" DECIMALS="2"/>
|
||||
<FIELD NAME="created_at" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/>
|
||||
<FIELD NAME="textid" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false"/>
|
||||
<FIELD NAME="reportid" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false"/>
|
||||
|
|
|
@ -27,7 +27,7 @@ $tasks = array(
|
|||
array(
|
||||
'classname' => 'plagiarism_pchkorg\task\update_reports',
|
||||
'blocking' => 0,
|
||||
'minute' => '*/2',
|
||||
'minute' => '*',
|
||||
'hour' => '*',
|
||||
'day' => '*',
|
||||
'dayofweek' => '*',
|
||||
|
@ -36,7 +36,7 @@ $tasks = array(
|
|||
array(
|
||||
'classname' => 'plagiarism_pchkorg\task\send_submissions',
|
||||
'blocking' => 0,
|
||||
'minute' => '*/2',
|
||||
'minute' => '*',
|
||||
'hour' => '*',
|
||||
'day' => '*',
|
||||
'dayofweek' => '*',
|
||||
|
|
|
@ -57,5 +57,16 @@ function xmldb_plagiarism_pchkorg_upgrade($oldversion) {
|
|||
upgrade_plugin_savepoint(true, 2021072801, 'plagiarism', 'pchkorg');
|
||||
}
|
||||
|
||||
if ($oldversion < 2023060713) {
|
||||
$table = new xmldb_table('plagiarism_pchkorg_files');
|
||||
|
||||
$field1 = new xmldb_field('scoreai', XMLDB_TYPE_NUMBER, '4,2', XMLDB_UNSIGNED, null, null, null, null);
|
||||
$field1->setComment('AI score');
|
||||
|
||||
if (!$dbman->field_exists($table, $field1)) {
|
||||
$dbman->add_field($table, $field1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,14 @@ class plagiarism_pchkorg_setup_form extends moodleform {
|
|||
array(get_string('no'), get_string('yes'))
|
||||
);
|
||||
|
||||
$mform->addElement(
|
||||
'select',
|
||||
'pchkorg_enabled_by_default',
|
||||
get_string('pchkorg:enabledbydefault', 'plagiarism_pchkorg'),
|
||||
array(get_string('no'), get_string('yes'))
|
||||
);
|
||||
$mform->setDefault('pchkorg_enabled_by_default', '1');
|
||||
|
||||
$this->add_action_buttons(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ $string['pchkorg_debug_status_error'] = 'Some error for this file';
|
|||
$string['pchkorg_debug_student_not_allowed_see_widget'] = 'Students can not see a similarity score';
|
||||
$string['pchkorg_student_can_see_widget'] = 'Students can see a similarity score';
|
||||
$string['pchkorg_student_can_see_report'] = 'Students can access a similarity report';
|
||||
$string['pchkorg_check_ai'] = 'Enable AI Detector';
|
||||
$string['pchkorg_disclosure'] = 'Submission will be sent to <a target="_blank" href="https://plagiarismcheck.org/">PlagiarismCheck.org</a> for check.
|
||||
<br />
|
||||
By submitting assignment I agree with <a target="_blank" href="https://plagiarismcheck.org/terms-of-service/">Terms & Conditions</a>
|
||||
|
@ -69,6 +70,7 @@ $string['privacy:metadata:plagiarism_pchkorg_files:fileid'] = 'Identity of a sub
|
|||
$string['privacy:metadata:plagiarism_pchkorg_files:userid'] = 'Identity of user who submit file';
|
||||
$string['privacy:metadata:plagiarism_pchkorg_files:state'] = 'Status of a document. For example: queued, sent, checked.';
|
||||
$string['privacy:metadata:plagiarism_pchkorg_files:score'] = 'Originality score';
|
||||
$string['privacy:metadata:plagiarism_pchkorg_files:scoreai'] = 'Chat GPT score';
|
||||
$string['privacy:metadata:plagiarism_pchkorg_files:created_at'] = 'Date and time when document was saved.';
|
||||
$string['privacy:metadata:plagiarism_pchkorg_files:textid'] = 'Identity of originality check';
|
||||
$string['privacy:metadata:plagiarism_pchkorg_files:reportid'] = 'Identity of originality report';
|
||||
|
@ -88,8 +90,11 @@ $string['sendqueuedsubmissions'] = '';
|
|||
$string['updatereportscores'] = '';
|
||||
$string['pchkorg_label_title'] = 'PlagiarismCheck.org ID: %s; Similarity Score: %s%%';
|
||||
$string['pchkorg_label_result'] = 'ID: %s Similarity: %s%%';
|
||||
$string['pchkorg_label_title_ai'] = 'PlagiarismCheck.org ID: %s; Similarity Score: %s%% AI: %s%%';
|
||||
$string['pchkorg_label_result_ai'] = 'ID: %s Similarity: %s%% AI: %s%%';
|
||||
$string['pchkorg_label_sent'] = 'ID: %s Sent';
|
||||
$string['pchkorg_label_queued'] = 'In queue';
|
||||
$string['pchkorg:enable'] = 'Allow to enable/disable PlagiarismCheck.org inside an activity';
|
||||
$string['pchkorg:viewsimilarity'] = 'Allow to view similarity value from PlagiarismCheck.org';
|
||||
$string['pchkorg:changeminpercentfilter'] = 'Allow changing "Exclude sources below X% similarity"';
|
||||
$string['pchkorg:enabledbydefault'] = 'Enable PlagiarismCheck in Activities by default';
|
286
lib.php
286
lib.php
|
@ -66,7 +66,7 @@ function plagiarism_pchkorg_coursemodule_standard_elements($formwrapper, $mform)
|
|||
$defaultcmid = null;
|
||||
$cm = optional_param('update', $defaultcmid, PARAM_INT);
|
||||
$minpercent = $pchkorgconfigmodel->get_system_config('pchkorg_min_percent');
|
||||
$exportedvalues = $mform->exportValues([]);
|
||||
$exportedvalues = $mform->exportValues(array());
|
||||
if (!is_array($exportedvalues)) {
|
||||
$exportedvalues = array();
|
||||
}
|
||||
|
@ -97,7 +97,13 @@ function plagiarism_pchkorg_coursemodule_standard_elements($formwrapper, $mform)
|
|||
if (null === $cm) {
|
||||
if (!isset($exportedvalues['pchkorg_module_use'])
|
||||
|| is_null($exportedvalues['pchkorg_module_use'])) {
|
||||
$mform->setDefault('pchkorg_module_use', '1');
|
||||
$enabledbydefault = $pchkorgconfigmodel->get_system_config('pchkorg_enabled_by_default');
|
||||
if ('1' === $enabledbydefault || null === $enabledbydefault) {
|
||||
$mform->setDefault('pchkorg_module_use', '1');
|
||||
}
|
||||
if ('0' === $enabledbydefault) {
|
||||
$mform->setDefault('pchkorg_module_use', '0');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$records = $DB->get_records('plagiarism_pchkorg_config', array(
|
||||
|
@ -173,7 +179,6 @@ function plagiarism_pchkorg_coursemodule_standard_elements($formwrapper, $mform)
|
|||
array(get_string('no'), get_string('yes'))
|
||||
);
|
||||
|
||||
|
||||
$mform->addElement(
|
||||
'select',
|
||||
'pchkorg_student_can_see_widget',
|
||||
|
@ -187,12 +192,81 @@ function plagiarism_pchkorg_coursemodule_standard_elements($formwrapper, $mform)
|
|||
get_string('pchkorg_student_can_see_report', 'plagiarism_pchkorg'),
|
||||
array(get_string('no'), get_string('yes'))
|
||||
);
|
||||
|
||||
$mform->addElement(
|
||||
'select',
|
||||
'pchkorg_check_ai',
|
||||
get_string('pchkorg_check_ai', 'plagiarism_pchkorg'),
|
||||
array(get_string('no'), get_string('yes'))
|
||||
);
|
||||
$mform->setDefault('pchkorg_check_ai', 1);
|
||||
}
|
||||
}
|
||||
|
||||
function plagiarism_pchkorg_coursemodule_edit_post_actions($data, $course)
|
||||
{
|
||||
global $DB;
|
||||
|
||||
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
|
||||
|
||||
$config = $pchkorgconfigmodel->get_system_config('pchkorg_use');
|
||||
if ('1' != $config) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
$fields = array(
|
||||
'pchkorg_module_use',
|
||||
'pchkorg_min_percent',
|
||||
'pchkorg_include_citation',
|
||||
'pchkorg_include_referenced',
|
||||
'pchkorg_exclude_self_plagiarism',
|
||||
'pchkorg_student_can_see_widget',
|
||||
'pchkorg_student_can_see_report',
|
||||
'pchkorg_check_ai'
|
||||
);
|
||||
|
||||
$records = $DB->get_records('plagiarism_pchkorg_config', array(
|
||||
'cm' => $data->coursemodule
|
||||
));
|
||||
|
||||
$context = context_module::instance($data->coursemodule);
|
||||
$canchangeminpercent = has_capability(capability::CHANGE_MIN_PERCENT_FILTER, $context);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$isfounded = false;
|
||||
foreach ($records as $record) {
|
||||
if ($record->name === $field) {
|
||||
$isfounded = true;
|
||||
if ($field === 'pchkorg_min_percent' && !$canchangeminpercent) {
|
||||
$DB->delete_records('plagiarism_pchkorg_config', array('id' => $record->id));
|
||||
break;
|
||||
}
|
||||
if ($field === 'pchkorg_min_percent' && 0 == $data->{$record->name}) {
|
||||
$DB->delete_records('plagiarism_pchkorg_config', array('id' => $record->id));
|
||||
break;
|
||||
}
|
||||
$record->value = $data->{$record->name};
|
||||
$DB->update_record('plagiarism_pchkorg_config', $record);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$isfounded && isset($data->{$field})) {
|
||||
if ($field === 'pchkorg_min_percent' && !$canchangeminpercent) {
|
||||
continue;
|
||||
}
|
||||
if ($field === 'pchkorg_min_percent' && 0 == $data->{$field}) {
|
||||
continue;
|
||||
}
|
||||
$insert = new \stdClass();
|
||||
$insert->cm = $data->coursemodule;
|
||||
$insert->name = $field;
|
||||
$insert->value = $data->{$field};
|
||||
|
||||
$DB->insert_record('plagiarism_pchkorg_config', $insert);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,7 +290,11 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
|
|||
$isdebugenabled = $pchkorgconfigmodel->get_system_config('pchkorg_enable_debug') === '1';
|
||||
$apiprovider = new plagiarism_pchkorg_api_provider($apitoken);
|
||||
|
||||
$cmid = $linkarray['cmid'];
|
||||
$cmid = null;
|
||||
if (array_key_exists('cmid', $linkarray)) {
|
||||
$cmid = $linkarray['cmid'];
|
||||
}
|
||||
|
||||
if (array_key_exists('file', $linkarray)) {
|
||||
$file = $linkarray['file'];
|
||||
} else {
|
||||
|
@ -264,7 +342,7 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
|
|||
);
|
||||
}
|
||||
$roleDatas = get_user_roles($context, $USER->id, true);
|
||||
$roles = [];
|
||||
$roles = array();
|
||||
foreach ($roleDatas as $rolesData) {
|
||||
$roles[] = strtolower($rolesData->shortname);
|
||||
}
|
||||
|
@ -301,11 +379,13 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
|
|||
);
|
||||
}
|
||||
|
||||
$isreportallowed = !$isstudent || $pchkorgconfigmodel->show_report_for_student($cmid) === true;
|
||||
$isreportallowed = !$isstudent
|
||||
|| $pchkorgconfigmodel->show_report_for_student($cmid) === true
|
||||
|| $pchkorgconfigmodel->show_report_for_student($cmid) === null;
|
||||
|
||||
// Only for some type of account, method will call a remote HTTP API.
|
||||
// The API will be called only once, because result is static.
|
||||
// Also, there is timeout 2 seconds for response.
|
||||
// Also, there is timeout 8 seconds for response.
|
||||
// Even if service will be unavailable, method will try call API only once.
|
||||
// Also, we don't use raw user email.
|
||||
if (!$apiprovider->is_group_member($USER->email)) {
|
||||
|
@ -358,24 +438,46 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
|
|||
$action = $apiprovider->get_report_action($filerecord->textid);
|
||||
$reporttoken = $apiprovider->generate_api_token();
|
||||
$score = $filerecord->score;
|
||||
$title = sprintf(get_string('pchkorg_label_title', 'plagiarism_pchkorg'),
|
||||
$filerecord->textid,
|
||||
$score);
|
||||
$label = sprintf(get_string('pchkorg_label_result', 'plagiarism_pchkorg'), $filerecord->textid, $score);
|
||||
$isaienabled = '1' === $pchkorgconfigmodel->get_filter_for_module($cmid, 'pchkorg_check_ai');
|
||||
|
||||
if (isset($filerecord->scoreai) && $isaienabled) {
|
||||
$title = sprintf(
|
||||
get_string('pchkorg_label_title_ai', 'plagiarism_pchkorg'),
|
||||
$filerecord->textid,
|
||||
$score,
|
||||
$filerecord->scoreai
|
||||
);
|
||||
$label = sprintf(
|
||||
get_string('pchkorg_label_result_ai', 'plagiarism_pchkorg'),
|
||||
$filerecord->textid,
|
||||
$score,
|
||||
$filerecord->scoreai
|
||||
);
|
||||
} else {
|
||||
$title = sprintf(
|
||||
get_string('pchkorg_label_title', 'plagiarism_pchkorg'),
|
||||
$filerecord->textid,
|
||||
$score
|
||||
);
|
||||
$label = sprintf(
|
||||
get_string('pchkorg_label_result', 'plagiarism_pchkorg'),
|
||||
$filerecord->textid,
|
||||
$score
|
||||
);
|
||||
}
|
||||
|
||||
if ($score < 30) {
|
||||
$color = '#63ec80a1';
|
||||
$color = '#63EC80';
|
||||
} else if (30 < $score && $score < 60) {
|
||||
$color = '#f7b011';
|
||||
$color = '#F7B011';
|
||||
} else {
|
||||
$color = '#f04343';
|
||||
$color = '#F04343';
|
||||
}
|
||||
$jsdata = array(
|
||||
'id' => $filerecord->id,
|
||||
'title' => $title,
|
||||
'action' => $action,
|
||||
'token' => $reporttoken,
|
||||
'image' => $imgsrc,
|
||||
'label' => $label,
|
||||
'color' => $color,
|
||||
'isreportallowed' => $isreportallowed,
|
||||
|
@ -390,27 +492,27 @@ window.plagiarism_check_full_report = function (action, token) {
|
|||
const form = document.createElement('form');
|
||||
const element1 = document.createElement('input');
|
||||
const element2 = document.createElement('input');
|
||||
|
||||
|
||||
form.method = 'POST';
|
||||
form.target = '_blank';
|
||||
form.action = action;
|
||||
|
||||
|
||||
element1.value = 'moodle';
|
||||
element1.name = 'lms-type';
|
||||
element1.type = 'hidden';
|
||||
form.appendChild(element1);
|
||||
|
||||
|
||||
element2.value = token;
|
||||
element2.name = 'token';
|
||||
element2.type = 'hidden';
|
||||
form.appendChild(element2);
|
||||
|
||||
|
||||
document.body.appendChild(form);
|
||||
|
||||
|
||||
form.submit();
|
||||
};
|
||||
|
||||
require(['jquery'], function ($) {
|
||||
require(['jquery'], function ($) {
|
||||
$(function () {
|
||||
var spans = window.document.getElementsByClassName('plagiarism-pchkorg-widget');
|
||||
for (var s in spans) {
|
||||
|
@ -428,20 +530,20 @@ require(['jquery'], function ($) {
|
|||
a.setAttribute('href', '#');
|
||||
a.setAttribute('title', data.title);
|
||||
a.setAttribute('data-id', data.id);
|
||||
a.style.padding = '5px 3px';
|
||||
a.style.fontFamily = 'Roboto';
|
||||
a.style.fontStyle = 'normal';
|
||||
a.style.fontWeight = '400';
|
||||
a.style.fontSize = '16px';
|
||||
a.style.textAlign = 'center';
|
||||
a.style.padding = '4px 16px';
|
||||
a.style.textDecoration = 'none';
|
||||
a.style.backgroundColor = data.color;
|
||||
a.style.color = 'black';
|
||||
a.style.cursor = 'pointer';
|
||||
a.style.borderRadius = '3px 3px 3px 3px';
|
||||
a.style.borderRadius = '4px 4px 4px 4px';
|
||||
a.style.margin = '4px';
|
||||
a.style.display = 'inline-block';
|
||||
var label = document.createTextNode(data.label);
|
||||
var img = document.createElement('img');
|
||||
img.setAttribute('alt', 'PlagiarismCheck.org');
|
||||
img.setAttribute('src', data.image);
|
||||
img.setAttribute('width', '20');
|
||||
a.appendChild(img);
|
||||
a.appendChild(label);
|
||||
span.appendChild(a);
|
||||
break;
|
||||
|
@ -453,7 +555,7 @@ require(['jquery'], function ($) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(window.document.body).on('click', '.plagiarism-pchkorg-widget', function(e) {
|
||||
var id = $(e.target).closest('a').attr('data-id')
|
||||
if (id) {
|
||||
|
@ -548,65 +650,7 @@ display: inline-block;"
|
|||
* @throws dml_exception
|
||||
*/
|
||||
public function save_form_elements($data) {
|
||||
global $DB;
|
||||
|
||||
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
|
||||
|
||||
$config = $pchkorgconfigmodel->get_system_config('pchkorg_use');
|
||||
if ('1' != $config) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fields = array(
|
||||
'pchkorg_module_use',
|
||||
'pchkorg_min_percent',
|
||||
'pchkorg_include_citation',
|
||||
'pchkorg_include_referenced',
|
||||
'pchkorg_exclude_self_plagiarism',
|
||||
'pchkorg_student_can_see_widget',
|
||||
'pchkorg_student_can_see_report'
|
||||
);
|
||||
|
||||
$records = $DB->get_records('plagiarism_pchkorg_config', array(
|
||||
'cm' => $data->coursemodule
|
||||
));
|
||||
|
||||
$context = context_module::instance($data->coursemodule);
|
||||
$canchangeminpercent = has_capability(capability::CHANGE_MIN_PERCENT_FILTER, $context);
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$isfounded = false;
|
||||
foreach ($records as $record) {
|
||||
if ($record->name === $field) {
|
||||
$isfounded = true;
|
||||
if ($field === 'pchkorg_min_percent' && !$canchangeminpercent) {
|
||||
$DB->delete_records('plagiarism_pchkorg_config', array('id' => $record->id));
|
||||
break;
|
||||
}
|
||||
if ($field === 'pchkorg_min_percent' && 0 == $data->{$record->name}) {
|
||||
$DB->delete_records('plagiarism_pchkorg_config', array('id' => $record->id));
|
||||
break;
|
||||
}
|
||||
$record->value = $data->{$record->name};
|
||||
$DB->update_record('plagiarism_pchkorg_config', $record);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$isfounded && isset($data->{$field})) {
|
||||
if ($field === 'pchkorg_min_percent' && !$canchangeminpercent) {
|
||||
continue;
|
||||
}
|
||||
if ($field === 'pchkorg_min_percent' && 0 == $data->{$field}) {
|
||||
continue;
|
||||
}
|
||||
$insert = new \stdClass();
|
||||
$insert->cm = $data->coursemodule;
|
||||
$insert->name = $field;
|
||||
$insert->value = $data->{$field};
|
||||
|
||||
$DB->insert_record('plagiarism_pchkorg_config', $insert);
|
||||
}
|
||||
}
|
||||
return plagiarism_pchkorg_coursemodule_edit_post_actions($data, null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -676,6 +720,17 @@ display: inline-block;"
|
|||
public function event_handler($eventdata) {
|
||||
global $USER, $DB;
|
||||
|
||||
// Whitelist of supported events, ignore other.
|
||||
$issupportedevent = in_array($eventdata['eventtype'], array(
|
||||
"forum_attachment",
|
||||
"quiz_submitted",
|
||||
"assessable_submitted",
|
||||
"content_uploaded"
|
||||
));
|
||||
if (!$issupportedevent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$modulename = $eventdata['other']['modulename'];
|
||||
$allowedmodules = array('assign', 'mod_assign');
|
||||
// We support only assign module so just ignore all other.
|
||||
|
@ -702,7 +757,7 @@ display: inline-block;"
|
|||
$cmid = $eventdata['contextinstanceid'];
|
||||
// Remove the event if the course module no longer exists.
|
||||
$cm = get_coursemodule_from_id($eventdata['other']['modulename'], $cmid);
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
if (!$cm) {
|
||||
return true;
|
||||
}
|
||||
|
@ -715,25 +770,39 @@ display: inline-block;"
|
|||
|
||||
// Only for some type of account, method will call a remote HTTP API.
|
||||
// The API will be called only once, because result is static.
|
||||
// Also, there is timeout 2 seconds for response.
|
||||
// Also, there is timeout 8 seconds for response.
|
||||
// Even if service is unavailable, method will try call only once.
|
||||
// Also, we don't use raw users email.
|
||||
if (!$apiprovider->is_group_member($USER->email)) {
|
||||
return true;
|
||||
$ismemberresponse = $apiprovider->get_group_member_response($USER->email);
|
||||
if (!$ismemberresponse->is_member) {
|
||||
if ($ismemberresponse->is_auto_registration_enabled) {
|
||||
$name = $USER->firstname . ' ' . $USER->lastname;
|
||||
$roleDatas = get_user_roles($context, $USER->id, true);
|
||||
$roles = array();
|
||||
foreach ($roleDatas as $rolesData) {
|
||||
$roles[] = strtolower($rolesData->shortname);
|
||||
}
|
||||
// Moodle has multiple roles in courses.
|
||||
$isstudent = !in_array('teacher', $roles)
|
||||
&& !in_array('editingteacher', $roles)
|
||||
&& !in_array('managerteacher', $roles);
|
||||
$isregistered = $apiprovider->auto_registrate_member($name, $USER->email, $isstudent ? 3 : 2);
|
||||
if (!$isregistered) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Set the author and submitter.
|
||||
$submitter = $eventdata['userid'];
|
||||
$author = (!empty($eventdata['relateduserid'])) ? $eventdata['relateduserid'] : $eventdata['userid'];
|
||||
|
||||
// Related user ID will be NULL if an instructor submits on behalf of a student who is in a group.
|
||||
// To get around this, we get the group ID, get the group members and set the author as the first student in the group.
|
||||
if ((empty($eventdata['relateduserid'])) && ($eventdata['other']['modulename'] == 'assign')
|
||||
&& has_capability('mod/assign:editothersubmission', context_module::instance($cm->id), $submitter)) {
|
||||
&& has_capability('mod/assign:editothersubmission', $context, $submitter)) {
|
||||
$moodlesubmission = $DB->get_record('assign_submission', array('id' => $eventdata['objectid']), 'id, groupid');
|
||||
if (!empty($moodlesubmission->groupid)) {
|
||||
$author = $this->get_first_group_author($cm->course, $moodlesubmission->groupid);
|
||||
}
|
||||
}
|
||||
|
||||
if ($eventdata['other']['modulename'] === 'forum'
|
||||
|
@ -903,7 +972,7 @@ display: inline-block;"
|
|||
$moodlesubmission = $DB->get_record('assign_submission', array('id' => $eventdata['objectid']), 'id');
|
||||
|
||||
$moodletextsubmission = $DB->get_record('assignsubmission_onlinetext',
|
||||
array('submission' => $moodlesubmission->id), 'onlinetext');
|
||||
array('submission' => $eventdata['objectid']), 'onlinetext');
|
||||
|
||||
if ($moodletextsubmission) {
|
||||
$eventdata['other']['content'] = $moodletextsubmission->onlinetext;
|
||||
|
@ -911,8 +980,8 @@ display: inline-block;"
|
|||
|
||||
$filesconditions = array(
|
||||
'component' => 'assignsubmission_file',
|
||||
'itemid' => $moodlesubmission->id,
|
||||
'userid' => $author
|
||||
'itemid' => $eventdata['objectid'],
|
||||
'userid' => $eventdata['userid']
|
||||
);
|
||||
|
||||
$moodlefiles = $DB->get_records('files', $filesconditions);
|
||||
|
@ -1065,7 +1134,7 @@ display: inline-block;"
|
|||
} else {
|
||||
$minpercent = $systemminpercent;
|
||||
}
|
||||
$filters = [
|
||||
$filters = array(
|
||||
'include_references' => $pchkorgconfigmodel->get_filter_for_module(
|
||||
$cm->id,
|
||||
'pchkorg_include_referenced'
|
||||
|
@ -1078,7 +1147,7 @@ display: inline-block;"
|
|||
$cm->id,
|
||||
'pchkorg_exclude_self_plagiarism'
|
||||
),
|
||||
];
|
||||
);
|
||||
if ($minpercent) {
|
||||
$filters['source_min_percent'] = $minpercent;
|
||||
}
|
||||
|
@ -1096,11 +1165,13 @@ display: inline-block;"
|
|||
|
||||
if ($cm->modname === 'quiz') {
|
||||
if ($filedb->fileid === null) {
|
||||
|
||||
$questionanswers = $DB->get_records_sql(
|
||||
"SELECT {question_attempts}.responsesummary "
|
||||
." FROM {question_attempts} "
|
||||
." INNER JOIN {question} on {question}.id = {question_attempts}.questionid "
|
||||
." WHERE {question_attempts}.questionusageid = ? AND {question}.qtype = 'essay' ", array(
|
||||
." INNER JOIN {question} on {question}.id = {question_attempts}.questionid "
|
||||
." INNER JOIN {quiz_attempts} on {quiz_attempts}.uniqueid = {question_attempts}.questionusageid "
|
||||
." WHERE {quiz_attempts}.id= ? AND {question}.qtype = 'essay' ", array(
|
||||
$filedb->itemid
|
||||
)
|
||||
);
|
||||
|
@ -1119,7 +1190,7 @@ display: inline-block;"
|
|||
html_to_text($content, 75, false),
|
||||
'plain/text',
|
||||
sprintf('%s-quiz.txt', $filedb->itemid),
|
||||
$filters,
|
||||
$filters
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -1188,7 +1259,7 @@ display: inline-block;"
|
|||
html_to_text($content, 75, false),
|
||||
'plain/text',
|
||||
sprintf('%s-quiz.txt', $filedb->itemid),
|
||||
$filters,
|
||||
$filters
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1246,7 +1317,7 @@ display: inline-block;"
|
|||
html_to_text($content, 75, false),
|
||||
'plain/text',
|
||||
sprintf('%s-submussion.txt', $moodletextsubmission->id),
|
||||
$filters,
|
||||
$filters
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -1336,6 +1407,7 @@ display: inline-block;"
|
|||
$filedbnew->state = 5;
|
||||
$filedbnew->reportid = $report->id;
|
||||
$filedbnew->score = $report->percent;
|
||||
$filedbnew->scoreai = $report->percent_ai;
|
||||
|
||||
$DB->update_record('plagiarism_pchkorg_files', $filedbnew);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,10 @@ if (($data = $mform->get_data()) && confirm_sesskey()) {
|
|||
|
||||
foreach ($data as $field => $value) {
|
||||
if (strpos($field, 'pchkorg') === 0) {
|
||||
set_config($field, $value, 'plagiarism');
|
||||
if ('pchkorg_use' === $field) {
|
||||
set_config('enabled', $value, 'plagiarism_pchkorg');
|
||||
}
|
||||
set_config($field, $value, 'plagiarism_pchkorg');
|
||||
$pchkorgconfigmodel->set_system_config($field, $value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,9 +26,9 @@ defined('MOODLE_INTERNAL') || die();
|
|||
if (!isset($plugin)) {
|
||||
$plugin = new stdClass();
|
||||
}
|
||||
$plugin->version = 2022072914;
|
||||
$plugin->version = 2024030512;
|
||||
$plugin->requires = 2020061501; // Requires Moodle 3.9 .
|
||||
$plugin->release = 'v3.10.2';
|
||||
$plugin->release = 'v3.14.7';
|
||||
$plugin->component = 'plagiarism_pchkorg';
|
||||
$plugin->maturity = MATURITY_STABLE;
|
||||
$plugin->dependencies = array(
|
||||
|
|
Loading…
Reference in New Issue