diff --git a/mod/assign/feedback/comments/locallib.php b/mod/assign/feedback/comments/locallib.php index bfe019c8386..6ba2770ab82 100644 --- a/mod/assign/feedback/comments/locallib.php +++ b/mod/assign/feedback/comments/locallib.php @@ -100,6 +100,29 @@ class assign_feedback_comments extends assign_feedback_plugin { return ($newvalue !== false) && ($newvalue != $commenttext); } + /** + * Has the comment feedback been modified? + * + * @param stdClass $grade The grade object. + * @param stdClass $data Data from the form submission. + * @return boolean True if the comment feedback has been modified, else false. + */ + public function is_feedback_modified(stdClass $grade, stdClass $data) { + $commenttext = ''; + if ($grade) { + $feedbackcomments = $this->get_feedback_comments($grade->id); + if ($feedbackcomments) { + $commenttext = $feedbackcomments->commenttext; + } + } + + if ($commenttext == $data->assignfeedbackcomments_editor['text']) { + return false; + } else { + return true; + } + } + /** * Override to indicate a plugin supports quickgrading. diff --git a/mod/assign/feedback/editpdf/locallib.php b/mod/assign/feedback/editpdf/locallib.php index 0bde7548b8e..57e0e71fee9 100644 --- a/mod/assign/feedback/editpdf/locallib.php +++ b/mod/assign/feedback/editpdf/locallib.php @@ -185,6 +185,53 @@ class assign_feedback_editpdf extends assign_feedback_plugin { } } + /** + * Check to see if the grade feedback for the pdf has been modified. + * + * @param stdClass $grade Grade object. + * @param stdClass $data Data from the form submission (not used). + * @return boolean True if the pdf has been modified, else false. + */ + public function is_feedback_modified(stdClass $grade, stdClass $data) { + global $USER; + $pagenumbercount = document_services::page_number_for_attempt($this->assignment, $grade->userid, $grade->attemptnumber); + for ($i = 0; $i < $pagenumbercount; $i++) { + // Select all annotations. + $draftannotations = page_editor::get_annotations($grade->id, $i, true); + $nondraftannotations = page_editor::get_annotations($grade->id, $i, false); + // Check to see if the count is the same. + if (count($draftannotations) != count($nondraftannotations)) { + // The count is different so we have a modification. + return true; + } else { + // Have a closer look and see if the draft files match the non draft files. + foreach ($nondraftannotations as $index => $ndannotation) { + foreach ($ndannotation as $key => $value) { + if ($key != 'id' && $value != $draftannotations[$index]->$key) { + return true; + } + } + } + } + // Select all comments. + $draftcomments = page_editor::get_comments($grade->id, $i, true); + $nondraftcomments = page_editor::get_comments($grade->id, $i, false); + if (count($draftcomments) != count($nondraftcomments)) { + return true; + } else { + // Go for a closer inspection. + foreach ($nondraftcomments as $index => $ndcomment) { + foreach ($ndcomment as $key => $value) { + if ($key != 'id' && $value != $draftcomments[$index]->$key) { + return true; + } + } + } + } + } + return false; + } + /** * Generate the pdf. * diff --git a/mod/assign/feedback/file/locallib.php b/mod/assign/feedback/file/locallib.php index c4d95bc1eba..27d1b344e29 100644 --- a/mod/assign/feedback/file/locallib.php +++ b/mod/assign/feedback/file/locallib.php @@ -77,6 +77,70 @@ class assign_feedback_file extends assign_feedback_plugin { return $fileoptions; } + /** + * Has the feedback file been modified? + * + * @param stdClass $grade Grade object. + * @param stdClass $data Form data. + * @return boolean True if the file area has been modified, else false. + */ + public function is_feedback_modified(stdClass $grade, stdClass $data) { + global $USER; + + $filekey = null; + $draftareainfo = null; + foreach ($data as $key => $value) { + if (strpos($key, 'files_') === 0) { + $filekey = $key; + } + } + if (isset($filekey)) { + $draftareainfo = file_get_draft_area_info($data->$filekey); + $filecount = $this->count_files($grade->id, ASSIGNFEEDBACK_FILE_FILEAREA); + if ($filecount != $draftareainfo['filecount']) { + return true; + } else { + // We need to check that the files in the draft area are the same as in the file area. + $usercontext = context_user::instance($USER->id); + $fs = get_file_storage(); + $draftfiles = $fs->get_area_files($usercontext->id, 'user', 'draft', $data->$filekey, 'id', true); + $files = $fs->get_area_files($this->assignment->get_context()->id, + 'assignfeedback_file', + ASSIGNFEEDBACK_FILE_FILEAREA, + $grade->id, + 'id', + false); + foreach ($files as $key => $file) { + // Flag for recording if we have a matching file. + $matchflag = false; + foreach ($draftfiles as $draftkey => $draftfile) { + if (!$file->is_directory()) { + // File name is the same, but it could be a different file with the same name. + if ($draftfile->get_filename() == $file->get_filename()) { + // If the file name is the same but the content hash is different, or + // The file path for the file has changed, then we have a modification. + if ($draftfile->get_contenthash() != $file->get_contenthash() || + $draftfile->get_filepath() != $file->get_filepath()) { + return true; + } + // These files match. Check the next file. + $matchflag = true; + // We have a match on the file name so we can move to the next file and not + // proceed through the other draftfiles. + break; + } + } + } + // If the file does not match then there has been a modification. + if (!$matchflag) { + return true; + } + } + } + } + return false; + } + /** * Copy all the files from one file area to another. * diff --git a/mod/assign/feedbackplugin.php b/mod/assign/feedbackplugin.php index 6d793f47a00..8398a49ae44 100644 --- a/mod/assign/feedbackplugin.php +++ b/mod/assign/feedbackplugin.php @@ -112,6 +112,19 @@ abstract class assign_feedback_plugin extends assign_plugin { return false; } + /** + * Has the plugin form element been modified in the current submission? + * + * @param stdClass $grade The grade. + * @param stdClass $data Form data from the feedback form. + * @return boolean - True if the form element has been modified. + */ + public function is_feedback_modified(stdClass $grade, stdClass $data) { + debugging('This plugin has not overwritten the is_feedback_modified() method. Please add this method to your plugin', + DEBUG_DEVELOPER); + return true; + } + /** * Save quickgrading changes. * diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index 5d44ce84494..aa6d88792c6 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -6838,12 +6838,19 @@ class assign { $adminconfig = $this->get_admin_config(); $gradebookplugin = $adminconfig->feedback_plugin_for_gradebook; + $feedbackmodified = false; + // Call save in plugins. foreach ($this->feedbackplugins as $plugin) { if ($plugin->is_enabled() && $plugin->is_visible()) { - if (!$plugin->save($grade, $formdata)) { - $result = false; - print_error($plugin->get_error()); + $gradingmodified = $plugin->is_feedback_modified($grade, $formdata); + if ($gradingmodified) { + if (!$plugin->save($grade, $formdata)) { + $result = false; + print_error($plugin->get_error()); + } + // If $feedbackmodified is true, keep it true. + $feedbackmodified = $feedbackmodified || $gradingmodified; } if (('assignfeedback_' . $plugin->get_type()) == $gradebookplugin) { // This is the feedback plugin chose to push comments to the gradebook. @@ -6852,10 +6859,12 @@ class assign { } } } + // We do not want to update the timemodified if no grade was added. if (!empty($formdata->addattempt) || ($originalgrade !== null && $originalgrade != -1) || - ($grade->grade !== null && $grade->grade != -1)) { + ($grade->grade !== null && $grade->grade != -1) || + $feedbackmodified) { $this->update_grade($grade, !empty($formdata->addattempt)); } // Note the default if not provided for this option is true (e.g. webservices). diff --git a/mod/assign/upgrade.txt b/mod/assign/upgrade.txt index d8d0282c4d7..7cadc8d1694 100644 --- a/mod/assign/upgrade.txt +++ b/mod/assign/upgrade.txt @@ -1,5 +1,9 @@ This files describes API changes in the assign code. +=== 3.1 === +* The feedback plugins now need to implement the is_feedback_modified() method. The default is to return true + for backwards compatibiltiy. + === 3.0 === * assign_submission_status renderable now requires $usergroups in its constructor