Skip to content

Commit

Permalink
Merge pull request #445 from turnitin/develop
Browse files Browse the repository at this point in the history
Release v2018052301
  • Loading branch information
jmcgettrick authored May 23, 2018
2 parents 4013b5e + 5d1e255 commit fc160df
Show file tree
Hide file tree
Showing 52 changed files with 1,253 additions and 505 deletions.
93 changes: 93 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,96 @@
### Date: 2018-May-23
### Release: v2018052301

#### :zap: What's new

---

#### We now support Moodle 3.5

You can find out more about Moodle 3.5 via Moodle's [release notes](https://docs.moodle.org/dev/Moodle_3.5_release_notes).

#### Turnitin's Moodle V2 plugin is GDPR compliant!

To support upcoming changes to European data protection law, we’ve focused our efforts on refreshing our processes around how we use your data.

##### Repository settings are more transparent

We've made the Moodle V2 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.

##### We're reporting on the data we store about our users

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.

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.

#### Students can request to download their data

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.

#### Students can request to remove their data

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 [email protected] to request that student data be removed from Turnitin itself.

> 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.

#### You can now send all papers to your institutional repository by default!

We're aligning Turnitin repository options with our Moodle V2 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.

If you're a Moodle administrator, follow the steps below to enable this repository setting in Turnitin:

1. Log into Turnitin.com or TurnitinUK.com.
2. Under **Edit**, select the cog icon.
3. Select **Edit account settings**.
4. Scroll to **Paper repository options** and select **Submit all papers to the institution repository**.
6. Select the **Submit** button at the bottom of the page.

Now, it's time to move to Moodle!

1. From the Moodle left-hand side panel, select **Site administration**.
2. Select **Plugins**.
3. Select **Activity Modules**.
4. Then **Manage Activities**.
5. Scroll to **Turnitin Assignment 2** and select **Settings**.
6. Scroll to **Paper Repository Assignments** and select **Submit all papers to the institutional repository**.

### :wrench: Fixes and enhancements

#### Assignment titles are now visible in the grade book

This was a bit of an odd one! If an instructor created an assignment with Turnitin GradeMark disabled, the assignment title displayed in the Moodle grade book as the word 'Grade'. We're sure that you'd much rather see the assignment name to be able to distinguish one assignment from the other? Now, you can! Sorry about that!

#### You can now exit lightboxes using the 'Close' button
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.

> **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.
---

### 2018-March-12
### v2018031201

#### Fixes and enhancements

---

#### Manual adjustments to grades now stick during V1 to V2 migration

>Following the migration of a Moodle Direct V1 assignment to V2, grades that had been manually adjusted in the Moodle grade book would be overwritten to match the grade originally set in Turnitin Feedback Studio. With this overwrite being completely unintentional, we've made several backend changes to ensure that future manual adjustments within the grade book always remain fixed during migration.
#### V1 assignments are now removed automatically after migration

>If an administrator failed to delete a Moodle Direct V1 assignment after its migration to V2, the grade of the V1 assignment would remain in the Moodle grade book, causing grades to effectively double. We've now adjusted the behavior of the Moodle Migration Tool to resolve this. So that you no longer need to worry about incorrect grades in the grade book, Moodle V1 assignments are now automatically deleted after migration.
>
>There may be instances where you'll still be required to remove V1 assignments manually (for example, the migration has been successful but there are conflicting grades in the grade book).
#### Deleting V1 assignments that were migrated in prior versions

> You can manually delete your previously migrated assignments from the usual spot in the Moodle Migration Tool; we encourage you to delete these as soon as possible in order to resolve any current issues in the grade book. Any V1 assignments migrated after this update will be automatically deleted.

### :snowflake: Date: 2018-January-16
### :snowflake: Release: v2018011601

