mirror of
https://github.com/moodle/moodle.git
synced 2025-08-05 08:56:36 +02:00
Merge branch 'MDL-64336-m311' of https://github.com/NeillM/moodle into MOODLE_311_STABLE
This commit is contained in:
commit
4070ef538b
4 changed files with 159 additions and 10 deletions
|
@ -2375,7 +2375,8 @@ class mod_assign_external extends external_api {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve the rest of the renderable objects.
|
// Retrieve the rest of the renderable objects.
|
||||||
if (has_capability('mod/assign:submit', $assign->get_context(), $user)) {
|
$cansubmit = has_capability('mod/assign:submit', $context, $user, false);
|
||||||
|
if ($cansubmit || $assign->get_user_submission($user->id, false) !== false) {
|
||||||
$lastattempt = $assign->get_assign_submission_status_renderable($user, true);
|
$lastattempt = $assign->get_assign_submission_status_renderable($user, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2431,7 +2432,8 @@ class mod_assign_external extends external_api {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can edit its own submission?
|
// Can edit its own submission?
|
||||||
$lastattempt->caneditowner = $assign->submissions_open($user->id) && $assign->is_any_submission_plugin_enabled();
|
$lastattempt->caneditowner = $cansubmit && $assign->submissions_open($user->id)
|
||||||
|
&& $assign->is_any_submission_plugin_enabled();
|
||||||
|
|
||||||
$result['lastattempt'] = $lastattempt;
|
$result['lastattempt'] = $lastattempt;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2091,6 +2091,33 @@ class assign {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns array with sql code and parameters returning all ids of users who have submitted an assignment.
|
||||||
|
*
|
||||||
|
* @param int $group The group that the query is for.
|
||||||
|
* @return array list($sql, $params)
|
||||||
|
*/
|
||||||
|
protected function get_submitted_sql($group = 0) {
|
||||||
|
// We need to guarentee unique table names.
|
||||||
|
static $i = 0;
|
||||||
|
$i++;
|
||||||
|
$prefix = 'sa' . $i . '_';
|
||||||
|
$params = [
|
||||||
|
"{$prefix}assignment" => (int) $this->get_instance()->id,
|
||||||
|
"{$prefix}status" => ASSIGN_SUBMISSION_STATUS_NEW,
|
||||||
|
];
|
||||||
|
$capjoin = get_enrolled_with_capabilities_join($this->context, $prefix, '', $group, $this->show_only_active_users());
|
||||||
|
$params += $capjoin->params;
|
||||||
|
$sql = "SELECT {$prefix}s.userid
|
||||||
|
FROM {assign_submission} {$prefix}s
|
||||||
|
JOIN {user} {$prefix}u ON {$prefix}u.id = {$prefix}s.userid
|
||||||
|
$capjoin->joins
|
||||||
|
WHERE {$prefix}s.assignment = :{$prefix}assignment
|
||||||
|
AND {$prefix}s.status <> :{$prefix}status
|
||||||
|
AND $capjoin->wheres";
|
||||||
|
return array($sql, $params);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a list of users enrolled in the current course with the specified permission and group.
|
* Load a list of users enrolled in the current course with the specified permission and group.
|
||||||
* 0 for no group.
|
* 0 for no group.
|
||||||
|
@ -2098,6 +2125,7 @@ class assign {
|
||||||
*
|
*
|
||||||
* @param int $currentgroup
|
* @param int $currentgroup
|
||||||
* @param bool $idsonly
|
* @param bool $idsonly
|
||||||
|
* @param bool $tablesort
|
||||||
* @return array List of user records
|
* @return array List of user records
|
||||||
*/
|
*/
|
||||||
public function list_participants($currentgroup, $idsonly, $tablesort = false) {
|
public function list_participants($currentgroup, $idsonly, $tablesort = false) {
|
||||||
|
@ -2113,6 +2141,8 @@ class assign {
|
||||||
if (!isset($this->participants[$key])) {
|
if (!isset($this->participants[$key])) {
|
||||||
list($esql, $params) = get_enrolled_sql($this->context, 'mod/assign:submit', $currentgroup,
|
list($esql, $params) = get_enrolled_sql($this->context, 'mod/assign:submit', $currentgroup,
|
||||||
$this->show_only_active_users());
|
$this->show_only_active_users());
|
||||||
|
list($ssql, $sparams) = $this->get_submitted_sql($currentgroup);
|
||||||
|
$params += $sparams;
|
||||||
|
|
||||||
$fields = 'u.*';
|
$fields = 'u.*';
|
||||||
$orderby = 'u.lastname, u.firstname, u.id';
|
$orderby = 'u.lastname, u.firstname, u.id';
|
||||||
|
@ -2159,7 +2189,7 @@ class assign {
|
||||||
|
|
||||||
$sql = "SELECT $fields
|
$sql = "SELECT $fields
|
||||||
FROM {user} u
|
FROM {user} u
|
||||||
JOIN ($esql) je ON je.id = u.id
|
JOIN ($esql UNION $ssql) je ON je.id = u.id
|
||||||
$additionaljoins
|
$additionaljoins
|
||||||
WHERE u.deleted = 0
|
WHERE u.deleted = 0
|
||||||
$additionalfilters
|
$additionalfilters
|
||||||
|
@ -2217,12 +2247,18 @@ class assign {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_enrolled($this->context, $participant, 'mod/assign:submit', $this->show_only_active_users())) {
|
if (!is_enrolled($this->context, $participant, '', $this->show_only_active_users())) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->get_submission_info_for_participants(array($participant->id => $participant));
|
$result = $this->get_submission_info_for_participants(array($participant->id => $participant));
|
||||||
return $result[$participant->id];
|
|
||||||
|
$submissioninfo = $result[$participant->id];
|
||||||
|
if (!$submissioninfo->submitted && !has_capability('mod/assign:submit', $this->context, $userid)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $submissioninfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2311,7 +2347,7 @@ class assign {
|
||||||
if ($currentgroup === null) {
|
if ($currentgroup === null) {
|
||||||
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
|
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
|
||||||
}
|
}
|
||||||
list($esql, $params) = get_enrolled_sql($this->get_context(), 'mod/assign:submit', $currentgroup, true);
|
list($esql, $params) = get_enrolled_sql($this->get_context(), '', $currentgroup, true);
|
||||||
|
|
||||||
$params['assignid'] = $this->get_instance()->id;
|
$params['assignid'] = $this->get_instance()->id;
|
||||||
$params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
|
$params['submitted'] = ASSIGN_SUBMISSION_STATUS_SUBMITTED;
|
||||||
|
@ -2426,7 +2462,7 @@ class assign {
|
||||||
if ($currentgroup === null) {
|
if ($currentgroup === null) {
|
||||||
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
|
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
|
||||||
}
|
}
|
||||||
list($esql, $params) = get_enrolled_sql($this->get_context(), 'mod/assign:submit', $currentgroup, true);
|
list($esql, $params) = get_enrolled_sql($this->get_context(), '', $currentgroup, true);
|
||||||
|
|
||||||
$params['assignid'] = $this->get_instance()->id;
|
$params['assignid'] = $this->get_instance()->id;
|
||||||
$params['assignid2'] = $this->get_instance()->id;
|
$params['assignid2'] = $this->get_instance()->id;
|
||||||
|
@ -4868,7 +4904,7 @@ class assign {
|
||||||
if (has_any_capability(array('mod/assign:viewgrades', 'mod/assign:grade'), $this->context)) {
|
if (has_any_capability(array('mod/assign:viewgrades', 'mod/assign:grade'), $this->context)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ($userid == $USER->id && has_capability('mod/assign:submit', $this->context)) {
|
if ($userid == $USER->id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -5441,8 +5477,9 @@ class assign {
|
||||||
$o = '';
|
$o = '';
|
||||||
|
|
||||||
if ($this->can_view_submission($user->id)) {
|
if ($this->can_view_submission($user->id)) {
|
||||||
|
$cansubmit = has_capability('mod/assign:submit', $this->get_context(), $user, false);
|
||||||
if (has_capability('mod/assign:submit', $this->get_context(), $user, false)) {
|
if ($cansubmit || $this->get_user_submission($user->id, false) !== false) {
|
||||||
|
// The user can submit, or has a submission.
|
||||||
$submissionstatus = $this->get_assign_submission_status_renderable($user, $showlinks);
|
$submissionstatus = $this->get_assign_submission_status_renderable($user, $showlinks);
|
||||||
$o .= $this->get_renderer()->render($submissionstatus);
|
$o .= $this->get_renderer()->render($submissionstatus);
|
||||||
}
|
}
|
||||||
|
@ -5471,6 +5508,10 @@ class assign {
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function show_submit_button($submission = null, $teamsubmission = null, $userid = null) {
|
protected function show_submit_button($submission = null, $teamsubmission = null, $userid = null) {
|
||||||
|
if (!has_capability('mod/assign:submit', $this->get_context(), $userid, false)) {
|
||||||
|
// The user does not have the capability to submit.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($teamsubmission) {
|
if ($teamsubmission) {
|
||||||
if ($teamsubmission->status === ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
|
if ($teamsubmission->status === ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
|
||||||
// The assignment submission has been completed.
|
// The assignment submission has been completed.
|
||||||
|
|
|
@ -28,8 +28,11 @@ defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
global $CFG;
|
global $CFG;
|
||||||
require_once(__DIR__ . '/../locallib.php');
|
require_once(__DIR__ . '/../locallib.php');
|
||||||
|
require_once($CFG->dirroot . '/mod/assign/tests/generator.php');
|
||||||
|
|
||||||
class mod_assign_locallib_participants extends advanced_testcase {
|
class mod_assign_locallib_participants extends advanced_testcase {
|
||||||
|
use mod_assign_test_generator;
|
||||||
|
|
||||||
public function test_list_participants_blind_marking() {
|
public function test_list_participants_blind_marking() {
|
||||||
global $DB;
|
global $DB;
|
||||||
$this->resetAfterTest(true);
|
$this->resetAfterTest(true);
|
||||||
|
@ -118,6 +121,40 @@ class mod_assign_locallib_participants extends advanced_testcase {
|
||||||
$this->assertEquals($newkeys, array_keys($table->rawdata));
|
$this->assertEquals($newkeys, array_keys($table->rawdata));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that users who have a submission, but can no longer submit are listed.
|
||||||
|
*/
|
||||||
|
public function test_list_participants_can_no_longer_submit() {
|
||||||
|
global $DB;
|
||||||
|
$this->resetAfterTest(true);
|
||||||
|
// Create a role that will prevent users submitting.
|
||||||
|
$role = self::getDataGenerator()->create_role();
|
||||||
|
assign_capability('mod/assign:submit', CAP_PROHIBIT, $role, context_system::instance());
|
||||||
|
// Create the test data.
|
||||||
|
$course = self::getDataGenerator()->create_course();
|
||||||
|
$coursecontext = context_course::instance($course->id);
|
||||||
|
$assign = $this->create_instance($course);
|
||||||
|
self::getDataGenerator()->create_and_enrol($course, 'teacher');
|
||||||
|
$student1 = self::getDataGenerator()->create_and_enrol($course, 'student');
|
||||||
|
$student2 = self::getDataGenerator()->create_and_enrol($course, 'student');
|
||||||
|
$cannotsubmit1 = self::getDataGenerator()->create_and_enrol($course, 'student');
|
||||||
|
$cannotsubmit2 = self::getDataGenerator()->create_and_enrol($course, 'student');
|
||||||
|
// Create submissions for some users.
|
||||||
|
$this->add_submission($student1, $assign);
|
||||||
|
$this->submit_for_grading($student1, $assign);
|
||||||
|
$this->add_submission($cannotsubmit1, $assign);
|
||||||
|
$this->submit_for_grading($cannotsubmit1, $assign);
|
||||||
|
// Remove the capability to submit from some users.
|
||||||
|
role_assign($role, $cannotsubmit1->id, $coursecontext);
|
||||||
|
role_assign($role, $cannotsubmit2->id, $coursecontext);
|
||||||
|
// Everything is setup for the test now.
|
||||||
|
$participants = $assign->list_participants(null, true);
|
||||||
|
self::assertCount(3, $participants);
|
||||||
|
self::assertArrayHasKey($student1->id, $participants);
|
||||||
|
self::assertArrayHasKey($student2->id, $participants);
|
||||||
|
self::assertArrayHasKey($cannotsubmit1->id, $participants);
|
||||||
|
}
|
||||||
|
|
||||||
public function helper_add_submission($assign, $user, $data, $type) {
|
public function helper_add_submission($assign, $user, $data, $type) {
|
||||||
global $USER;
|
global $USER;
|
||||||
|
|
||||||
|
|
|
@ -1065,6 +1065,56 @@ class mod_assign_locallib_testcase extends advanced_testcase {
|
||||||
$this->assertFalse($participant->grantedextension);
|
$this->assertFalse($participant->grantedextension);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that if a student with no submission who can no longer submit is not a participant.
|
||||||
|
*/
|
||||||
|
public function test_get_participant_with_no_submission_no_capability() {
|
||||||
|
global $DB;
|
||||||
|
$this->resetAfterTest();
|
||||||
|
$course = self::getDataGenerator()->create_course();
|
||||||
|
$coursecontext = context_course::instance($course->id);
|
||||||
|
$assign = $this->create_instance($course);
|
||||||
|
$teacher = self::getDataGenerator()->create_and_enrol($course, 'teacher');
|
||||||
|
$student = self::getDataGenerator()->create_and_enrol($course, 'student');
|
||||||
|
|
||||||
|
// Remove the students capability to submit.
|
||||||
|
$role = $DB->get_field('role', 'id', ['shortname' => 'student']);
|
||||||
|
assign_capability('mod/assign:submit', CAP_PROHIBIT, $role, $coursecontext);
|
||||||
|
|
||||||
|
$participant = $assign->get_participant($student->id);
|
||||||
|
|
||||||
|
self::assertNull($participant);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests that if a student that has submitted but can no longer submit is a participant.
|
||||||
|
*/
|
||||||
|
public function test_get_participant_with_submission_no_capability() {
|
||||||
|
global $DB;
|
||||||
|
$this->resetAfterTest();
|
||||||
|
$course = self::getDataGenerator()->create_course();
|
||||||
|
$coursecontext = context_course::instance($course->id);
|
||||||
|
$assign = $this->create_instance($course);
|
||||||
|
$teacher = self::getDataGenerator()->create_and_enrol($course, 'teacher');
|
||||||
|
$student = self::getDataGenerator()->create_and_enrol($course, 'student');
|
||||||
|
|
||||||
|
// Simulate a submission.
|
||||||
|
$this->add_submission($student, $assign);
|
||||||
|
$this->submit_for_grading($student, $assign);
|
||||||
|
|
||||||
|
// Remove the students capability to submit.
|
||||||
|
$role = $DB->get_field('role', 'id', ['shortname' => 'student']);
|
||||||
|
assign_capability('mod/assign:submit', CAP_PROHIBIT, $role, $coursecontext);
|
||||||
|
|
||||||
|
$participant = $assign->get_participant($student->id);
|
||||||
|
|
||||||
|
self::assertNotNull($participant);
|
||||||
|
self::assertEquals($student->id, $participant->id);
|
||||||
|
self::assertTrue($participant->submitted);
|
||||||
|
self::assertTrue($participant->requiregrading);
|
||||||
|
self::assertFalse($participant->grantedextension);
|
||||||
|
}
|
||||||
|
|
||||||
public function test_get_participant_with_graded_submission() {
|
public function test_get_participant_with_graded_submission() {
|
||||||
$this->resetAfterTest();
|
$this->resetAfterTest();
|
||||||
$course = $this->getDataGenerator()->create_course();
|
$course = $this->getDataGenerator()->create_course();
|
||||||
|
@ -2345,6 +2395,25 @@ class mod_assign_locallib_testcase extends advanced_testcase {
|
||||||
$output = $assign->view_student_summary($student, true);
|
$output = $assign->view_student_summary($student, true);
|
||||||
$this->assertDoesNotMatchRegularExpression('/Feedback/', $output,
|
$this->assertDoesNotMatchRegularExpression('/Feedback/', $output,
|
||||||
'Do not show feedback if the grade is hidden in the gradebook');
|
'Do not show feedback if the grade is hidden in the gradebook');
|
||||||
|
|
||||||
|
// Freeze the context.
|
||||||
|
$this->setAdminUser();
|
||||||
|
$context = $assign->get_context();
|
||||||
|
$CFG->contextlocking = true;
|
||||||
|
$context->set_locked(true);
|
||||||
|
|
||||||
|
// No feedback should be available because the grade is hidden.
|
||||||
|
$this->setUser($student);
|
||||||
|
$output = $assign->view_student_summary($student, true);
|
||||||
|
$this->assertDoesNotMatchRegularExpression('/Feedback/', $output, 'Do not show feedback if the grade is hidden in the gradebook');
|
||||||
|
|
||||||
|
// Show the feedback again - it should still be visible even in a frozen context.
|
||||||
|
$this->setUser($teacher);
|
||||||
|
$gradeitem->set_hidden(0, false);
|
||||||
|
|
||||||
|
$this->setUser($student);
|
||||||
|
$output = $assign->view_student_summary($student, true);
|
||||||
|
$this->assertMatchesRegularExpression('/Feedback/', $output, 'Show feedback if there is a grade');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_show_student_summary_with_feedback() {
|
public function test_show_student_summary_with_feedback() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue