1
0
mirror of https://github.com/PlagiarismCheck/moodle-plagiarism_pchkorg.git synced 2024-12-22 04:10:07 +00:00

Use moodle task.

This commit is contained in:
Jane Adelmann 2019-04-05 19:25:06 +03:00
parent 070672f974
commit dfd7195f91
No known key found for this signature in database
GPG Key ID: 4CCF39DF30B8AF72
18 changed files with 676 additions and 486 deletions

View File

@ -21,19 +21,35 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
defined('MOODLE_INTERNAL') || die(); if (!defined('MOODLE_INTERNAL')) {
die('Direct access to this script is forbidden.'); // It must be included from a Moodle page.
}
require_once($CFG->dirroot . '/plagiarism/pchkorg/lib.php'); require_once($CFG->dirroot.'/plagiarism/pchkorg/lib.php');
/**
* This class subscribe to events.
*/
class plagiarism_pchkorg_observer { class plagiarism_pchkorg_observer {
/**
* Handle the course_module_deleted event.
* @param \core\event\course_module_deleted $event
*/
public static function course_module_deleted(
\core\event\course_module_deleted $event) {
global $DB;
$eventdata = $event->get_data();
$DB->delete_records('plagiarism_pchkorg_files', array('cm' => $eventdata['contextinstanceid']));
$DB->delete_records('plagiarism_pchkorg_config', array('cm' => $eventdata['contextinstanceid']));
}
/** /**
* Handle the assignment assessable_uploaded event. * Handle the assignment assessable_uploaded event.
*
* @param \assignsubmission_file\event\assessable_uploaded $event * @param \assignsubmission_file\event\assessable_uploaded $event
*/ */
public static function assignsubmission_file_uploaded( public static function assignsubmission_file_uploaded(
\assignsubmission_file\event\assessable_uploaded $event) { \assignsubmission_file\event\assessable_uploaded $event) {
$eventdata = $event->get_data(); $eventdata = $event->get_data();
$eventdata['eventtype'] = 'file_uploaded'; $eventdata['eventtype'] = 'file_uploaded';
$eventdata['other']['modulename'] = 'assign'; $eventdata['other']['modulename'] = 'assign';
@ -44,11 +60,10 @@ class plagiarism_pchkorg_observer {
/** /**
* Handle the assignment assessable_uploaded event. * Handle the assignment assessable_uploaded event.
*
* @param \assignsubmission_onlinetext\event\assessable_uploaded $event * @param \assignsubmission_onlinetext\event\assessable_uploaded $event
*/ */
public static function assignsubmission_onlinetext_uploaded( public static function assignsubmission_onlinetext_uploaded(
\assignsubmission_onlinetext\event\assessable_uploaded $event) { \assignsubmission_onlinetext\event\assessable_uploaded $event) {
$eventdata = $event->get_data(); $eventdata = $event->get_data();
$eventdata['eventtype'] = 'content_uploaded'; $eventdata['eventtype'] = 'content_uploaded';
$eventdata['other']['modulename'] = 'assign'; $eventdata['other']['modulename'] = 'assign';
@ -59,11 +74,10 @@ class plagiarism_pchkorg_observer {
/** /**
* Handle the assignment assessable_submitted event. * Handle the assignment assessable_submitted event.
*
* @param \mod_assign\event\assessable_submitted $event * @param \mod_assign\event\assessable_submitted $event
*/ */
public static function assignsubmission_submitted( public static function assignsubmission_submitted(
\mod_assign\event\assessable_submitted $event) { \mod_assign\event\assessable_submitted $event) {
$eventdata = $event->get_data(); $eventdata = $event->get_data();
$eventdata['eventtype'] = 'assessable_submitted'; $eventdata['eventtype'] = 'assessable_submitted';
$eventdata['other']['modulename'] = 'assign'; $eventdata['other']['modulename'] = 'assign';

View File

@ -24,25 +24,34 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
/** /**
* Class plagiarism_pchkorg_api_provider * Class provider HTTP-API methods.
*/ */
class plagiarism_pchkorg_api_provider { class plagiarism_pchkorg_api_provider {
/** /**
* @var * Auth token.
*
* @var string
*/ */
private $token; private $token;
/** /**
* Url of api.
*
* @var string * @var string
*/ */
private $endpoint; private $endpoint;
/** /**
* @var * Last api error.
*
* @var string|null
*/ */
private $lasterror; private $lasterror;
/** /**
* Fetch last api error.
*
* @return mixed * @return mixed
*/ */
public function get_last_error() { public function get_last_error() {
@ -50,6 +59,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Setup last api error.
*
* @param mixed $lasterror * @param mixed $lasterror
*/ */
public function set_last_error($lasterror) { public function set_last_error($lasterror) {
@ -57,19 +68,19 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* plagiarism_pchkorg_api_provider constructor. * Constructor for api provider.
* *
* @param $token * @param $token
* @param string $endpoint * @param string $endpoint
*/ */
public function __construct($token, $endpoint = 'https://plagiarismcheck.org') { public function __construct($token, $endpoint = 'https://plagiarismcheck.org') {
$this->endpoint = 'http://plagcheck.local';
$this->token = $token; $this->token = $token;
$this->endpoint = $endpoint; $this->endpoint = $endpoint;
} }
/** /**
* Send text for originality check.
*
* @param $authorhash * @param $authorhash
* @param $cousereid * @param $cousereid
* @param $assignmentid * @param $assignmentid
@ -78,6 +89,7 @@ class plagiarism_pchkorg_api_provider {
* @param $content * @param $content
* @param $mime * @param $mime
* @param $filename * @param $filename
*
* @return |null * @return |null
*/ */
public function send_group_text($authorhash, $cousereid, $assignmentid, $submissionid, $attachmentid, $content, $mime, public function send_group_text($authorhash, $cousereid, $assignmentid, $submissionid, $attachmentid, $content, $mime,
@ -124,6 +136,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Build HTTP body of request.
*
* @param $boundary * @param $boundary
* @param $authorhash * @param $authorhash
* @param $cousereid * @param $cousereid
@ -155,6 +169,8 @@ class plagiarism_pchkorg_api_provider {
$body .= $this->get_part('attachment_id', $attachmentid, $boundary); $body .= $this->get_part('attachment_id', $attachmentid, $boundary);
$body .= $this->get_part('filename', $filename, $boundary); $body .= $this->get_part('filename', $filename, $boundary);
$body .= $this->get_part('language', 'en', $boundary); $body .= $this->get_part('language', 'en', $boundary);
$body .= $this->get_part('skip_english_words_validation', '1', $boundary);
$body .= $this->get_part('skip_percentage_words_validation', '1', $boundary);
$body .= $this->get_file_part('content', $content, $mime, $filename, $boundary); $body .= $this->get_file_part('content', $content, $mime, $filename, $boundary);
$body .= '--' . $boundary . '--' . $eol; $body .= '--' . $boundary . '--' . $eol;
@ -162,12 +178,15 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Send text to the service for check.
*
* @param $content * @param $content
* @param $mime * @param $mime
* @param $filename * @param $filename
* @return |null * @return |null
*/ */
public function send_text($content, $mime, $filename) { public function send_text($content, $mime, $filename) {
$boundary = sprintf('PLAGCHECKBOUNDARY-%s', uniqid(time())); $boundary = sprintf('PLAGCHECKBOUNDARY-%s', uniqid(time()));
$curl = new curl(); $curl = new curl();
@ -201,6 +220,32 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
*
* Method send information to service thar agreement had been accepted.
* Method will be called only for personal account type.
*
*/
public function save_accepted_agreement() {
$curl = new curl();
$curl->post(
$this->endpoint . '/api/v1/agreement/create/moodle-plugin/2019-04-11/',
'',
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(),
),
)
);
}
/**
* Build part of HTTP body.
*
* @param $name * @param $name
* @param $value * @param $value
* @param $boundary * @param $boundary
@ -217,6 +262,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Build part of HTTP body. This part contains file.
*
* @param $name * @param $name
* @param $value * @param $value
* @param $mime * @param $mime
@ -237,6 +284,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Build body for http-request.
*
* @param $boundary * @param $boundary
* @param $content * @param $content
* @param $mime * @param $mime
@ -248,6 +297,8 @@ class plagiarism_pchkorg_api_provider {
$body = ''; $body = '';
$body .= $this->get_part('language', 'en', $boundary); $body .= $this->get_part('language', 'en', $boundary);
$body .= $this->get_part('skip_english_words_validation', '1', $boundary);
$body .= $this->get_part('skip_percentage_words_validation', '1', $boundary);
$body .= $this->get_file_part('text', $content, $mime, $filename, $boundary); $body .= $this->get_file_part('text', $content, $mime, $filename, $boundary);
$body .= '--' . $boundary . '--' . $eol; $body .= '--' . $boundary . '--' . $eol;
@ -255,15 +306,20 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Convert user email to sha256 salted hash.
*
* @param $email * @param $email
* @return string * @return string
*/ */
public function user_email_to_hash($email) { public function user_email_to_hash($email) {
// We don't send raw user email to service. // We don't send raw user email to the service.
return hash('sha256', $this->token . $email); return hash('sha256', $this->token . $email);
} }
/** /**
* Check type of service account.
* There are two types of accounts: personal and group.
*
* @return bool * @return bool
*/ */
public function is_group_token() { public function is_group_token() {
@ -271,6 +327,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Check that user belongs to group when it is group account.
*
* @param string $email * @param string $email
* @return bool * @return bool
*/ */
@ -307,8 +365,11 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Check status of document.
* If document has been checked, state is 5.
*
* @param $textid * @param $textid
* @return |null * @return object|null
*/ */
public function check_text($textid) { public function check_text($textid) {
$curl = new curl(); $curl = new curl();
@ -333,6 +394,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Build url for the api.
*
* @param $id * @param $id
* @return string * @return string
*/ */
@ -341,6 +404,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* Generate token for API auth.
*
* @return string * @return string
*/ */
public function generate_api_token() { public function generate_api_token() {
@ -354,6 +419,8 @@ class plagiarism_pchkorg_api_provider {
} }
/** /**
* List of supported mime.
*
* @param $mime * @param $mime
* @return bool * @return bool
*/ */
@ -364,7 +431,17 @@ class plagiarism_pchkorg_api_provider {
'application/rtf', 'application/rtf',
'application/vnd.oasis.opendocument.text', 'application/vnd.oasis.opendocument.text',
'text/plain', 'text/plain',
'plain/text',
'application/pdf', 'application/pdf',
), true); ), true);
} }
/**
* Return maximum size of document.
*
* @return int
*/
public function get_max_filesize() {
return 20 * 1048576;
}
} }

View File

@ -29,6 +29,10 @@ defined('MOODLE_INTERNAL') || die();
class plagiarism_pchkorg_config_model { class plagiarism_pchkorg_config_model {
/** /**
*
* Check if plugin is enable for some specific module.
* Result is static.
*
* @param $module * @param $module
* @return bool * @return bool
*/ */
@ -60,6 +64,9 @@ class plagiarism_pchkorg_config_model {
} }
/** /**
*
* Save plugin settings.
*
* @param $name * @param $name
* @param $value * @param $value
*/ */
@ -104,6 +111,10 @@ class plagiarism_pchkorg_config_model {
} }
/** /**
*
* Fetch all plugin settings as array.
* Result is static.
*
* @return array * @return array
*/ */
public function get_all_system_config() { public function get_all_system_config() {

View File

@ -57,10 +57,14 @@ class provider implements
'cm' => 'privacy:metadata:plagiarism_pchkorg_files:cm', 'cm' => 'privacy:metadata:plagiarism_pchkorg_files:cm',
'fileid' => 'privacy:metadata:plagiarism_pchkorg_files:fileid', 'fileid' => 'privacy:metadata:plagiarism_pchkorg_files:fileid',
'userid' => 'privacy:metadata:plagiarism_pchkorg_files:userid', 'userid' => 'privacy:metadata:plagiarism_pchkorg_files:userid',
'state' => 'privacy:metadata:plagiarism_pchkorg_files:state',
'score' => 'privacy:metadata:plagiarism_pchkorg_files:score', 'score' => 'privacy:metadata:plagiarism_pchkorg_files:score',
'created_at' => 'privacy:metadata:plagiarism_pchkorg_files:created_at',
'textid' => 'privacy:metadata:plagiarism_pchkorg_files:textid', 'textid' => 'privacy:metadata:plagiarism_pchkorg_files:textid',
'reportid' => 'privacy:metadata:plagiarism_pchkorg_files:reportid', 'reportid' => 'privacy:metadata:plagiarism_pchkorg_files:reportid',
'signature' => 'privacy:metadata:plagiarism_pchkorg_files:signature', 'signature' => 'privacy:metadata:plagiarism_pchkorg_files:signature',
'attempt' => 'privacy:metadata:plagiarism_pchkorg_files:attempt',
'itemid' => 'privacy:metadata:plagiarism_pchkorg_files:itemid',
), ),
'privacy:metadata:plagiarism_pchkorg_files' 'privacy:metadata:plagiarism_pchkorg_files'

View File

@ -21,24 +21,37 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace plagiarism_pchkorg\task;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
if (empty($error)) { /**
$PAGE->requires->js_init_code('window.document.getElementById("plagiarism_pchkorg_report_id").submit();', false); * Send queued submissions to Turnitin.
echo $OUTPUT->header(); */
?> class send_submissions extends \core\task\scheduled_task {
<form id="plagiarism_pchkorg_report_id" action="<?php echo htmlspecialchars($action) ?>" method="post">
<input type="hidden" name="token" value="<?php echo htmlspecialchars($token) ?>"/>
<input type="hidden" name="lms-type" value="moodle"/>
<input type="submit" value="<?php echo get_string('pchkorg_check_for_plagiarism_report', 'plagiarism_pchkorg'); ?>">
</form>
<?php
} else {
echo $OUTPUT->header();
?>
<h2>Error: <?php
echo htmlspecialchars($error) ?></h2>
<?php
}
echo $OUTPUT->footer(); /**
* Name of the task.
*
* @return string
* @throws \coding_exception
*/
public function get_name() {
return get_string('sendqueuedsubmissions', 'plagiarism_pchkorg');
}
/**
* Task execution.
*
* @throws \coding_exception
* @throws \dml_exception
*/
public function execute() {
global $CFG;
require_once($CFG->dirroot.'/plagiarism/pchkorg/lib.php');
$plugin = new \plagiarism_plugin_pchkorg();
$plugin->cron_send_submissions();
}
}

View File

@ -21,32 +21,36 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
namespace plagiarism_pchkorg\task;
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
/** /**
* Class plagiarism_pchkorg_url_generator * Update report Scores from Turnitin.
*/ */
class plagiarism_pchkorg_url_generator { class update_reports extends \core\task\scheduled_task {
/** /**
* @param $cmid * Get a name of task
* @param $fileid *
* @return moodle_url * @return string
* @throws moodle_exception * @throws \coding_exception
*/ */
public function get_check_url($cmid, $fileid) { public function get_name() {
return new moodle_url(sprintf( return get_string('updatereportscores', 'plagiarism_pchkorg');
'/plagiarism/pchkorg/page/report.php?cmid=%s&file=%s',
intval($cmid),
intval($fileid)
)
);
} }
/** /**
* @return moodle_url * Task execution.
* @throws moodle_exception *
* @throws \dml_exception
*/ */
public function get_status_url() { public function execute() {
return new moodle_url('/plagiarism/pchkorg/page/status.php'); global $CFG;
require_once($CFG->dirroot.'/plagiarism/pchkorg/lib.php');
$plugin = new \plagiarism_plugin_pchkorg();
$plugin->cron_update_reports();
} }
} }

View File

@ -23,37 +23,21 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
echo $OUTPUT->header(); $observers = array (
?> array(
'eventname' => '\assignsubmission_file\event\assessable_uploaded',
<style> 'callback' => 'plagiarism_pchkorg_observer::assignsubmission_file_uploaded'
.plagiarism-preview-content { ),
width: 800px; array(
height: 400px; 'eventname' => '\assignsubmission_onlinetext\event\assessable_uploaded',
overflow-y: scroll; 'callback' => 'plagiarism_pchkorg_observer::assignsubmission_onlinetext_uploaded'
} ),
array(
.plagiarism-preview-content-inner { 'eventname' => '\mod_assign\event\assessable_submitted',
/*white-space: pre;*/ 'callback' => 'plagiarism_pchkorg_observer::assignsubmission_submitted'
} ),
</style> array(
<br/> 'eventname' => '\core\event\course_module_deleted',
<div class="plagiarism-preview-content"> 'callback' => 'plagiarism_pchkorg_observer::course_module_deleted'
<div class="plagiarism-preview-content-inner"> ),
<?php );
echo nl2br(htmlspecialchars($content, ENT_COMPAT | ENT_HTML401, $encoding = 'UTF-8')) ?>
</div>
</div>
<br/>
<div>
<?php
if ($issupported) {
echo $form->display();
} else {
echo 'file not supported';
}
?>
</div>
<?php
echo $OUTPUT->footer();

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="plagiarism/pchkorg/db" VERSION="20190318" COMMENT="XMLDB file for Moodle plagiarism/pchkorg plugin." <XMLDB PATH="plagiarism/pchkorg/db" VERSION="20190406" COMMENT="XMLDB file for Moodle plagiarism/pchkorg plugin."
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
> >
@ -8,14 +8,16 @@
<FIELDS> <FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/> <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="cm" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="cm" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="fileid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="fileid" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <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="state" TYPE="int" LENGTH="3" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="score" TYPE="float" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="score" TYPE="float" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="created_at" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false"/> <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="textid" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="reportid" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="reportid" TYPE="int" LENGTH="11" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="signature" TYPE="char" LENGTH="40" NOTNULL="false" DEFAULT="NULL" SEQUENCE="false" COMMENT="Sha1 signature of content"/> <FIELD NAME="signature" TYPE="char" LENGTH="40" NOTNULL="false" DEFAULT="NULL" SEQUENCE="false" COMMENT="Sha1 signature of content"/>
<FIELD NAME="attempt" TYPE="int" LENGTH="5" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
</FIELDS> </FIELDS>
<KEYS> <KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/> <KEY NAME="primary" TYPE="primary" FIELDS="id"/>

View File

@ -23,24 +23,23 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/formslib.php'); $tasks = array(
array(
/** 'classname' => 'plagiarism_pchkorg\task\update_reports',
* Class send_text_form 'blocking' => 0,
*/ 'minute' => '*/5',
class send_text_form extends moodleform { 'hour' => '*',
'day' => '*',
/** 'dayofweek' => '*',
* @throws coding_exception 'month' => '*'
*/ ),
public function definition() { array(
$mform = $this->_form; // Don't forget the underscore! 'classname' => 'plagiarism_pchkorg\task\send_submissions',
'blocking' => 0,
$mform->addElement('hidden', 'fileid', ''); 'minute' => '*/5',
$mform->setType('fileid', PARAM_INT); 'hour' => '*',
$mform->addElement('hidden', 'cmid', ''); 'day' => '*',
$mform->setType('cmid', PARAM_INT); 'dayofweek' => '*',
'month' => '*'
$this->add_action_buttons(false, get_string('pchkorg_submit', 'plagiarism_pchkorg')); ),
} );
}

View File

@ -24,11 +24,14 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
/** /**
* Class plagiarism_pchkorg_setup_form * Class defined plugin settings form.
*/ */
class plagiarism_pchkorg_setup_form extends moodleform { class plagiarism_pchkorg_setup_form extends moodleform {
/** /**
*
* Method defined plugin settings form.
*
* @throws coding_exception * @throws coding_exception
*/ */
public function definition() { public function definition() {

View File

@ -36,18 +36,23 @@ $string['pchkorg_submit'] = 'Submit';
$string['pchkorg_check_for_plagiarism_report'] = 'View report'; $string['pchkorg_check_for_plagiarism_report'] = 'View report';
$string['savedconfigsuccess'] = 'Settings had been changed'; $string['savedconfigsuccess'] = 'Settings had been changed';
$string['pchkorg_check_for_plagiarism'] = 'Check for plagiarism'; $string['pchkorg_check_for_plagiarism'] = 'Check for plagiarism';
$string['pchkorg_disclosure'] = 'Submission will be sent to plagiarismcheck.org for check'; $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 &amp; Conditions</a> '
. 'and <a target="_blank" href="https://plagiarismcheck.org/privacy-policy/">Privacy Policy</a>.';
$string['privacy:metadata:plagiarism_pchkorg_files'] = $string['privacy:metadata:plagiarism_pchkorg_files'] =
'Table with information about a file within moodle system belonge to a check in plagiarismcheck.org system.'; 'Table with information about a file within moodle system belonge to a check in plagiarismcheck.org system.';
$string['privacy:metadata:plagiarism_pchkorg_files:cm'] = 'Course module identity '; $string['privacy:metadata:plagiarism_pchkorg_files:cm'] = 'Course module identity ';
$string['privacy:metadata:plagiarism_pchkorg_files:fileid'] = 'Identity of a submitted file'; $string['privacy:metadata:plagiarism_pchkorg_files:fileid'] = 'Identity of a submitted file';
$string['privacy:metadata:plagiarism_pchkorg_files:userid'] = 'Identity of user who submit file'; $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:score'] = 'Originality 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:textid'] = 'Identity of originality check';
$string['privacy:metadata:plagiarism_pchkorg_files:reportid'] = 'Identity of originality report'; $string['privacy:metadata:plagiarism_pchkorg_files:reportid'] = 'Identity of originality report';
$string['privacy:metadata:plagiarism_pchkorg_files:signature'] = 'Sha1 signature of content'; $string['privacy:metadata:plagiarism_pchkorg_files:signature'] = 'Sha1 signature of content';
$string['privacy:metadata:plagiarism_pchkorg_files:attempt'] = 'Amount of sending attempts';
$string['privacy:metadata:plagiarism_pchkorg_files:itemid'] = 'Identity of submission';
$string['privacy:metadata:plagiarism_pchkorg_config'] = 'Table with module settings'; $string['privacy:metadata:plagiarism_pchkorg_config'] = 'Table with module settings';
$string['privacy:metadata:plagiarism_pchkorg_config:cm'] = 'Course module identity'; $string['privacy:metadata:plagiarism_pchkorg_config:cm'] = 'Course module identity';
$string['privacy:metadata:plagiarism_pchkorg_config:name'] = 'Name of option'; $string['privacy:metadata:plagiarism_pchkorg_config:name'] = 'Name of option';
@ -56,6 +61,11 @@ $string['privacy:metadata:plagiarism_pchkorg_config:value'] = 'Value of option';
$string['privacy:metadata:plagiarism_pchkorg'] = 'Service for originality check plagiarismcheck.org'; $string['privacy:metadata:plagiarism_pchkorg'] = 'Service for originality check plagiarismcheck.org';
$string['privacy:metadata:plagiarism_pchkorg:file'] = $string['privacy:metadata:plagiarism_pchkorg:file'] =
'Submission attachment for originality checkprivacy:metadata:plagiarism_pchkorg'; 'Submission attachment for originality checkprivacy:metadata:plagiarism_pchkorg';
$string['pchkorg:enable'] = 'Enable or Disable plugin'; $string['pchkorg:enable'] = 'Enable or Disable plugin';
$string['privacy:metadata:core_files'] = 'We need a content of submission, for originality check'; $string['privacy:metadata:core_files'] = 'We need a content of submission, for originality check';
$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_sent'] = 'ID: %s Sent';
$string['pchkorg_label_queued'] = 'In queue';

464
lib.php
View File

@ -29,7 +29,6 @@ require_once($CFG->dirroot . '/plagiarism/lib.php');
require_once($CFG->libdir . '/filelib.php'); require_once($CFG->libdir . '/filelib.php');
require_once($CFG->libdir . '/accesslib.php'); require_once($CFG->libdir . '/accesslib.php');
require_once(__DIR__ . '/classes/plagiarism_pchkorg_config_model.php'); require_once(__DIR__ . '/classes/plagiarism_pchkorg_config_model.php');
require_once(__DIR__ . '/classes/plagiarism_pchkorg_url_generator.php');
require_once(__DIR__ . '/classes/plagiarism_pchkorg_api_provider.php'); require_once(__DIR__ . '/classes/plagiarism_pchkorg_api_provider.php');
/** /**
@ -37,25 +36,30 @@ require_once(__DIR__ . '/classes/plagiarism_pchkorg_api_provider.php');
*/ */
class plagiarism_plugin_pchkorg extends plagiarism_plugin { class plagiarism_plugin_pchkorg extends plagiarism_plugin {
/** /**
* hook to allow plagiarism specific information to be displayed beside a submission * hook to allow plagiarism specific information to be displayed beside a submission.
* *
* @param array $linkarraycontains all relevant information for the plugin to generate a link * @param array $linkarraycontains all relevant information for the plugin to generate a link
* @return string * @return string
* *
*/ */
public function get_links($linkarray) { public function get_links($linkarray) {
global $DB, $USER; global $DB, $USER;
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model(); $pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
$urlgenerator = new plagiarism_pchkorg_url_generator();
$apitoken = $pchkorgconfigmodel->get_system_config('pchkorg_token'); $apitoken = $pchkorgconfigmodel->get_system_config('pchkorg_token');
$apiprovider = new plagiarism_pchkorg_api_provider($apitoken); $apiprovider = new plagiarism_pchkorg_api_provider($apitoken);
$cmid = $linkarray['cmid']; $cmid = $linkarray['cmid'];
$file = $linkarray['file']; if (array_key_exists('file', $linkarray)) {
$file = $linkarray['file'];
} else {
// Online text submission.
$file = null;
}
// We can do nothing with submissions which we can not handle. // We can do nothing with submissions which we can not handle.
if (!$apiprovider->is_supported_mime($file->get_mimetype())) { if (null !== $file && !$apiprovider->is_supported_mime($file->get_mimetype())) {
return ''; return '';
} }
@ -78,8 +82,8 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
// Only for some type of account, method will call a remote HTTP API. // Only for some type of account, method will call a remote HTTP API.
// The API will be called only once, because result is static. // The API will be called only once, because result is static.
// Also, there is timeout 2 seconds for response. // Also, there is timeout 2 seconds for response.
// Even if service is unavailable, method will try call only once. // Even if service will be unavailable, method will try call API only once.
// Also, we don't use use raw user email. // Also, we don't use raw user email.
if (!$apiprovider->is_group_member($USER->email)) { if (!$apiprovider->is_group_member($USER->email)) {
return ''; return '';
} }
@ -91,28 +95,94 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
$where = new \stdClass(); $where = new \stdClass();
$where->cm = $cmid; $where->cm = $cmid;
$where->fileid = $file->get_id(); if ($file === null) {
$where->signature = sha1($linkarray['content']);
$filerecord = $DB->get_record('plagiarism_pchkorg_files', (array) $where); $where->fileid = null;
$checkurl = $urlgenerator->get_check_url($cmid, $file->get_id());
if ($filerecord) {
$label = sprintf('%.2f', $filerecord->score) . '%';
$link = sprintf(' <a href="%s" target="_blank">( %s )</a> ', $checkurl->__toString(), $label);
} else { } else {
$label = get_string('pchkorg_check_for_plagiarism', 'plagiarism_pchkorg'); $where->fileid = $file->get_id();
$link = sprintf(' <a href="%s">( %s )</a> ', $checkurl->__toString(), $label);
} }
return $link; $filerecords = $DB->get_records('plagiarism_pchkorg_files', (array) $where,
'id', '*', 0, 1);
if ($filerecords) {
$filerecord = end($filerecords);
$img = new moodle_url('/plagiarism/pchkorg/pix/icon.png');
$imgsrc = $img->__toString();
// Text had been successfully checked.
if ($filerecord->state == 5) {
$action = $apiprovider->get_report_action($filerecord->textid);
$reporttoken = $apiprovider->generate_api_token();
$formid = 'plagiarism_pchkorg_report_id_' . $filerecord->id;
$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);
if ($score < 30) {
$color = '#63ec80a1';
} else if (30 < $score && $score < 60) {
$color = '#f7b011';
} else {
$color = '#f04343';
}
return '
<a style="padding: 5px 3px;
text-decoration: none;
background-color: ' . $color . ';
color: black;
cursor: pointer;
border-radius: 3px 3px 3px 3px;
margin: 4px;"
href="#" title="' . $title . '"
class="plagiarism_pchkorg_report_id_score"
onclick="document.getElementById(\'' . $formid . '\').submit(); return false;">
<img src="' . $imgsrc . '" alt="logo" width="20px;" />
' . $label . '
</a><form target="_blank" id="' . $formid . '" action="' . $action . '" method="post">
<input type="hidden" name="token" value="' . $reporttoken . '"/>
<input type="hidden" name="lms-type" value="moodle"/>
</form>';
} else if ($filerecord->state == 10) {
$label = get_string('pchkorg_label_queued', 'plagiarism_pchkorg');
return '
<span style="padding: 5px 3px;
text-decoration: none;
background-color: #eeeded;
color: black;
border-radius: 3px 3px 3px 3px;
margin: 4px;"
href="#" class="plagiarism_pchkorg_report_id_score">
<img src="' . $imgsrc . '" alt="logo" width="20px;" />
' . $label . '
</span>';
} else if ($filerecord->state == 12) {
$label = sprintf(get_string('pchkorg_label_sent', 'plagiarism_pchkorg'), $filerecord->textid);
return '
<span style="padding: 5px 3px;
text-decoration: none;
background-color: #eeeded;
color: black;
border-radius: 3px 3px 3px 3px;
margin: 4px;"
href="#" class="plagiarism_pchkorg_report_id_score">
<img src="' . $imgsrc . '" alt="logo" width="20px;" />
' . $label . '
</span>';
}
}
return '';
} }
/* hook to save plagiarism specific settings on a module settings page
* @param object $data - data from an mform submission.
*/
/** /**
* @param $data * hook to save plagiarism specific settings on a module settings page
*
* @param object $data - data from an mform submission.
* @throws dml_exception * @throws dml_exception
*/ */
public function save_form_elements($data) { public function save_form_elements($data) {
@ -148,6 +218,9 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
} }
/** /**
*
* Build plugin settings form.
*
* @param object $mform * @param object $mform
* @param object $context * @param object $context
* @param string $modulename * @param string $modulename
@ -171,7 +244,8 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
'cm' => $cm, 'cm' => $cm,
)); ));
if (!empty($records)) { if (!empty($records)) {
$mform->setDefault($records[0]->name, $records[0]->value); $record = end($records);
$mform->setDefault($record->name, $record->value);
} }
} }
@ -191,7 +265,7 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
} }
/** /**
* hook to allow a disclosure to be printed notifying users what will happen with their submission * hook to allow a disclosure to be printed notifying users what will happen with their submission.
* *
* @param int $cmid - course module id * @param int $cmid - course module id
* @return string * @return string
@ -206,7 +280,7 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
// Get course details. // Get course details.
$cm = get_coursemodule_from_id('', $cmid); $cm = get_coursemodule_from_id('', $cmid);
if ($cm->modname != 'assign') { if (!$cm || $cm->modname != 'assign') {
return ''; return '';
} }
@ -217,7 +291,7 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
return ''; return '';
} }
if ($configmodel->is_enabled_for_module($cmid) != '1') { if (!$configmodel->is_enabled_for_module($cmid)) {
return ''; return '';
} }
@ -229,9 +303,345 @@ class plagiarism_plugin_pchkorg extends plagiarism_plugin {
$formatoptions->noclean = true; $formatoptions->noclean = true;
$formatoptions->cmid = $cmid; $formatoptions->cmid = $cmid;
$result .= '<div style="background-color: #d5ffd5; padding: 10px; border: 1px solid #b7dab7">';
$result .= format_text(get_string('pchkorg_disclosure', 'plagiarism_pchkorg'), FORMAT_MOODLE, $formatoptions); $result .= format_text(get_string('pchkorg_disclosure', 'plagiarism_pchkorg'), FORMAT_MOODLE, $formatoptions);
$result .= '</div>';
$result .= $OUTPUT->box_end(); $result .= $OUTPUT->box_end();
return $result; return $result;
} }
/**
*
* Method will handle event assessable_uploaded.
*
* @param $eventdata
* @return bool
* @throws coding_exception
* @throws dml_exception
*/
public function event_handler($eventdata) {
global $USER, $DB;
// We support only assign module so just ignore all other.
if ($eventdata['other']['modulename'] !== 'assign') {
return true;
}
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
$apitoken = $pchkorgconfigmodel->get_system_config('pchkorg_token');
$apiprovider = new plagiarism_pchkorg_api_provider($apitoken);
// SQL will be called only once, result is static.
$config = $pchkorgconfigmodel->get_system_config('pchkorg_use');
if ('1' !== $config) {
return true;
}
// Receive couser moudle id.
$cmid = $eventdata['contextinstanceid'];
// Remove the event if the course module no longer exists.
$cm = get_coursemodule_from_id($eventdata['other']['modulename'], $cmid);
if (!$cm) {
return true;
}
// SQL will be called only once per page. There is static result inside.
// Plugin is enabled for this module.
if (!$pchkorgconfigmodel->is_enabled_for_module($cm->id)) {
return true;
}
// 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.
// 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;
}
// 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)) {
$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);
}
}
// Get actual text content and files to be submitted for draft submissions.
// As this won't be present in eventdata for certain event types.
if ($eventdata['other']['modulename'] == 'assign' && $eventdata['eventtype'] == "assessable_submitted") {
// Get content.
$moodlesubmission = $DB->get_record('assign_submission', array('id' => $eventdata['objectid']), 'id');
if ($moodletextsubmission = $DB->get_record('assignsubmission_onlinetext',
array('submission' => $moodlesubmission->id), 'onlinetext')) {
$eventdata['other']['content'] = $moodletextsubmission->onlinetext;
}
$filesconditions = array(
'component' => 'assignsubmission_file',
'itemid' => $moodlesubmission->id,
'userid' => $author
);
$moodlefiles = $DB->get_records('files', $filesconditions);
if ($moodlefiles) {
$fs = get_file_storage();
foreach ($moodlefiles as $filedb) {
$file = $fs->get_file_by_id($filedb->id);
if (!$file) {
// We can not find file so we do not send it in queue.
continue;
} else {
try {
// Check that we can fetch content without exception.
$content = $file->get_content();
} catch (Exception $e) {
// No we can not.
continue;
}
}
if ($file->get_filename() === '.') {
continue;
}
$filemime = $file->get_mimetype();
// File type is not supported.
if (!$apiprovider->is_supported_mime($filemime)) {
continue;
}
$filerecord = new \stdClass();
$filerecord->fileid = $file->get_id();
$filerecord->cm = $cmid;
$filerecord->userid = $USER->id;
$filerecord->textid = null;
$filerecord->state = 10;
$filerecord->created_at = time();
$filerecord->itemid = $eventdata['objectid'];
$filerecord->signature = sha1($content);
$DB->insert_record('plagiarism_pchkorg_files', $filerecord);
}
}
}
// Queue text content to send to plagiarismcheck.org.
// If there was an error when creating the assignment then still queue the submission so it can be saved as failed.
if (in_array($eventdata['eventtype'], array("content_uploaded", "assessable_submitted"))
&& !empty($eventdata['other']['content'])) {
$signature = sha1($eventdata['other']['content']);
$filesconditions = array(
'signature' => $signature,
'cm' => $cmid,
'userid' => $USER->id,
'itemid' => $eventdata['objectid']
);
$oldfile = $DB->get_record('plagiarism_pchkorg_files', $filesconditions);
if ($oldfile) {
// There is the same check in database, so we can skip this one.
return true;
}
$filerecord = new \stdClass();
$filerecord->fileid = null;
$filerecord->cm = $cmid;
$filerecord->userid = $USER->id;
$filerecord->textid = null;
$filerecord->state = 10;
$filerecord->created_at = time();
$filerecord->itemid = $eventdata['objectid'];
$filerecord->signature = $signature;
$DB->insert_record('plagiarism_pchkorg_files', $filerecord);
}
return true;
}
/**
*
* Will find the first user in group assignment.
*
* @param $cmid
* @param $groupid
* @return mixed
* @throws coding_exception
*/
private function get_first_group_author($cmid, $groupid) {
static $context;
if (empty($context)) {
$context = context_course::instance($cmid);
}
$groupmembers = groups_get_members($groupid, "u.id");
foreach ($groupmembers as $author) {
if (!has_capability('mod/assign:grade', $context, $author->id)) {
return $author->id;
}
}
}
/**
*
* Method will be called by cron. Method sends queued files into plagiarism check system.
*
* @return bool
* @throws coding_exception
* @throws dml_exception
*/
public function cron_send_submissions() {
global $DB;
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
$apitoken = $pchkorgconfigmodel->get_system_config('pchkorg_token');
$apiprovider = new plagiarism_pchkorg_api_provider($apitoken);
// SQL will be called only once, result is static.
$config = $pchkorgconfigmodel->get_system_config('pchkorg_use');
if ('1' !== $config) {
return true;
}
$filesconditions = array('state' => 10);
$moodlefiles = $DB->get_records('plagiarism_pchkorg_files', $filesconditions,
'id', '*', 0, 20);
if ($moodlefiles) {
$fs = get_file_storage();
foreach ($moodlefiles as $filedb) {
$textid = null;
$user = $DB->get_record('user', array('id' => $filedb->userid));
// This is attached file.
$cm = get_coursemodule_from_id('', $filedb->cm);
if ($filedb->fileid === null) {
$moodletextsubmission = $DB->get_record('assignsubmission_onlinetext',
array('submission' => $filedb->itemid), '*');
if ($moodletextsubmission) {
$content = $moodletextsubmission->onlinetext;
if ($apiprovider->is_group_token()) {
$textid = $apiprovider->send_group_text(
$apiprovider->user_email_to_hash($user->email),
$cm->course,
$cm->id,
$moodletextsubmission->id,
$moodletextsubmission->id,
html_to_text($content, 75, false),
'plain/text',
sprintf('%s-submussion.txt', $moodletextsubmission->id)
);
} else {
$textid = $apiprovider->send_text(
html_to_text($content, 75, false),
'plain/text',
sprintf('%s-submussion.txt', $moodletextsubmission->id)
);
}
}
} else {
$moodlesubmission = $DB->get_record('assign_submission', array('assignment' => $cm->instance,
'userid' => $filedb->userid, 'id' => $filedb->itemid), 'id');
$file = $fs->get_file_by_id($filedb->fileid);
if ($apiprovider->is_group_token()) {
$textid = $apiprovider->send_group_text(
$apiprovider->user_email_to_hash($user->email),
$cm->course,
$cm->id,
$moodlesubmission->id,
$file->get_id(),
$file->get_content(),
$file->get_mimetype(),
$file->get_filename()
);
} else {
$agreementwhere = array(
'cm' => 0,
'name' => 'accepter_agreement',
'value' => '1'
);
$agreementaccepted = $DB->get_records('plagiarism_pchkorg_config', $agreementwhere);
if (!$agreementaccepted) {
$apiprovider->save_accepted_agreement();
$DB->insert_record('plagiarism_pchkorg_config', $agreementwhere);
}
$textid = $apiprovider->send_text(
$file->get_content(),
$file->get_mimetype(),
$file->get_filename()
);
}
}
$filedbnew = new stdClass();
$filedbnew->id = $filedb->id;
if ($textid) {
// Text was successfully sent to the service.
$filedbnew->textid = $textid;
$filedbnew->state = 12; // 12 - is SENT.
} else {
$filedbnew->attempt = $filedb->attempt + 1;
if ($filedbnew->attempt > 6) {
$filedbnew->state = 11; // Sending error.
}
}
$DB->update_record('plagiarism_pchkorg_files', $filedbnew);
}
}
return true;
}
/**
* Method will update similarity score and change status of checks.
*
* @return bool
* @throws dml_exception
*/
public function cron_update_reports() {
global $DB;
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
$apitoken = $pchkorgconfigmodel->get_system_config('pchkorg_token');
$apiprovider = new plagiarism_pchkorg_api_provider($apitoken);
// SQL will be called only once, result is static.
$config = $pchkorgconfigmodel->get_system_config('pchkorg_use');
if ('1' !== $config) {
return true;
}
$filesconditions = array('state' => 12);
$moodlefiles = $DB->get_records('plagiarism_pchkorg_files', $filesconditions,
'id', '*', 0, 20);
foreach ($moodlefiles as $filedb) {
$report = $apiprovider->check_text($filedb->textid);
if ($report !== null) {
$filedbnew = new stdClass();
$filedbnew->id = $filedb->id;
$filedbnew->state = 5;
$filedbnew->reportid = $report->id;
$filedbnew->score = $report->percent;
$DB->update_record('plagiarism_pchkorg_files', $filedbnew);
}
}
}
} }

View File

@ -1,95 +0,0 @@
<?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/>.
/**
* @package plagiarism_pchkorg
* @category plagiarism
* @copyright PlagiarismCheck.org, https://plagiarismcheck.org/
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../config.php');
require_once(__DIR__ . '/../lib.php');
require_once(__DIR__ . '/../form/send_text_form.php');
require_once(__DIR__ . '/../classes/plagiarism_pchkorg_config_model.php');
require_once(__DIR__ . '/../classes/plagiarism_pchkorg_url_generator.php');
require_once(__DIR__ . '/../classes/plagiarism_pchkorg_api_provider.php');
global $PAGE, $CFG, $OUTPUT, $DB, $USER;
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
$urlgenerator = new plagiarism_pchkorg_url_generator();
$apiprovider = new plagiarism_pchkorg_api_provider(
$pchkorgconfigmodel->get_system_config('pchkorg_token')
);
$cmid = (int) required_param('cmid', PARAM_INT); // Course Module ID
$fileid = (int) required_param('file', PARAM_INT); // plagiarism file id.
$cm = get_coursemodule_from_id('', $cmid);
require_login($cm->course, true, $cm);
$context = context_module::instance($cm->id);
header('Content-Type: application/json');
$isgranted = has_capability('mod/assign:grade', $context, null);
if (!$isgranted) {
die('{error: "access denied"}');
}
$fs = get_file_storage();
$file = $fs->get_file_by_id($fileid);
if (!$file) {
die('{error: "file not exists"}');
}
if ('submission_files' !== $file->get_filearea()
|| $file->get_contextid() != $context->id) {
die('{error: "access denied"}');
}
// Prevent JS caching.
$CFG->cachejs = false;
$PAGE->set_url($urlgenerator->get_status_url());
$where = new \stdClass();
$where->cm = $cmid;
$where->fileid = $fileid;
$filerecord = $DB->get_record('plagiarism_pchkorg_files', (array) $where);
if (!$filerecord) {
echo json_encode(array(
'success' => false,
'message' => '404 can not find text'
));
}
$report = $apiprovider->check_text($filerecord->textid);
if ($checked = (null !== $report)) {
$filerecord->reportid = $report->id;
$filerecord->score = $report->percent;
$DB->update_record('plagiarism_pchkorg_files', $filerecord);
}
$location = new moodle_url(sprintf(
'/plagiarism/pchkorg/page/report.php?cmid=%s&file=%s',
intval($cmid),
intval($fileid)
));
echo json_encode(array(
'success' => true,
'checked' => $checked,
'location' => $location->out(false)
));

View File

@ -1,169 +0,0 @@
<?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/>.
/**
* @package plagiarism_pchkorg
* @category plagiarism
* @copyright PlagiarismCheck.org, https://plagiarismcheck.org/
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(__DIR__ . '/../../../config.php');
require_once(__DIR__ . '/../lib.php');
require_once(__DIR__ . '/../form/send_text_form.php');
require_once(__DIR__ . '/../classes/plagiarism_pchkorg_config_model.php');
require_once(__DIR__ . '/../classes/plagiarism_pchkorg_url_generator.php');
require_once(__DIR__ . '/../classes/plagiarism_pchkorg_api_provider.php');
global $PAGE, $CFG, $OUTPUT, $DB, $USER;
$pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
$urlgenerator = new plagiarism_pchkorg_url_generator();
$apiprovider = new plagiarism_pchkorg_api_provider($pchkorgconfigmodel->get_system_config('pchkorg_token'));
$cmid = (int) required_param('cmid', PARAM_INT); // Course Module ID.
$fileid = (int) required_param('file', PARAM_INT); // plagiarism file id.
$cm = get_coursemodule_from_id('', $cmid, 0, false, MUST_EXIST);
require_login($cm->course, true, $cm);
$context = context_module::instance($cm->id);// Get context of course.
$isgranted = has_capability('mod/assign:view', $context, null);
if (!$isgranted) {
die('403 permission denied');
}
$fs = get_file_storage();
$form = new send_text_form($currenturl = $urlgenerator->get_check_url($cmid, $fileid));
$CFG->cachejs = false;
$PAGE->set_url($currenturl);
$PAGE->set_pagelayout('report');
$PAGE->set_title(get_string('pluginname', 'plagiarism_pchkorg'));
$PAGE->set_heading(get_string('pluginname', 'plagiarism_pchkorg'));
if ('POST' === $_SERVER['REQUEST_METHOD']) { // Form submission.
$data = $form->get_data();
$cmid = (int) $data->cmid;
$fileid = (int) $data->fileid;
$file = $fs->get_file_by_id($fileid);
$where = new \stdClass();
$where->cm = $cmid;
$where->fileid = $file->get_id();
$filerecord = $DB->get_record('plagiarism_pchkorg_files', (array) $where);
// Preventing some race condition.
if ($filerecord) {
redirect($urlgenerator->get_check_url($cmid, $fileid), 'Document already checked.');
exit;
}
if ('submission_files' !== $file->get_filearea()
|| $file->get_contextid() != $context->id) {
die('permission denied');
}
if (!$file) {
// File not found.
die('404 not exists');
}
if ($apiprovider->is_group_token()) {
$textid = $apiprovider->send_group_text(
$apiprovider->user_email_to_hash($USER->email),
$cm->course,
$cm->id,
$cm->id,
$file->get_id(),
$file->get_content(),
$file->get_mimetype(),
$file->get_filename()
);
} else {
$textid = $apiprovider->send_text(
$file->get_content(),
$file->get_mimetype(),
$file->get_filename()
);
}
$message = '';
if (null !== $textid) {
$filerecord = new \stdClass();
$filerecord->fileid = $fileid;
$filerecord->cm = $cmid;
$filerecord->userid = $USER->id;
$filerecord->textid = $textid;
$filerecord->state = 1; // 1 - is SENT.
$filerecord->created_at = time();
$DB->insert_record('plagiarism_pchkorg_files', $filerecord);
} else {
if ('Invalid token' === $apiprovider->get_last_error()) {
$pchkorgconfigmodel->set_system_config('pchkorg_use', '0');
}
$message = $apiprovider->get_last_error();
}
redirect($urlgenerator->get_check_url($cmid, $fileid), $message);
exit;
}
$file = $fs->get_file_by_id($fileid);
if ('submission_files' !== $file->get_filearea()
|| $file->get_contextid() != $context->id) {
die('permission denied');
}
if (!$file) {
die('404 not exists');
}
$where = new \stdClass();
$where->cm = $cmid;
$where->fileid = $fileid;
$filerecord = $DB->get_record('plagiarism_pchkorg_files', (array) $where);
if (!$filerecord) {
$content = $file->get_content();
$mime = $file->get_mimetype();
if ($issupported = $apiprovider->is_supported_mime($file->get_mimetype())) {
if ('plain/text' === $mime || 'text/plain' === $mime) {
$content = $content = $file->get_content();
} else {
$content = $file->get_filename();
}
$default = array('fileid' => $fileid, 'cmid' => $cmid);
$form->set_data($default);
}
require('../view/send_text.php');
} else if (null !== $filerecord->reportid) {
$action = $apiprovider->get_report_action($filerecord->textid);
$token = $apiprovider->generate_api_token();
require('../view/report.php');
} else if (null !== $filerecord->textid) {
require('../view/check_report.php');
}

BIN
pix/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -35,7 +35,7 @@ $pchkorgconfigmodel = new plagiarism_pchkorg_config_model();
require_login(); require_login();
admin_externalpage_setup('plagiarismpchkorg'); admin_externalpage_setup('plagiarismpchkorg');
$context = context_system::instance(CONTEXT_SYSTEM); $context = context_system::instance();
require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions"); require_capability('moodle/site:config', $context, $USER->id, true, "nopermissions");

View File

@ -26,11 +26,10 @@ defined('MOODLE_INTERNAL') || die();
if (!isset($plugin)) { if (!isset($plugin)) {
$plugin = new stdClass(); $plugin = new stdClass();
} }
$plugin->version = 2019031801; $plugin->version = 2019041101;
$plugin->requires = 2017051501; // Requires Moodle 3.3 . $plugin->requires = 2017051501; // Requires Moodle 3.3 .
$plugin->release = 'v3.1'; $plugin->release = 'v3.2';
$plugin->maturity = MATURITY_STABLE; $plugin->maturity = MATURITY_STABLE;
$plugin->component = 'plagiarism_pchkorg'; $plugin->component = 'plagiarism_pchkorg';
$plugin->dependencies = array( $plugin->dependencies = array(
'mod_assign' => ANY_VERSION, 'mod_assign' => ANY_VERSION,

View File

@ -1,76 +0,0 @@
<?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/>.
/**
* @package plagiarism_pchkorg
* @category plagiarism
* @copyright PlagiarismCheck.org, https://plagiarismcheck.org/
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$ajaxurl = new moodle_url('/plagiarism/pchkorg/page/check.php');
$PAGE->requires->js_init_code("
var interval;
var data = {
'file': $('#plagcheck-loader').attr('data-file'),
'cmid': $('#plagcheck-loader').attr('data-cmid')
};
var checkStatus = function () {
$.post('{$ajaxurl}', data, function (response) {
if (!response || !response.success) {
$('#plagcheck-loader').hide();
clearInterval(interval);
} else if (response.checked) {
$('#plagcheck-loader').hide();
clearInterval(interval);
window.location.href = response.location;
}
}, 'JSON');
};
interval = setInterval(checkStatus, 1000);
", true);
echo $OUTPUT->header();
?>
<style>
.loader {
border: 16px solid #f3f3f3; /* Light grey */
border-top: 16px solid #3498db; /* Blue */
border-radius: 50%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<div>
<div id="plagcheck-loader" data-cmid="<?php
echo intval($cmid) ?>" data-file="<?php
echo intval($fileid) ?>" class="loader"></div>
</div>
<?php
echo $OUTPUT->footer();