Skip to content

Commit e6a53eb

Browse files
authored
Merge pull request #315 from turnitin/develop
Develop into master for release 2018052401
2 parents 01b3c19 + 64c542f commit e6a53eb

37 files changed

+826
-78
lines changed

CHANGELOG.md

+74
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,77 @@
1+
### Date: 2018-May-24
2+
### Release: v2018052401
3+
4+
#### :zap: What's new
5+
6+
---
7+
8+
#### We now support Moodle 3.5
9+
10+
You can find out more about Moodle 3.5 via Moodle's [release notes](https://docs.moodle.org/dev/Moodle_3.5_release_notes).
11+
12+
#### Turnitin's Plagiarism Plugin is GDPR compliant!
13+
14+
To support upcoming changes to European data protection law, we’ve focused our efforts on refreshing our processes around how we use your data.
15+
16+
##### Repository settings are more transparent
17+
18+
We've made the Moodle Plagiarism Plugin repository settings much clearer, by providing easy-to-understand, transparent language behind the Store student papers help icon. During assignment setup, administrators and instructors can now be completely sure that they're selecting the correct storage options for student papers.
19+
20+
##### We're reporting on the data we store about our users
21+
22+
Moodle has released two plugins with privacy features to assist with GDPR compliance. While we've successfully implemented [Moodle's new privacy features](https://docs.moodle.org/dev/Privacy_API), Moodle's update is only available to those using Moodle 3.3.5+, 3.4.2+, or 3.5. Therefore, if you're using an earlier version, you must upgrade to have access to these new features.
23+
24+
To inform you about the data we store in relation to our users, we now provide a detailed list via the Moodle Privacy and Policies page. Learn more about the data we're reporting on via our [Moodle Plugins and GDPR](https://guides.turnitin.com/03_Integrations/Turnitin_Partner_Integrations/Moodle/Moodle_Plugins_and_GDPR) page.
25+
26+
#### Students can request to download their data
27+
28+
Students have the ability to request an export of their data stored in Moodle. This request can be accepted or declined by their Moodle administrator. If accepted, the student will be able to download all the data held about them, which includes data from Turnitin.
29+
30+
#### Students can request to remove their data
31+
32+
Students can also request their data to be removed from Moodle. This requested can be accepted or declined by their Moodle administrator. If accepted, the administrator will remove the student data from Moodle. However, administrators must contact support@turnitin.com to request that student data be removed from Turnitin itself.
33+
34+
> If you're a Moodle administrator, and using version 3.3.5+, 3.4.2+, or 3.5, follow the steps on the [Moodle Plugins and GDPR](https://guides.turnitin.com/03_Integrations/Turnitin_Partner_Integrations/Moodle/Moodle_Plugins_and_GDPR) page to view the data we store in Moodle.
35+
36+
#### You can now send all papers to your institutional repository by default!
37+
38+
We're aligning Turnitin repository options with the Plagiarism Plugin. If an institutional repository is enabled on their Turnitin account, administrators can now opt to **Submit all papers to the institutional repository**. This submission storage option sends all student submissions to the institutional repository without instructor intervention. For this repository option to work successfully, it must firstly be enabled in Turnitin, before it can be configured in Moodle.
39+
40+
If you're a Moodle administrator, follow the steps below to enable this repository setting in Turnitin:
41+
42+
1. Log into Turnitin.com or TurnitinUK.com.
43+
2. Under **Edit**, select the cog icon.
44+
3. Select **Edit account settings**.
45+
4. Scroll to **Paper repository options** and select **Submit all papers to the institution repository**.
46+
6. Select the **Submit** button at the bottom of the page.
47+
48+
Now, it's time to move to Moodle!
49+
50+
1. From the Moodle left-hand side panel, select **Site administration**.
51+
2. Select **Plugins**.
52+
3. Select **Activity Modules**.
53+
4. Then **Manage Activities**.
54+
5. Scroll to **Turnitin Assignment 2** and select **Settings**.
55+
6. Scroll to **Paper Repository Assignments** and select **Submit all papers to the institutional repository**.
56+
57+
### :wrench: Fixes and enhancements
58+
59+
#### We've removed a technical notice from the assignment settings page
60+
61+
In Moodle's debug mode, a peculiar notice appeared within the assignment settings: 'Array to string conversion in /usr/share/nginx/html/lib/pear/HTML/QuickForm/select.php on line 501'. We've made some adjustments to ensure that this doesn't appear in future.
62+
63+
#### You can now exit lightboxes using the 'Close' button
64+
65+
We received a report that the Close button in the Plagiarism Plugin's lightboxes wasn't performing correctly, in that it wasn't actually closing anything! Instead, users saw the following error: 'Uncaught TypeError: Cannot read property 'close' of undefined at HTMLAnchorElement.onclick'. Thanks for the heads up, @Haietza! We've fixed this issue.
66+
67+
> **Lightboxes** display content by filling the screen and dimming out the rest of the web page. They can be closed to find the website contents still available. Items such as the QuickMark manager and the rubric manager are contained inside a lightbox.
68+
69+
#### Instructors can now successfully submit on behalf of a student
70+
71+
An instructor encountered an issue when attempting to resubmit on behalf of a student within a group submission. This was down to us incorrectly checking the permissions of the student, rather than the submitter. These permissions told us that the student wasn't permitted to resubmit to the assignment, but if we'd checked the instructor permissions, we'd have found that their permissions allowed this. Phew. A big thanks to @micaherne for his patch to fix this! It did the job nicely.
72+
73+
---
74+
175
### :snowflake: Date: 2018-January-16
276
### :snowflake: Release: v2018011602
377

classes/digitalreceipt/pp_receipt_message.php

+9-2
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,17 @@ class pp_receipt_message {
3131
* @param string $message
3232
* @return void
3333
*/
34-
public function send_message($userid, $message) {
34+
public function send_message($userid, $message, $courseid) {
35+
global $CFG;
3536

3637
$subject = get_string('digital_receipt_subject', 'plagiarism_turnitin');
3738

38-
$eventdata = new stdClass();
39+
// Pre 2.9 does not have \core\message\message()
40+
if ($CFG->branch >= 29) {
41+
$eventdata = new \core\message\message();
42+
} else {
43+
$eventdata = new stdClass();
44+
}
3945
$eventdata->component = 'plagiarism_turnitin'; // Your component name.
4046
$eventdata->name = 'submission'; // This is the message name from messages.php.
4147
$eventdata->userfrom = \core_user::get_noreply_user();
@@ -46,6 +52,7 @@ public function send_message($userid, $message) {
4652
$eventdata->fullmessagehtml = $message;
4753
$eventdata->smallmessage = '';
4854
$eventdata->notification = 1; // This is only set to 0 for personal messages between users.
55+
$eventdata->courseid = $courseid;
4956

5057
message_send($eventdata);
5158
}

classes/modules/turnitin_assign.class.php

+5-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function set_content($linkarray, $cm) {
6969
* @param $assignid
7070
*/
7171
public function is_resubmission_allowed($assignid, $reportgenspeed, $submissiontype, $attemptreopenmethod) {
72-
global $DB;
72+
global $DB, $CFG;
7373

7474
// Get the maximum number of file submissions allowed.
7575
$params = array('assignment' => $assignid,
@@ -82,6 +82,10 @@ public function is_resubmission_allowed($assignid, $reportgenspeed, $submissiont
8282
$maxfilesubmissions = $result->value;
8383
}
8484

85+
if ($CFG->branch <= 32) {
86+
require_once($CFG->dirroot.'/mod/assign/lib.php');
87+
}
88+
8589
return ($reportgenspeed > 0 && $attemptreopenmethod == ASSIGN_ATTEMPT_REOPEN_METHOD_NONE
8690
&& ($submissiontype == 'text_content' || $maxfilesubmissions == 1));
8791
}

classes/modules/turnitin_forum.class.php

+10-3
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,19 @@ public function user_enrolled_on_course($context, $userid) {
4646
return has_capability('mod/'.$this->modname.':replypost', $context, $userid);
4747
}
4848

49-
public function get_author($itemid) {
49+
public function get_author($itemid = 0) {
5050
return;
5151
}
5252

53-
public function set_content($linkarray, $moduleid) {
54-
return $linkarray["content"];
53+
public function set_content($linkarray) {
54+
global $DB;
55+
56+
if (empty($linkarray['postid'])) {
57+
return $linkarray["content"];
58+
} else {
59+
$post = $DB->get_record('forum_posts', array('id' => $linkarray['postid']));
60+
return $post->message;
61+
}
5562
}
5663

5764
public function create_file_event($params) {

classes/privacy/provider.php

+199
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
<?php
2+
// This file is part of Moodle - http://moodle.org/
3+
//
4+
// Moodle is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Moodle is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU General Public License
15+
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16+
17+
/**
18+
* Privacy Subsystem implementation for mod_turnitintool.
19+
*
20+
* @package plagiarism_turnitin
21+
* @copyright 2018 David Winn <dwinn@turnitin.com>
22+
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23+
*/
24+
25+
namespace plagiarism_turnitin\privacy;
26+
27+
defined('MOODLE_INTERNAL') || die();
28+
29+
use core_privacy\local\metadata\collection;
30+
use core_privacy\local\request\contextlist;
31+
use core_privacy\local\request\helper;
32+
use core_privacy\local\request\writer;
33+
34+
class provider implements
35+
// This plugin does store personal user data.
36+
\core_privacy\local\metadata\provider,
37+
\core_plagiarism\privacy\plagiarism_provider {
38+
39+
// This trait must be included to provide the relevant polyfill for the metadata provider.
40+
use \core_privacy\local\legacy_polyfill;
41+
42+
// This trait must be included to provide the relevant polyfill for the plagirism provider.
43+
use \core_plagiarism\privacy\legacy_polyfill;
44+
45+
/**
46+
* Return the fields which contain personal data.
47+
*
48+
* @param $collection collection a reference to the collection to use to store the metadata.
49+
* @return $collection the updated collection of metadata items.
50+
*/
51+
public static function _get_metadata(collection $collection) {
52+
53+
$collection->link_subsystem(
54+
'core_files',
55+
'privacy:metadata:core_files'
56+
);
57+
58+
$collection->add_database_table(
59+
'plagiarism_turnitin_files',
60+
[
61+
'userid' => 'privacy:metadata:plagiarism_turnitin_files:userid',
62+
'similarityscore' => 'privacy:metadata:plagiarism_turnitin_files:submissionscore',
63+
'attempt' => 'privacy:metadata:plagiarism_turnitin_files:attempt',
64+
'transmatch' => 'privacy:metadata:plagiarism_turnitin_files:transmatch',
65+
'lastmodified' => 'privacy:metadata:plagiarism_turnitin_files:lastmodified',
66+
'grade' => 'privacy:metadata:plagiarism_turnitin_files:grade',
67+
'orcapable' => 'privacy:metadata:plagiarism_turnitin_files:orcapable',
68+
'student_read' => 'privacy:metadata:plagiarism_turnitin_files:student_read',
69+
],
70+
'privacy:metadata:plagiarism_turnitin_files'
71+
);
72+
73+
$collection->link_external_location('plagiarism_turnitin_client', [
74+
'email' => 'privacy:metadata:plagiarism_turnitin_client:email',
75+
'firstname' => 'privacy:metadata:plagiarism_turnitin_client:firstname',
76+
'lastname' => 'privacy:metadata:plagiarism_turnitin_client:lastname',
77+
'submission_title' => 'privacy:metadata:plagiarism_turnitin_client:submission_title',
78+
'submission_filename' => 'privacy:metadata:plagiarism_turnitin_client:submission_filename',
79+
], 'privacy:metadata:plagiarism_turnitin_client');
80+
81+
return $collection;
82+
}
83+
84+
/**
85+
* Get the list of contexts that contain user information for the specified user.
86+
*
87+
* @param int $userid the userid.
88+
* @return contextlist the list of contexts containing user info for the user.
89+
*/
90+
public static function _get_contexts_for_userid($userid) {
91+
92+
$params = ['modulename' => 'assign',
93+
'contextlevel' => CONTEXT_MODULE,
94+
'userid' => $userid];
95+
96+
$sql = "SELECT ctx.id
97+
FROM {course_modules} cm
98+
JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
99+
JOIN {assign} a ON cm.instance = a.id
100+
JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
101+
LEFT JOIN {plagiarism_turnitin_files} tf ON cm.instance = cm
102+
WHERE tf.userid = :userid";
103+
104+
$contextlist = new contextlist();
105+
$contextlist->add_from_sql($sql, $params);
106+
107+
return $contextlist;
108+
}
109+
110+
111+
/**
112+
* Export all plagiarism data from each plagiarism plugin for the specified userid and context.
113+
*
114+
* @param int $userid The user to export.
115+
* @param \context $context The context to export.
116+
* @param array $subcontext The subcontext within the context to export this information to.
117+
* @param array $linkarray The weird and wonderful link array used to display information for a specific item
118+
*/
119+
public static function _export_plagiarism_user_data($userid, \context $context, array $subcontext, array $linkarray) {
120+
global $DB;
121+
122+
$user = $DB->get_record('user', array('id' => $userid));
123+
124+
$params = ['userid' => $user->id];
125+
126+
$sql = "SELECT cm,
127+
similarityscore,
128+
attempt,
129+
transmatch,
130+
lastmodified,
131+
grade,
132+
orcapable,
133+
student_read
134+
FROM {plagiarism_turnitin_files}
135+
WHERE userid = :userid";
136+
$submissions = $DB->get_records_sql($sql, $params);
137+
138+
foreach ($submissions as $submission) {
139+
$context = \context_module::instance($submission->cm);
140+
self::_export_plagiarism_turnitin_data_for_user((array)$submission, $context, $user);
141+
}
142+
}
143+
144+
/**
145+
* Export the supplied personal data for a single activity, along with any generic data or area files.
146+
*
147+
* @param array $submissiondata the personal data to export.
148+
* @param \context_module $context the module context.
149+
* @param \stdClass $user the user record
150+
*/
151+
protected static function _export_plagiarism_turnitin_data_for_user(array $submissiondata, \context_module $context, \stdClass $user) {
152+
// Fetch the generic module data.
153+
$contextdata = helper::get_context_data($context, $user);
154+
155+
// Merge with module data and write it.
156+
$contextdata = (object)array_merge((array)$contextdata, $submissiondata);
157+
writer::with_context($context)->export_data([], $contextdata);
158+
159+
// Write generic module intro files.
160+
helper::export_context_files($context, $user);
161+
}
162+
163+
/**
164+
* Delete all data for all users in the specified context.
165+
*
166+
* @param \context $context the context to delete in.
167+
*/
168+
public static function _delete_plagiarism_for_context(\context $context) {
169+
global $DB;
170+
171+
if (empty($context)) {
172+
return;
173+
}
174+
175+
if (!$context instanceof \context_module) {
176+
return;
177+
}
178+
179+
$instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
180+
181+
$cm = get_coursemodule_from_instance('assign', $instanceid);
182+
183+
// Delete all submissions.
184+
$DB->delete_records('plagiarism_turnitin_files', ['cm' => $cm->id]);
185+
186+
}
187+
188+
/**
189+
* Delete all user information for the provided user and context.
190+
*
191+
* @param int $userid The user to delete
192+
* @param \context $context The context to refine the deletion.
193+
*/
194+
public static function _delete_plagiarism_for_user($userid, \context $context) {
195+
global $DB;
196+
197+
$DB->delete_records('plagiarism_turnitin_files', ['userid' => $userid]);
198+
}
199+
}

jquery/jquery-1.8.2.min.js

-2
This file was deleted.

jquery/jquery-3.3.1.min.js

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jquery/turnitin_module.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ jQuery(document).ready(function($) {
167167
}
168168

169169
function lightBoxCloseButton(closeBtnText) {
170-
$('body').append('<div id="tii_close_bar"><a href="#" onclick="$.colorbox.close(); return false;">' + M.str.plagiarism_turnitin.closebutton + '</a></div>');
170+
$('body').append('<div id="tii_close_bar"><a href="#" onclick="jQuery(\'#cboxClose\').click(); return false;">' + M.str.plagiarism_turnitin.closebutton + '</a></div>');
171171
}
172172

173173
function getLoadingGif() {

lang/ar/plagiarism_turnitin.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
$string['standardrepository'] = 'المستودع القياسي';
7979
$string['submitpapersto'] = 'حفظ مستندات الطلبة';
8080
$string['institutionalrepository'] = 'المستودعات المؤسسية (عند الاقتضاء)';
81-
$string['submitpapersto_help'] = 'سيوفر هذا الإعداد للمدرسين القدرة على اختيار ما اذا كانت المستندات ستحفظ في مستودع مستندات الطلبة. تكمن الفائدة من ارسال المستندات إلى مستودع مستندات الطلبة في التحقق من مستندات الطلاب التي تم إرسالها مقابل إرسالات &#39;الطلاب الآخرين في صفوفك الدراسية الحالية أو السابقة. إذا اخترت &#34;لا مستودعات&#34; فلن يتم تخزين المستندات في مخزن مستندات الطلاب.&#39;';
8281
$string['checkagainstnote'] = 'ملحوظة: إذا لم تحدد "نعم" لخيار "التحقق مقابل..." واحد على الأقل الموجود أدناه، فلن يتم إنشاء تقرير الأصالة.';
8382
$string['spapercheck'] = 'قحص مقابل مستندات الطلبة المخزونة';
8483
$string['internetcheck'] = 'فحص مقابل الإنترنت';
@@ -199,3 +198,5 @@
199198
$string['deleted'] = 'تم حذف';
200199
$string['pending'] = 'قيد الانتظار';
201200
$string['because'] = 'هذا بسبب قيام أحد المسؤولين بحذف مهمة معلقة من قائمة المعالجة وإيقاف الإرسال إلى Turnitin. <br /><strong>ما زال الملف موجودًا في Moodle، الرجاء الاتصال بمعلمك.</strong><br />الرجاء الاطلاع أدناه على أي رموز خطأ:';
201+
$string['submitpapersto_help'] = '<strong>لا توجد مستودعات: </strong><br />تتم مطالبة Turnitin بعدم تخزين المستندات المرسلة في أي مستودع. وسوف تقتصر معالجتنا للورق على إجراء فحص أولي على التشابه.<br /><br /><strong>المستودع القياسي: </strong><br />سوف يخزن Turnitin نُسخة من المستندات المرسلة فقط في المستودع القياسي. وباختيار هذا الخيار، يتم توجيه Turnitin باستخدام المستندات المخزنة فقط لإجراء فحوصات تشابه على المستندات التي يتم إرسالها لاحقًا.<br /><br /><strong>المستودعات المؤسسية (عند الاقتضاء): </strong><br />باختيار هذا الخيار، يتم توجيه Turnitin إلى إضافة المستندات المرسلة إلى المستودع الخاص بالمؤسسة فقط. ويتم إجراء فحوصات التشابه على المستندات المرسلة بواسطة معلمين آخرين من مؤسستك.';
202+
$string['errorcode12'] = 'لم يتم إرسال هذا الملف إلى Turnitin، لأنه ينتمي إلى مهمة تم حذف دورتها التدريبية. معرف السطر: ({$a->id}) | معرف وحدة الدورة: ({$a->cm}) | معرف المستخدم: ({$a->userid})';

0 commit comments

Comments
 (0)