Expand Down
6 changes: 5 additions & 1 deletion classes/nonsubmitters/nonsubmitters_message.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class nonsubmitters_message {
* @param string $message
* @return void
*/
public function send_message($userid, $subject, $message) {
public function send_message($userid, $subject, $message, $courseid) {
global $CFG;

// Pre 2.9 does not have \core\message\message()
Expand All @@ -45,6 +45,10 @@ public function send_message($userid, $subject, $message) {
$eventdata->smallmessage = '';
$eventdata->notification = 1; // This is only set to 0 for personal messages between users.

if ($CFG->branch >= 32) {
$eventdata->courseid = $courseid;
}

message_send($eventdata);
}
}
245 changes: 245 additions & 0 deletions classes/privacy/provider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,245 @@
<?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/>.

/**
* Privacy Subsystem implementation for mod_turnitintooltwo.
*
* @package mod_turnitintooltwo
* @copyright 2018 John McGettrick <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

namespace mod_turnitintooltwo\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\helper;
use core_privacy\local\request\writer;

class provider implements
// This plugin does store personal user data.
\core_privacy\local\metadata\provider,

// This plugin is a core_user_data_provider.
\core_privacy\local\request\plugin\provider {

// This is the trait to be included to actually benefit from the polyfill.
use \core_privacy\local\legacy_polyfill;

/**
* Return the fields which contain personal data.
*
* @param $collection items a reference to the collection to use to store the metadata.
* @return $collection the updated collection of metadata items.
*/
public static function _get_metadata(collection $collection) {

$collection->link_subsystem(
'core_files',
'privacy:metadata:core_files'
);

$collection->add_database_table(
'turnitintooltwo_users',
[
'userid' => 'privacy:metadata:turnitintooltwo_users:userid',
'turnitin_uid' => 'privacy:metadata:turnitintooltwo_users:turnitin_uid',
'instructor_defaults' => 'privacy:metadata:turnitintooltwo_users:instructor_defaults',
'instructor_rubrics' => 'privacy:metadata:turnitintooltwo_users:instructor_rubrics',
'user_agreement_accepted' => 'privacy:metadata:turnitintooltwo_users:user_agreement_accepted',
],
'privacy:metadata:turnitintooltwo_users'
);

$collection->add_database_table(
'turnitintooltwo_submissions',
[
'userid' => 'privacy:metadata:turnitintooltwo_submissions:userid',
'submission_title' => 'privacy:metadata:turnitintooltwo_submissions:submission_title',
'submission_filename' => 'privacy:metadata:turnitintooltwo_submissions:submission_filename',
'submission_objectid' => 'privacy:metadata:turnitintooltwo_submissions:submission_objectid',
'submission_score' => 'privacy:metadata:turnitintooltwo_submissions:submission_score',
'submission_grade' => 'privacy:metadata:turnitintooltwo_submissions:submission_grade',
'submission_attempts' => 'privacy:metadata:turnitintooltwo_submissions:submission_attempts',
'submission_modified' => 'privacy:metadata:turnitintooltwo_submissions:submission_modified',
'submission_unanon' => 'privacy:metadata:turnitintooltwo_submissions:submission_unanon',
'submission_unanonreason' => 'privacy:metadata:turnitintooltwo_submissions:submission_unanonreason',
'submission_transmatch' => 'privacy:metadata:turnitintooltwo_submissions:submission_transmatch',
'submission_orcapable' => 'privacy:metadata:turnitintooltwo_submissions:submission_orcapable',
'submission_hash' => 'privacy:metadata:turnitintooltwo_submissions:submission_hash',
],
'privacy:metadata:turnitintooltwo_submissions'
);

$collection->link_external_location('turnitintooltwo_client', [
'email' => 'privacy:metadata:turnitintooltwo_client:email',
'firstname' => 'privacy:metadata:turnitintooltwo_client:firstname',
'lastname' => 'privacy:metadata:turnitintooltwo_client:lastname',
'submission_title' => 'privacy:metadata:turnitintooltwo_client:submission_title',
'submission_filename' => 'privacy:metadata:turnitintooltwo_client:submission_filename',
], 'privacy:metadata:turnitintooltwo_client');

return $collection;
}

/**
* Get the list of contexts that contain user information for the specified user.
*
* @param int $userid the userid.
* @return contextlist the list of contexts containing user info for the user.
*/
public static function _get_contexts_for_userid($userid) {

// Fetch all contexts where the user has a submission.
$sql = "SELECT c.id
FROM {context} c
INNER JOIN {course_modules} cm ON cm.id = c.instanceid AND c.contextlevel = :contextlevel
INNER JOIN {modules} m ON m.id = cm.module AND m.name = :modname
INNER JOIN {turnitintooltwo} t ON t.id = cm.instance
LEFT JOIN {turnitintooltwo_submissions} ts ON ts.turnitintooltwoid = t.id
";

$params = [
'contextlevel' => CONTEXT_MODULE,
'modname' => 'turnitintooltwo',
'userid' => $userid,
];

$contextlist = new contextlist();
$contextlist->add_from_sql($sql, $params);

return $contextlist;
}

/**
* Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
*
* @param approved_contextlist $contextlist a list of contexts approved for export.
*/
public static function _export_user_data(approved_contextlist $contextlist) {
global $DB;

if (empty($contextlist->count())) {
return;
}

$user = $contextlist->get_user();

list($contextsql, $contextparams) = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);

$sql = "SELECT cm.id AS cmid,
ts.submission_title,
ts.submission_filename,
ts.submission_objectid,
ts.submission_score,
ts.submission_grade,
ts.submission_attempts,
ts.submission_modified,
ts.submission_unanon,
ts.submission_unanonreason,
ts.submission_transmatch,
ts.submission_orcapable,
ts.submission_hash,
tu.turnitin_uid,
tu.instructor_defaults,
tu.instructor_rubrics,
tu.user_agreement_accepted
FROM {context} c
INNER JOIN {course_modules} cm ON cm.id = c.instanceid
INNER JOIN {turnitintooltwo} t ON t.id = cm.instance
LEFT JOIN {turnitintooltwo_submissions} ts ON ts.turnitintooltwoid = t.id
LEFT JOIN {turnitintooltwo_users} tu ON ts.userid = tu.userid
WHERE c.id {$contextsql}
AND ts.userid = :userid
ORDER BY cm.id";

$params = ['userid' => $user->id] + $contextparams;

$submissions = $DB->get_records_sql($sql, $params);
foreach ($submissions as $submission) {
$context = \context_module::instance($submission->cmid);
self::_export_turnitintooltwo_data_for_user((array)$submission, $context, $user);
}
}

/**
* Export the supplied personal data for a single activity, along with any generic data or area files.
*
* @param array $submissiondata the personal data to export.
* @param \context_module $context the module context.
* @param \stdClass $user the user record
*/
protected static function _export_turnitintooltwo_data_for_user(array $submissiondata, \context_module $context, \stdClass $user) {
// Fetch the generic module data.
$contextdata = helper::get_context_data($context, $user);

// Merge with module data and write it.
$contextdata = (object)array_merge((array)$contextdata, $submissiondata);
writer::with_context($context)->export_data([], $contextdata);

// Write generic module intro files.
helper::export_context_files($context, $user);
}

/**
* Delete all data for all users in the specified context.
*
* @param \context $context the context to delete in.
*/
public static function _delete_data_for_all_users_in_context(\context $context) {
global $DB;

if (empty($context)) {
return;
}

if (!$context instanceof \context_module) {
return;
}

$instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
$DB->delete_records('turnitintooltwo_submissions', ['turnitintooltwoid' => $instanceid]);
}

/**
* Delete all user data for the specified user, in the specified contexts.
*
* @param approved_contextlist $contextlist a list of contexts approved for deletion.
*/
public static function _delete_data_for_user(approved_contextlist $contextlist) {
global $DB;

if (empty($contextlist->count())) {
return;
}

// Delete records.
foreach ($contextlist->get_contexts() as $context) {

if (!$context instanceof \context_module) {
return;
}
$instanceid = $DB->get_field('course_modules', 'instance', ['id' => $context->instanceid], MUST_EXIST);
$DB->delete_records(
'turnitintooltwo_submissions',
['turnitintooltwoid' => $instanceid, 'userid' => $contextlist->get_user()->id]
);
}
}
}
Loading

0 comments on commit fc160df

Please sign in to comment.