diff --git a/mod/workshop/assessment.php b/mod/workshop/assessment.php index 36dbcb9456f..df504ff04eb 100644 --- a/mod/workshop/assessment.php +++ b/mod/workshop/assessment.php @@ -55,25 +55,11 @@ $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); $PAGE->navbar->add(get_string('assessingsubmission', 'workshop')); -$canviewallassessments = has_capability('mod/workshop:viewallassessments', $workshop->context); -$canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $workshop->context); $cansetassessmentweight = has_capability('mod/workshop:allocate', $workshop->context); $canoverridegrades = has_capability('mod/workshop:overridegrades', $workshop->context); $isreviewer = ($USER->id == $assessment->reviewerid); -$isauthor = ($USER->id == $submission->authorid); -$canviewallsubmissions = $canviewallsubmissions && $workshop->check_group_membership($submission->authorid); - -if ($isreviewer or $isauthor or ($canviewallassessments and $canviewallsubmissions)) { - // such a user can continue -} else { - print_error('nopermissions', 'error', $workshop->view_url(), 'view this assessment'); -} - -if ($isauthor and !$isreviewer and !$canviewallassessments and $workshop->phase != workshop::PHASE_CLOSED) { - // authors can see assessments of their work at the end of workshop only - print_error('nopermissions', 'error', $workshop->view_url(), 'view assessment of own work before workshop is closed'); -} +$workshop->check_view_assessment($assessment, $submission); // only the reviewer is allowed to modify the assessment if ($isreviewer and $workshop->assessing_allowed($USER->id)) { diff --git a/mod/workshop/classes/external.php b/mod/workshop/classes/external.php index 3c1e13ff99b..0d5743935bf 100644 --- a/mod/workshop/classes/external.php +++ b/mod/workshop/classes/external.php @@ -1116,4 +1116,70 @@ class mod_workshop_external extends external_api { ) ); } + + /** + * Returns the description of the external function parameters. + * + * @return external_function_parameters + * @since Moodle 3.4 + */ + public static function get_assessment_parameters() { + return new external_function_parameters( + array( + 'assessmentid' => new external_value(PARAM_INT, 'Assessment id'), + ) + ); + } + + + /** + * Retrieves the given assessment. + * + * @param int $assessmentid the assessment id + * @return array containing the assessment and warnings. + * @since Moodle 3.4 + * @throws moodle_exception + */ + public static function get_assessment($assessmentid) { + global $DB, $PAGE; + + $params = self::validate_parameters(self::get_assessment_parameters(), array('assessmentid' => $assessmentid)); + $warnings = array(); + + // Get and validate the assessment, submission and workshop. + $assessment = $DB->get_record('workshop_assessments', array('id' => $params['assessmentid']), '*', MUST_EXIST); + $submission = $DB->get_record('workshop_submissions', array('id' => $assessment->submissionid), '*', MUST_EXIST); + list($workshop, $course, $cm, $context) = self::validate_workshop($submission->workshopid); + + // Check that we can get the assessment. + $workshop->check_view_assessment($assessment, $submission); + + $assessment = $workshop->get_assessment_by_id($assessment->id); + $assessment = self::prepare_assessment_for_external($assessment, $workshop); + if (empty($assessment)) { + throw new moodle_exception('nopermissions', 'error', '', 'view assessment'); + } + $related = array('context' => $context); + $exporter = new assessment_exporter($assessment, $related); + + return array( + 'assessment' => $exporter->export($PAGE->get_renderer('core')), + 'warnings' => $warnings + ); + } + + /** + * Returns description of method result value + * + * @return external_description + * @since Moodle 3.4 + */ + public static function get_assessment_returns() { + return new external_single_structure( + array( + 'assessment' => assessment_exporter::get_read_structure(), + 'warnings' => new external_warnings() + ) + ); + } } diff --git a/mod/workshop/db/services.php b/mod/workshop/db/services.php index 497b793dac5..341e017b662 100644 --- a/mod/workshop/db/services.php +++ b/mod/workshop/db/services.php @@ -106,4 +106,11 @@ $functions = array( 'type' => 'read', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) ), + 'mod_workshop_get_assessment' => array( + 'classname' => 'mod_workshop_external', + 'methodname' => 'get_assessment', + 'description' => 'Retrieves the given assessment.', + 'type' => 'read', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE) + ), ); diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 4baddbe4bee..0a6cb3c9bf9 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -2940,6 +2940,35 @@ class workshop { return $submission->id; } + /** + * Helper method for validating if the current user can view the given assessment. + * + * @param stdClass $assessment assessment object + * @param stdClass $submission submission object + * @return void + * @throws moodle_exception + * @since Moodle 3.4 + */ + public function check_view_assessment($assessment, $submission) { + global $USER; + + $isauthor = $submission->authorid == $USER->id; + $isreviewer = $assessment->reviewerid == $USER->id; + $canviewallassessments = has_capability('mod/workshop:viewallassessments', $this->context); + $canviewallsubmissions = has_capability('mod/workshop:viewallsubmissions', $this->context); + + $canviewallsubmissions = $canviewallsubmissions && $this->check_group_membership($submission->authorid); + + if (!$isreviewer and !$isauthor and !($canviewallassessments and $canviewallsubmissions)) { + print_error('nopermissions', 'error', $this->view_url(), 'view this assessment'); + } + + if ($isauthor and !$isreviewer and !$canviewallassessments and $this->phase != self::PHASE_CLOSED) { + // Authors can see assessments of their work at the end of workshop only. + print_error('nopermissions', 'error', $this->view_url(), 'view assessment of own work before workshop is closed'); + } + } + //////////////////////////////////////////////////////////////////////////////// // Internal methods (implementation details) // //////////////////////////////////////////////////////////////////////////////// diff --git a/mod/workshop/tests/external_test.php b/mod/workshop/tests/external_test.php index 075f31b3902..17e30e3ca7c 100644 --- a/mod/workshop/tests/external_test.php +++ b/mod/workshop/tests/external_test.php @@ -1142,4 +1142,125 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $this->assertEquals(50, $result['assessments'][0]['grade']); $this->assertEquals($assessmentid, $result['assessments'][0]['id']); } + + /** + * Test get_assessment_author. + */ + public function test_get_assessment_author() { + global $DB; + + // Create the submission. + $submissionid = $this->create_test_submission($this->anotherstudentg1); + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( + 'weight' => 2, + 'grade' => 90, + )); + + // Switch to closed phase. + $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id)); + $this->setUser($this->anotherstudentg1); + $result = mod_workshop_external::get_assessment($assessmentid); + $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); + $this->assertEquals($assessmentid, $result['assessment']['id']); + $this->assertEquals(90, $result['assessment']['grade']); + // I can't see the reviewer review. + $this->assertFalse(isset($result['assessment']['feedbackreviewer'])); + } + + /** + * Test get_assessment_reviewer. + */ + public function test_get_assessment_reviewer() { + global $DB; + + // Create the submission. + $submissionid = $this->create_test_submission($this->anotherstudentg1); + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( + 'weight' => 2, + 'grade' => 90, + )); + + // Switch to closed phase. + $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id)); + $this->setUser($this->student); + $result = mod_workshop_external::get_assessment($assessmentid); + $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); + $this->assertEquals($assessmentid, $result['assessment']['id']); + $this->assertEquals(90, $result['assessment']['grade']); + // I can see the reviewer review. + $this->assertTrue(isset($result['assessment']['feedbackreviewer'])); + } + + /** + * Test get_assessment_teacher. + */ + public function test_get_assessment_teacher() { + global $DB; + + // Create the submission. + $submissionid = $this->create_test_submission($this->anotherstudentg1); + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( + 'weight' => 2, + 'grade' => 90, + )); + + // Switch to closed phase. + $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id)); + $this->setUser($this->teacher); + $result = mod_workshop_external::get_assessment($assessmentid); + $result = external_api::clean_returnvalue(mod_workshop_external::get_assessment_returns(), $result); + $this->assertEquals($assessmentid, $result['assessment']['id']); + $this->assertEquals(90, $result['assessment']['grade']); + } + + /** + * Test get_assessment_student_invalid_phase. + */ + public function test_get_assessment_student_invalid_phase() { + global $DB; + + // Create the submission. + $submissionid = $this->create_test_submission($this->anotherstudentg1); + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( + 'weight' => 2, + 'grade' => 90, + )); + + // Switch to closed phase. + $this->setUser($this->anotherstudentg1); + + $this->setExpectedException('moodle_exception'); + mod_workshop_external::get_assessment($assessmentid); + } + + /** + * Test get_assessment_student_invalid_user. + */ + public function test_get_assessment_student_invalid_user() { + global $DB; + + // Create the submission. + $submissionid = $this->create_test_submission($this->anotherstudentg1); + + $workshopgenerator = $this->getDataGenerator()->get_plugin_generator('mod_workshop'); + $assessmentid = $workshopgenerator->create_assessment($submissionid, $this->student->id, array( + 'weight' => 2, + 'grade' => 90, + )); + + // Switch to closed phase. + $DB->set_field('workshop', 'phase', workshop::PHASE_CLOSED, array('id' => $this->workshop->id)); + $this->setUser($this->anotherstudentg2); + + $this->setExpectedException('moodle_exception'); + mod_workshop_external::get_assessment($assessmentid); + } } diff --git a/mod/workshop/version.php b/mod/workshop/version.php index 12fb42529bb..487445b0a54 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2017051510; // The current module version (YYYYMMDDXX) +$plugin->version = 2017051511; // The current module version (YYYYMMDDXX) $plugin->requires = 2017050500; // Requires this Moodle version. $plugin->component = 'mod_workshop'; $plugin->cron = 60; // Give as a chance every minute.