MDL-29795 mod_assign: Add user/group override assignment module

This commit is contained in:
Ilya Tregubov 2016-07-18 19:08:50 +10:00 committed by Juan Leyva
parent 919b9dfabd
commit d685b95935
30 changed files with 3307 additions and 17 deletions

View File

@ -130,6 +130,10 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
'name',
'value'));
$overrides = new backup_nested_element('overrides');
$override = new backup_nested_element('override', array('id'), array(
'groupid', 'userid', 'allowsubmissionsfromdate', 'duedate', 'cutoffdate'));
// Build the tree.
$assign->add_child($userflags);
$userflags->add_child($userflag);
@ -139,12 +143,17 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
$grades->add_child($grade);
$assign->add_child($pluginconfigs);
$pluginconfigs->add_child($pluginconfig);
$assign->add_child($overrides);
$overrides->add_child($override);
// Define sources.
$assign->set_source_table('assign', array('id' => backup::VAR_ACTIVITYID));
$pluginconfig->set_source_table('assign_plugin_config',
array('assignment' => backup::VAR_PARENTID));
// Assign overrides to backup are different depending of user info.
$overrideparams = array('assignid' => backup::VAR_PARENTID);
if ($userinfo) {
$userflag->set_source_table('assign_user_flags',
array('assignment' => backup::VAR_PARENTID));
@ -158,8 +167,12 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
// Support 2 types of subplugins.
$this->add_subplugin_structure('assignsubmission', $submission, true);
$this->add_subplugin_structure('assignfeedback', $grade, true);
} else {
$overrideparams['userid'] = backup_helper::is_sqlparam(null); // Without userinfo, skip user overrides.
}
$override->set_source_table('assign_overrides', $overrideparams);
// Define id annotations.
$userflag->annotate_ids('user', 'userid');
$userflag->annotate_ids('user', 'allocatedmarker');
@ -168,6 +181,8 @@ class backup_assign_activity_structure_step extends backup_activity_structure_st
$grade->annotate_ids('user', 'userid');
$grade->annotate_ids('user', 'grader');
$assign->annotate_ids('grouping', 'teamsubmissiongroupingid');
$override->annotate_ids('user', 'userid');
$override->annotate_ids('group', 'groupid');
// Define file annotations.
// These file areas don't have an itemid.

View File

@ -65,6 +65,7 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
$userflag = new restore_path_element('assign_userflag',
'/activity/assign/userflags/userflag');
$paths[] = $userflag;
$paths[] = new restore_path_element('assign_override', '/activity/assign/overrides/override');
}
$paths[] = new restore_path_element('assign_plugin_config',
'/activity/assign/plugin_configs/plugin_config');
@ -353,6 +354,44 @@ class restore_assign_activity_structure_step extends restore_activity_structure_
}
}
/**
* Process a assign override restore
* @param object $data The data in object form
* @return void
*/
protected function process_assign_override($data) {
global $DB;
$data = (object)$data;
$oldid = $data->id;
// Based on userinfo, we'll restore user overides or no.
$userinfo = $this->get_setting_value('userinfo');
// Skip user overrides if we are not restoring userinfo.
if (!$userinfo && !is_null($data->userid)) {
return;
}
$data->assignid = $this->get_new_parentid('assign');
if (!is_null($data->userid)) {
$data->userid = $this->get_mappingid('user', $data->userid);
}
if (!is_null($data->groupid)) {
$data->groupid = $this->get_mappingid('group', $data->groupid);
}
$data->allowsubmissionsfromdate = $this->apply_date_offset($data->allowsubmissionsfromdate);
$data->duedate = $this->apply_date_offset($data->duedate);
$data->cutoffdate = $this->apply_date_offset($data->cutoffdate);
$newitemid = $DB->insert_record('assign_overrides', $data);
// Add mapping, restore of logs needs it.
$this->set_mapping('assign_override', $oldid, $newitemid);
}
/**
* Once the database tables have been fully restored, restore the files
* @return void

View File

@ -0,0 +1,118 @@
<?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/>.
/**
* The mod_assign group override created event.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_assign group override created event class.
*
* @property-read array $other {
* Extra information about event.
*
* - int assignid: the id of the assign.
* - int groupid: the id of the group.
* }
*
* @package mod_assign
* @since Moodle 3.2
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class group_override_created extends \core\event\base {
/**
* Init method.
*/
protected function init() {
$this->data['objecttable'] = 'assign_overrides';
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_TEACHING;
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventoverridecreated', 'mod_assign');
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' created the override with id '$this->objectid' for the assign with " .
"course module id '$this->contextinstanceid' for the group with id '{$this->other['groupid']}'.";
}
/**
* Returns relevant URL.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/assign/overrideedit.php', array('id' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
if (!isset($this->other['assignid'])) {
throw new \coding_exception('The \'assignid\' value must be set in other.');
}
if (!isset($this->other['groupid'])) {
throw new \coding_exception('The \'groupid\' value must be set in other.');
}
}
/**
* Get objectid mapping
*/
public static function get_objectid_mapping() {
return array('db' => 'assign_overrides', 'restore' => 'assign_override');
}
/**
* Get other mapping
*/
public static function get_other_mapping() {
$othermapped = array();
$othermapped['assignid'] = array('db' => 'assign', 'restore' => 'assign');
$othermapped['groupid'] = array('db' => 'groups', 'restore' => 'group');
return $othermapped;
}
}

View File

@ -0,0 +1,117 @@
<?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/>.
/**
* The mod_assign group override deleted event.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_assign group override deleted event class.
*
* @property-read array $other {
* Extra information about event.
*
* - int assignid: the id of the assign.
* - int groupid: the id of the group.
* }
*
* @package mod_assign
* @since Moodle 3.2
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class group_override_deleted extends \core\event\base {
/**
* Init method.
*/
protected function init() {
$this->data['objecttable'] = 'assign_overrides';
$this->data['crud'] = 'd';
$this->data['edulevel'] = self::LEVEL_TEACHING;
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventoverridedeleted', 'mod_assign');
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' deleted the override with id '$this->objectid' for the assign with " .
"course module id '$this->contextinstanceid' for the group with id '{$this->other['groupid']}'.";
}
/**
* Returns relevant URL.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/assign/overrides.php', array('cmid' => $this->contextinstanceid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
if (!isset($this->other['assignid'])) {
throw new \coding_exception('The \'assignid\' value must be set in other.');
}
if (!isset($this->other['groupid'])) {
throw new \coding_exception('The \'groupid\' value must be set in other.');
}
}
/**
* Get objectid mapping
*/
public static function get_objectid_mapping() {
return array('db' => 'assign_overrides', 'restore' => 'assign_override');
}
/**
* Get other mapping
*/
public static function get_other_mapping() {
$othermapped = array();
$othermapped['assignid'] = array('db' => 'assign', 'restore' => 'assign');
$othermapped['groupid'] = array('db' => 'groups', 'restore' => 'group');
return $othermapped;
}
}

View File

@ -0,0 +1,117 @@
<?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/>.
/**
* The mod_assign group override updated event.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_assign group override updated event class.
*
* @property-read array $other {
* Extra information about event.
*
* - int assignid: the id of the assign.
* - int groupid: the id of the group.
* }
*
* @package mod_assign
* @since Moodle 3.2
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class group_override_updated extends \core\event\base {
/**
* Init method.
*/
protected function init() {
$this->data['objecttable'] = 'assign_overrides';
$this->data['crud'] = 'u';
$this->data['edulevel'] = self::LEVEL_TEACHING;
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventoverrideupdated', 'mod_assign');
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' updated the override with id '$this->objectid' for the assign with " .
"course module id '$this->contextinstanceid' for the group with id '{$this->other['groupid']}'.";
}
/**
* Returns relevant URL.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/assign/overrideedit.php', array('id' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
if (!isset($this->other['assignid'])) {
throw new \coding_exception('The \'assignid\' value must be set in other.');
}
if (!isset($this->other['groupid'])) {
throw new \coding_exception('The \'groupid\' value must be set in other.');
}
}
/**
* Get objectid mapping
*/
public static function get_objectid_mapping() {
return array('db' => 'assign_overrides', 'restore' => 'assign_override');
}
/**
* Get other mapping
*/
public static function get_other_mapping() {
$othermapped = array();
$othermapped['assignid'] = array('db' => 'assign', 'restore' => 'assign');
$othermapped['groupid'] = array('db' => 'groups', 'restore' => 'group');
return $othermapped;
}
}

View File

@ -0,0 +1,115 @@
<?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/>.
/**
* The mod_assign user override created event.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_assign user override created event class.
*
* @property-read array $other {
* Extra information about event.
*
* - int assignid: the id of the assign.
* }
*
* @package mod_assign
* @since Moodle 3.2
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_override_created extends \core\event\base {
/**
* Init method.
*/
protected function init() {
$this->data['objecttable'] = 'assign_overrides';
$this->data['crud'] = 'c';
$this->data['edulevel'] = self::LEVEL_TEACHING;
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventoverridecreated', 'mod_assign');
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' created the override with id '$this->objectid' for the assign with " .
"course module id '$this->contextinstanceid' for the user with id '{$this->relateduserid}'.";
}
/**
* Returns relevant URL.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/assign/overrideedit.php', array('id' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
if (!isset($this->relateduserid)) {
throw new \coding_exception('The \'relateduserid\' must be set.');
}
if (!isset($this->other['assignid'])) {
throw new \coding_exception('The \'assignid\' value must be set in other.');
}
}
/**
* Get objectid mapping
*/
public static function get_objectid_mapping() {
return array('db' => 'assign_overrides', 'restore' => 'assign_override');
}
/**
* Get other mapping
*/
public static function get_other_mapping() {
$othermapped = array();
$othermapped['assignid'] = array('db' => 'assign', 'restore' => 'assign');
return $othermapped;
}
}

View File

@ -0,0 +1,115 @@
<?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/>.
/**
* The mod_assign user override deleted event.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_assign user override deleted event class.
*
* @property-read array $other {
* Extra information about event.
*
* - int assignid: the id of the assign.
* }
*
* @package mod_assign
* @since Moodle 3.2
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_override_deleted extends \core\event\base {
/**
* Init method.
*/
protected function init() {
$this->data['objecttable'] = 'assign_overrides';
$this->data['crud'] = 'd';
$this->data['edulevel'] = self::LEVEL_TEACHING;
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventoverridedeleted', 'mod_assign');
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' deleted the override with id '$this->objectid' for the assign with " .
"course module id '$this->contextinstanceid' for the user with id '{$this->relateduserid}'.";
}
/**
* Returns relevant URL.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/assign/overrides.php', array('cmid' => $this->contextinstanceid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
if (!isset($this->relateduserid)) {
throw new \coding_exception('The \'relateduserid\' must be set.');
}
if (!isset($this->other['assignid'])) {
throw new \coding_exception('The \'assignid\' value must be set in other.');
}
}
/**
* Get objectid mapping
*/
public static function get_objectid_mapping() {
return array('db' => 'assign_overrides', 'restore' => 'assign_override');
}
/**
* Get other mapping
*/
public static function get_other_mapping() {
$othermapped = array();
$othermapped['assignid'] = array('db' => 'assign', 'restore' => 'assign');
return $othermapped;
}
}

View File

@ -0,0 +1,116 @@
<?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/>.
/**
* The mod_assign user override updated event.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign\event;
defined('MOODLE_INTERNAL') || die();
/**
* The mod_assign user override updated event class.
*
* @property-read array $other {
* Extra information about event.
*
* - int assignid: the id of the assign.
* }
*
* @package mod_assign
* @since Moodle 3.2
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_override_updated extends \core\event\base {
/**
* Init method.
*/
protected function init() {
$this->data['objecttable'] = 'assign_overrides';
$this->data['crud'] = 'u';
$this->data['edulevel'] = self::LEVEL_TEACHING;
}
/**
* Returns localised general event name.
*
* @return string
*/
public static function get_name() {
return get_string('eventoverrideupdated', 'mod_assign');
}
/**
* Returns description of what happened.
*
* @return string
*/
public function get_description() {
return "The user with id '$this->userid' updated the override with id '$this->objectid' for the assign with " .
"course module id '$this->contextinstanceid' for the user with id '{$this->relateduserid}'.";
}
/**
* Returns relevant URL.
*
* @return \moodle_url
*/
public function get_url() {
return new \moodle_url('/mod/assign/overrideedit.php', array('id' => $this->objectid));
}
/**
* Custom validation.
*
* @throws \coding_exception
* @return void
*/
protected function validate_data() {
parent::validate_data();
if (!isset($this->relateduserid)) {
throw new \coding_exception('The \'relateduserid\' must be set.');
}
if (!isset($this->other['assignid'])) {
throw new \coding_exception('The \'assignid\' value must be set in other.');
}
}
/**
* Get objectid mapping
*/
public static function get_objectid_mapping() {
return array('db' => 'assign_overrides', 'restore' => 'assign_override');
}
/**
* Get other mapping
*/
public static function get_other_mapping() {
$othermapped = array();
$othermapped['assignid'] = array('db' => 'assign', 'restore' => 'assign');
return $othermapped;
}
}

View File

@ -0,0 +1,85 @@
<?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/>.
/**
* Group observers.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_assign;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/mod/assign/locallib.php');
/**
* Group observers class.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class group_observers {
/**
* Flag whether a course reset is in progress or not.
*
* @var int The course ID.
*/
protected static $resetinprogress = false;
/**
* A course reset has started.
*
* @param \core\event\base $event The event.
* @return void
*/
public static function course_reset_started($event) {
self::$resetinprogress = $event->courseid;
}
/**
* A course reset has ended.
*
* @param \core\event\base $event The event.
* @return void
*/
public static function course_reset_ended($event) {
if (!empty(self::$resetinprogress)) {
if (!empty($event->other['reset_options']['reset_groups_remove'])) {
assign_process_group_deleted_in_course($event->courseid);
}
}
self::$resetinprogress = null;
}
/**
* A group was deleted.
*
* @param \core\event\base $event The event.
* @return void
*/
public static function group_deleted($event) {
if (!empty(self::$resetinprogress)) {
// We will take care of that once the course reset ends.
return;
}
assign_process_group_deleted_in_course($event->courseid, $event->objectid);
}
}

View File

@ -178,5 +178,15 @@ $capabilities = array(
'manager' => CAP_ALLOW
)
),
// Edit the assign overrides.
'mod/assign:manageoverrides' => array(
'captype' => 'write',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'editingteacher' => CAP_ALLOW,
'manager' => CAP_ALLOW
)
),
);

43
mod/assign/db/events.php Normal file
View File

@ -0,0 +1,43 @@
<?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/>.
/**
* Add event handlers for the assign
*
* @package mod_assign
* @category event
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$observers = array(
array(
'eventname' => '\core\event\course_reset_started',
'callback' => '\mod_assign\group_observers::course_reset_started',
),
array(
'eventname' => '\core\event\course_reset_ended',
'callback' => '\mod_assign\group_observers::course_reset_ended',
),
array(
'eventname' => '\core\event\group_deleted',
'callback' => '\mod_assign\group_observers::group_deleted'
),
);

View File

@ -138,5 +138,23 @@
<INDEX NAME="mailed" UNIQUE="false" FIELDS="mailed" COMMENT="Has this user been mailed yet?"/>
</INDEXES>
</TABLE>
<TABLE NAME="assign_overrides" COMMENT="The overrides to assign settings.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="assignid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Foreign key references assign.id"/>
<FIELD NAME="groupid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Foreign key references groups.id. Can be null if this is a per-user override."/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Foreign key references user.id. Can be null if this is a per-group override."/>
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Rank for sorting overrides."/>
<FIELD NAME="allowsubmissionsfromdate" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Time at which students may start attempting this assign. Can be null, in which case the assign default is used."/>
<FIELD NAME="duedate" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Time by which students must have completed their attempt. Can be null, in which case the assign default is used."/>
<FIELD NAME="cutoffdate" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false" COMMENT="Time by which students must have completed their attempt. Can be null, in which case the assign default is used."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="assignid" TYPE="foreign" FIELDS="assignid" REFTABLE="assign" REFFIELDS="id"/>
<KEY NAME="groupid" TYPE="foreign" FIELDS="groupid" REFTABLE="groups" REFFIELDS="id"/>
<KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>

View File

@ -200,5 +200,35 @@ function xmldb_assign_upgrade($oldversion) {
// Moodle v3.1.0 release upgrade line.
// Put any upgrade step following this.
if ($oldversion < 2016070402) {
// Define table assign_overrides to be created.
$table = new xmldb_table('assign_overrides');
// Adding fields to table assign_overrides.
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('assignid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
$table->add_field('groupid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('allowsubmissionsfromdate', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('duedate', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
$table->add_field('cutoffdate', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
// Adding keys to table assign_overrides.
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->add_key('assignid', XMLDB_KEY_FOREIGN, array('assignid'), 'assign', array('id'));
$table->add_key('groupid', XMLDB_KEY_FOREIGN, array('groupid'), 'groups', array('id'));
$table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
// Conditionally launch create table for assign_overrides.
if (!$dbman->table_exists($table)) {
$dbman->create_table($table);
}
// Assign savepoint reached.
upgrade_mod_savepoint(true, 2016070402, 'assign');
}
return true;
}

View File

@ -2720,6 +2720,10 @@ class mod_assign_external extends external_api {
$assign->require_view_grades();
$participant = $assign->get_participant($params['userid']);
// Update assign with override information.
$assign->update_effective_access($params['userid']);
if (!$participant) {
// No participant found so we can return early.
throw new moodle_exception('usernotincourse');
@ -2731,6 +2735,10 @@ class mod_assign_external extends external_api {
'submitted' => $participant->submitted,
'requiregrading' => $participant->requiregrading,
'blindmarking' => $assign->is_blind_marking(),
'allowsubmissionsfromdate' => $assign->get_instance()->allowsubmissionsfromdate,
'duedate' => $assign->get_instance()->duedate,
'cutoffdate' => $assign->get_instance()->cutoffdate,
'duedatestr' => userdate($assign->get_instance()->duedate),
);
if (!empty($participant->groupid)) {
@ -2766,6 +2774,10 @@ class mod_assign_external extends external_api {
'submitted' => new external_value(PARAM_BOOL, 'have they submitted their assignment'),
'requiregrading' => new external_value(PARAM_BOOL, 'is their submission waiting for grading'),
'blindmarking' => new external_value(PARAM_BOOL, 'is blind marking enabled for this assignment'),
'allowsubmissionsfromdate' => new external_value(PARAM_INT, 'allowsubmissionsfromdate for the user'),
'duedate' => new external_value(PARAM_INT, 'duedate for the user'),
'cutoffdate' => new external_value(PARAM_INT, 'cutoffdate for the user'),
'duedatestr' => new external_value(PARAM_TEXT, 'duedate for the user'),
'groupid' => new external_value(PARAM_INT, 'for group assignments this is the group id', VALUE_OPTIONAL),
'groupname' => new external_value(PARAM_NOTAGS, 'for group assignments this is the group name', VALUE_OPTIONAL),
'user' => $userdescription,

View File

@ -131,6 +131,12 @@ class assign_grading_table extends table_sql implements renderable {
$params['assignmentid2'] = (int)$this->assignment->get_instance()->id;
$params['assignmentid3'] = (int)$this->assignment->get_instance()->id;
$params['assignmentid5'] = (int)$this->assignment->get_instance()->id;
$params['assignmentid6'] = (int)$this->assignment->get_instance()->id;
$params['assignmentid7'] = (int)$this->assignment->get_instance()->id;
$params['assignmentid8'] = (int)$this->assignment->get_instance()->id;
$params['assignmentid9'] = (int)$this->assignment->get_instance()->id;
$extrauserfields = get_extra_user_fields($this->assignment->get_context());
$fields = user_picture::fields('u', $extrauserfields) . ', ';
@ -148,7 +154,11 @@ class assign_grading_table extends table_sql implements renderable {
$fields .= 'uf.locked as locked, ';
$fields .= 'uf.extensionduedate as extensionduedate, ';
$fields .= 'uf.workflowstate as workflowstate, ';
$fields .= 'uf.allocatedmarker as allocatedmarker ';
$fields .= 'uf.allocatedmarker as allocatedmarker, ';
$fields .= 'priority.priority, ';
$fields .= 'effective.allowsubmissionsfromdate, ';
$fields .= 'effective.duedate, ';
$fields .= 'effective.cutoffdate ';
$from = '{user} u
LEFT JOIN {assign_submission} s
@ -178,6 +188,62 @@ class assign_grading_table extends table_sql implements renderable {
ON u.id = uf.userid
AND uf.assignment = :assignmentid3 ';
$from .= ' LEFT JOIN (
SELECT merged.userid, min(merged.priority) priority FROM (
( SELECT u.id as userid, 9999999 AS priority
FROM {user} u
)
UNION
( SELECT uo.userid, 0 AS priority
FROM {assign_overrides} uo
WHERE uo.assignid = :assignmentid5
)
UNION
( SELECT gm.userid, go.sortorder AS priority
FROM {assign_overrides} go
JOIN {groups} g ON g.id = go.groupid
JOIN {groups_members} gm ON gm.groupid = g.id
WHERE go.assignid = :assignmentid6
)
) AS merged
GROUP BY merged.userid
) priority ON priority.userid = u.id
JOIN (
(SELECT 9999999 AS priority,
u.id AS userid,
a.allowsubmissionsfromdate,
a.duedate,
a.cutoffdate
FROM {user} u
JOIN {assign} a ON a.id = :assignmentid7
)
UNION
(SELECT 0 AS priority,
uo.userid,
uo.allowsubmissionsfromdate,
uo.duedate,
uo.cutoffdate
FROM {assign_overrides} uo
WHERE uo.assignid = :assignmentid8
)
UNION
(SELECT go.sortorder AS priority,
gm.userid,
go.allowsubmissionsfromdate,
go.duedate,
go.cutoffdate
FROM {assign_overrides} go
JOIN {groups} g ON g.id = go.groupid
JOIN {groups_members} gm ON gm.groupid = g.id
WHERE go.assignid = :assignmentid9
)
) AS effective ON effective.priority = priority.priority AND effective.userid = priority.userid ';
if (!empty($this->assignment->get_instance()->blindmarking)) {
$from .= 'LEFT JOIN {assign_user_mapping} um
ON u.id = um.userid
@ -303,6 +369,18 @@ class assign_grading_table extends table_sql implements renderable {
$columns[] = 'status';
$headers[] = get_string('status', 'assign');
// Allowsubmissionsfromdate.
$columns[] = 'allowsubmissionsfromdate';
$headers[] = get_string('allowsubmissionsfromdate', 'assign');
// Duedate.
$columns[] = 'duedate';
$headers[] = get_string('duedate', 'assign');
// Cutoffdate.
$columns[] = 'cutoffdate';
$headers[] = get_string('cutoffdate', 'assign');
// Team submission columns.
if ($assignment->get_instance()->teamsubmission) {
$columns[] = 'team';
@ -1012,6 +1090,60 @@ class assign_grading_table extends table_sql implements renderable {
return $o;
}
/**
* Format a column of data for display.
*
* @param stdClass $row
* @return string
*/
public function col_allowsubmissionsfromdate(stdClass $row) {
$o = '';
if ($row->allowsubmissionsfromdate) {
$userdate = userdate($row->allowsubmissionsfromdate);
$o = $this->output->container($userdate, 'allowsubmissionsfromdate');
}
return $o;
}
/**
* Format a column of data for display.
*
* @param stdClass $row
* @return string
*/
public function col_duedate(stdClass $row) {
$o = '';
if ($row->duedate) {
$userdate = userdate($row->duedate);
$o = $this->output->container($userdate, 'duedate');
}
return $o;
}
/**
* Format a column of data for display.
*
* @param stdClass $row
* @return string
*/
public function col_cutoffdate(stdClass $row) {
$o = '';
if ($row->cutoffdate) {
$userdate = userdate($row->cutoffdate);
$o = $this->output->container($userdate, 'cutoffdate');
}
return $o;
}
/**
* Format a column of data for display.
*

View File

@ -29,6 +29,8 @@ $string['addnewattempt'] = 'Add a new attempt';
$string['addnewattempt_help'] = 'This will create a new blank submission for you to work on.';
$string['addnewattemptfromprevious'] = 'Add a new attempt based on previous submission';
$string['addnewattemptfromprevious_help'] = 'This will copy the contents of your previous submission to a new submission for you to work on.';
$string['addnewgroupoverride'] = 'Add group override';
$string['addnewuseroverride'] = 'Add user override';
$string['allocatedmarker'] = 'Allocated Marker';
$string['allocatedmarker_help'] = 'Marker allocated to this submission';
$string['allowsubmissions'] = 'Allow the user to continue making submissions to this assignment.';
@ -47,6 +49,7 @@ $string['assign:grade'] = 'Grade assignment';
$string['assign:grantextension'] = 'Grant extension';
$string['assign:manageallocations'] = 'Manage markers allocated to submissions';
$string['assign:managegrades'] = 'Review and release grades';
$string['assign:manageoverrides'] = 'Manage assign overrides';
$string['assign:receivegradernotifications'] = 'Receive grader submission notifications';
$string['assign:releasegrades'] = 'Release grades';
$string['assign:revealidentities'] = 'Reveal student identities';
@ -135,6 +138,7 @@ $string['defaultsettings_help'] = 'These settings define the defaults for all ne
$string['defaultteam'] = 'Default group';
$string['deleteallsubmissions'] = 'Delete all submissions';
$string['description'] = 'Description';
$string['disabled'] = 'Disabled';
$string['downloadall'] = 'Download all submissions';
$string['download all submissions'] = 'Download all submissions in a zip file.';
$string['downloadasfolders'] = 'Download as separate folders';
@ -151,11 +155,13 @@ $string['duedatereached'] = 'The due date for this assignment has now passed';
$string['duedatevalidation'] = 'Due date must be after the allow submissions from date.';
$string['editattemptfeedback'] = 'Edit the grade and feedback for attempt number {$a}.';
$string['editingpreviousfeedbackwarning'] = 'You are editing the feedback for a previous attempt. This is attempt {$a->attemptnumber} out of {$a->totalattempts}.';
$string['editoverride'] = 'Edit override';
$string['editsubmission'] = 'Edit submission';
$string['editsubmissionother'] = 'Edit submission for {$a}';
$string['editsubmission_help'] = 'Make changes to your submission';
$string['editingstatus'] = 'Editing status';
$string['editaction'] = 'Actions...';
$string['enabled'] = 'Enabled';
$string['eventallsubmissionsdownloaded'] = 'All the submissions are being downloaded.';
$string['eventassessablesubmitted'] = 'A submission has been submitted.';
$string['eventbatchsetmarkerallocationviewed'] = 'Batch set marker allocation viewed';
@ -167,6 +173,9 @@ $string['eventgradingformviewed'] = 'Grading form viewed';
$string['eventgradingtableviewed'] = 'Grading table viewed';
$string['eventidentitiesrevealed'] = 'The identities have been revealed.';
$string['eventmarkerupdated'] = 'The allocated marker has been updated.';
$string['eventoverridecreated'] = 'Assign override created';
$string['eventoverridedeleted'] = 'Assign override deleted';
$string['eventoverrideupdated'] = 'Assign override updated';
$string['eventrevealidentitiesconfirmationpageviewed'] = 'Reveal identities confirmation page viewed.';
$string['eventstatementaccepted'] = 'The user has accepted the statement of the submission.';
$string['eventsubmissionconfirmationformviewed'] = 'Submission confirmation form viewed.';
@ -200,7 +209,6 @@ $string['gradeuser'] = 'Grade {$a}';
$string['grantextension'] = 'Grant extension';
$string['grantextensionforusers'] = 'Grant extension for {$a} students';
$string['groupsubmissionsettings'] = 'Group submission settings';
$string['enabled'] = 'Enabled';
$string['errornosubmissions'] = 'There are no submissions to download';
$string['errorquickgradingvsadvancedgrading'] = 'The grades were not saved because this assignment is currently using advanced grading';
$string['errorrecordmodified'] = 'The grades were not saved because someone has modified one or more records more recently than when you loaded the page.';
@ -245,6 +253,9 @@ $string['gradingoptions'] = 'Options';
$string['gradingstatus'] = 'Grading status';
$string['gradingstudent'] = 'Grading student';
$string['gradingsummary'] = 'Grading summary';
$string['groupoverrides'] = 'Group overrides';
$string['groupoverridesdeleted'] = 'Group overrides deleted';
$string['groupsnone'] = 'There are no groups in this course';
$string['hideshow'] = 'Hide/Show';
$string['hiddenuser'] = 'Participant ';
$string['instructionfiles'] = 'Instruction files';
@ -252,6 +263,7 @@ $string['introattachments'] = 'Additional files';
$string['introattachments_help'] = 'Additional files for use in the assignment, such as answer templates, may be added. Download links for the files will then be displayed on the assignment page under the description.';
$string['invalidgradeforscale'] = 'The grade supplied was not valid for the current scale';
$string['invalidfloatforgrade'] = 'The grade provided could not be understood: {$a}';
$string['invalidoverrideid'] = 'Invalid override id';
$string['lastmodifiedsubmission'] = 'Last modified (submission)';
$string['lastmodifiedgrade'] = 'Last modified (grade)';
$string['latesubmissions'] = 'Late submissions';
@ -304,12 +316,16 @@ $string['multipleteamsgrader'] = 'Member of more than one group, so unable to ma
$string['mysubmission'] = 'My submission: ';
$string['newsubmissions'] = 'Assignments submitted';
$string['noattempt'] = 'No attempt';
$string['noclose'] = 'No close date';
$string['nofilters'] = 'No filters';
$string['nofiles'] = 'No files. ';
$string['nograde'] = 'No grade. ';
$string['nolatesubmissions'] = 'No late submissions accepted. ';
$string['nomoresubmissionsaccepted'] = 'Only allowed for participants who have been granted an extension';
$string['none'] = 'None';
$string['noonlinesubmissions'] = 'This assignment does not require you to submit anything online';
$string['noopen'] = 'No open date';
$string['nooverridedata'] = 'You must override at least one of the assign settings.';
$string['nosavebutnext'] = 'Next';
$string['nosubmission'] = 'Nothing has been submitted for this assignment';
$string['nosubmissionsacceptedafter'] = 'No submissions accepted after ';
@ -330,6 +346,14 @@ $string['offline'] = 'No online submissions required';
$string['open'] = 'Open';
$string['outof'] = '{$a->current} out of {$a->total}';
$string['overdue'] = '<font color="red">Assignment is overdue by: {$a}</font>';
$string['override'] = 'Override';
$string['overridedeletegroupsure'] = 'Are you sure you want to delete the override for group {$a}?';
$string['overridedeleteusersure'] = 'Are you sure you want to delete the override for user {$a}?';
$string['overridegroup'] = 'Override group';
$string['overridegroupeventname'] = '{$a->assign} - {$a->group}';
$string['overrides'] = 'Overrides';
$string['overrideuser'] = 'Override user';
$string['overrideusereventname'] = '{$a->assign} - Override';
$string['outlinegrade'] = 'Grade: {$a}';
$string['page-mod-assign-x'] = 'Any assignment module page';
$string['page-mod-assign-view'] = 'Assignment module main and submission page';
@ -346,6 +370,8 @@ $string['quickgrading'] = 'Quick grading';
$string['quickgradingresult'] = 'Quick grading';
$string['quickgradingchangessaved'] = 'The grade changes were saved';
$string['quickgrading_help'] = 'Quick grading allows you to assign grades (and outcomes) directly in the submissions table. Quick grading is not compatible with advanced grading and is not recommended when there are multiple markers.';
$string['removeallgroupoverrides'] = 'Delete all group overrides';
$string['removealluseroverrides'] = 'Delete all user overrides';
$string['reopenuntilpassincompatiblewithblindmarking'] = 'Reopen until pass option is incompatible with blind marking, because the grades are not released to the gradebook until the student identities are revealed.';
$string['requiresubmissionstatement'] = 'Require that students accept the submission statement';
$string['requiresubmissionstatement_help'] = 'Require that students accept the submission statement for all submissions to this assignment.';
@ -354,16 +380,19 @@ $string['requireallteammemberssubmit_help'] = 'If enabled, all members of the st
$string['recordid'] = 'Identifier';
$string['revealidentities'] = 'Reveal student identities';
$string['revealidentitiesconfirm'] = 'Are you sure you want to reveal student identities for this assignment? This operation cannot be undone. Once the student identities have been revealed, the marks will be released to the gradebook.';
$string['reverttodefaults'] = 'Revert to assign defaults';
$string['reverttodraftforstudent'] = 'Revert submission to draft for student: (id={$a->id}, fullname={$a->fullname}).';
$string['reverttodraft'] = 'Revert the submission to draft status.';
$string['reverttodraftshort'] = 'Revert the submission to draft';
$string['reviewed'] = 'Reviewed';
$string['save'] = 'Save';
$string['saveallquickgradingchanges'] = 'Save all quick grading changes';
$string['saveandcontinue'] = 'Save and continue';
$string['savechanges'] = 'Save changes';
$string['savegradingresult'] = 'Grade';
$string['savenext'] = 'Save and show next';
$string['savingchanges'] = 'Saving changes...';
$string['saveoverrideandstay'] = 'Save and enter another override';
$string['scale'] = 'Scale';
$string['search:activity'] = 'Assignment - activity information';
$string['sendstudentnotificationsdefault'] = 'Default setting for "Notify students"';
@ -482,6 +511,9 @@ $string['updatetable'] = 'Save and update table';
$string['upgradenotimplemented'] = 'Upgrade not implemented in plugin ({$a->type} {$a->subtype})';
$string['userextensiondate'] = 'Extension granted until: {$a}';
$string['useridlistnotcached'] = 'The grade changes were NOT saved, as it was not possible to determine which submission they were for.';
$string['useroverrides'] = 'User overrides';
$string['useroverridesdeleted'] = 'User overrides deleted';
$string['usersnone'] = 'No students have access to this assign';
$string['userswhoneedtosubmit'] = 'Users who need to submit: {$a}';
$string['usergrade'] = 'User grade';
$string['validmarkingworkflowstates'] = 'Valid marking workflow states';

View File

@ -166,6 +166,10 @@ function assign_reset_course_form_definition(&$mform) {
$mform->addElement('header', 'assignheader', get_string('modulenameplural', 'assign'));
$name = get_string('deleteallsubmissions', 'assign');
$mform->addElement('advcheckbox', 'reset_assign_submissions', $name);
$mform->addElement('advcheckbox', 'reset_assign_user_overrides',
get_string('removealluseroverrides', 'assign'));
$mform->addElement('advcheckbox', 'reset_assign_group_overrides',
get_string('removeallgroupoverrides', 'assign'));
}
/**
@ -174,7 +178,9 @@ function assign_reset_course_form_definition(&$mform) {
* @return array
*/
function assign_reset_course_form_defaults($course) {
return array('reset_assign_submissions'=>1);
return array('reset_assign_submissions' => 1,
'reset_assign_group_overrides' => 1,
'reset_assign_user_overrides' => 1);
}
/**
@ -193,6 +199,138 @@ function assign_update_instance(stdClass $data, $form) {
return $assignment->update_instance($data);
}
/**
* This function updates the events associated to the assign.
* If $override is non-zero, then it updates only the events
* associated with the specified override.
*
* @uses ASSIGN_MAX_EVENT_LENGTH
* @param object $assign the assign object.
* @param object $override (optional) limit to a specific override
*/
function assign_update_events($assign, $override = null) {
global $CFG, $DB;
require_once($CFG->dirroot . '/calendar/lib.php');
// Load the old events relating to this assign.
$conds = array('modulename' => 'assign',
'instance' => $assign->get_context()->id);
if (!empty($override)) {
// Only load events for this override.
if (isset($override->userid)) {
$conds['userid'] = $override->userid;
} else {
$conds['groupid'] = $override->groupid;
}
}
$oldevents = $DB->get_records('event', $conds);
// Now make a todo list of all that needs to be updated.
if (empty($override)) {
// We are updating the primary settings for the assign, so we
// need to add all the overrides.
$overrides = $DB->get_records('assign_overrides', array('assignid' => $assign->id));
// As well as the original assign (empty override).
$overrides[] = new stdClass();
} else {
// Just do the one override.
$overrides = array($override);
}
foreach ($overrides as $current) {
$groupid = isset($current->groupid) ? $current->groupid : 0;
$userid = isset($current->userid) ? $current->userid : 0;
$allowsubmissionsfromdate = isset($current->allowsubmissionsfromdate
) ? $current->allowsubmissionsfromdate : $assign->get_context()->allowsubmissionsfromdate;
$duedate = isset($current->duedate) ? $current->duedate : $assign->get_context()->duedate;
// Only add open/close events for an override if they differ from the assign default.
$addopen = empty($current->id) || !empty($current->allowsubmissionsfromdate);
$addclose = empty($current->id) || !empty($current->duedate);
if (!empty($assign->coursemodule)) {
$cmid = $assign->coursemodule;
} else {
$cmid = get_coursemodule_from_instance('assign', $assign->get_context()->id, $assign->get_context()->course)->id;
}
$event = new stdClass();
$event->description = format_module_intro('assign', $assign->get_context(), $cmid);
// Events module won't show user events when the courseid is nonzero.
$event->courseid = ($userid) ? 0 : $assign->get_context()->course;
$event->groupid = $groupid;
$event->userid = $userid;
$event->modulename = 'assign';
$event->instance = $assign->get_context()->id;
$event->timestart = $allowsubmissionsfromdate;
$event->timeduration = max($duedate - $allowsubmissionsfromdate, 0);
$event->visible = instance_is_visible('assign', $assign);
$event->eventtype = 'open';
// Determine the event name.
if ($groupid) {
$params = new stdClass();
$params->assign = $assign->get_context()->name;
$params->group = groups_get_group_name($groupid);
if ($params->group === false) {
// Group doesn't exist, just skip it.
continue;
}
$eventname = get_string('overridegroupeventname', 'assign', $params);
} else if ($userid) {
$params = new stdClass();
$params->assign = $assign->get_context()->name;
$eventname = get_string('overrideusereventname', 'assign', $params);
} else {
$eventname = $assign->name;
}
if ($addopen or $addclose) {
if ($duedate and $allowsubmissionsfromdate and $event->timeduration <= ASSIGN_MAX_EVENT_LENGTH) {
// Single event for the whole assign.
if ($oldevent = array_shift($oldevents)) {
$event->id = $oldevent->id;
} else {
unset($event->id);
}
$event->name = $eventname;
// The method calendar_event::create will reuse a db record if the id field is set.
calendar_event::create($event);
} else {
// Separate start and end events.
$event->timeduration = 0;
if ($allowsubmissionsfromdate && $addopen) {
if ($oldevent = array_shift($oldevents)) {
$event->id = $oldevent->id;
} else {
unset($event->id);
}
$event->name = $eventname.' ('.get_string('open', 'assign').')';
// The method calendar_event::create will reuse a db record if the id field is set.
calendar_event::create($event);
}
if ($duedate && $addclose) {
if ($oldevent = array_shift($oldevents)) {
$event->id = $oldevent->id;
} else {
unset($event->id);
}
$event->name = $eventname.' ('.get_string('duedate', 'assign').')';
$event->timestart = $duedate;
$event->eventtype = 'close';
calendar_event::create($event);
}
}
}
}
// Delete any leftover events.
foreach ($oldevents as $badevent) {
$badevent = calendar_event::load($badevent);
$badevent->delete();
}
}
/**
* Return the list if Moodle features this module supports
*
@ -249,6 +387,17 @@ function assign_grading_areas_list() {
function assign_extend_settings_navigation(settings_navigation $settings, navigation_node $navref) {
global $PAGE, $DB;
// We want to add these new nodes after the Edit settings node, and before the
// Locally assigned roles node. Of course, both of those are controlled by capabilities.
$keys = $navref->get_children_key_list();
$beforekey = null;
$i = array_search('modedit', $keys);
if ($i === false and array_key_exists(0, $keys)) {
$beforekey = $keys[0];
} else if (array_key_exists($i + 1, $keys)) {
$beforekey = $keys[$i + 1];
}
$cm = $PAGE->cm;
if (!$cm) {
return;
@ -261,6 +410,19 @@ function assign_extend_settings_navigation(settings_navigation $settings, naviga
return;
}
if (has_capability('mod/assign:manageoverrides', $PAGE->cm->context)) {
$url = new moodle_url('/mod/assign/overrides.php', array('cmid' => $PAGE->cm->id));
$node = navigation_node::create(get_string('groupoverrides', 'assign'),
new moodle_url($url, array('mode' => 'group')),
navigation_node::TYPE_SETTING, null, 'mod_assign_groupoverrides');
$navref->add_node($node, $beforekey);
$node = navigation_node::create(get_string('useroverrides', 'assign'),
new moodle_url($url, array('mode' => 'user')),
navigation_node::TYPE_SETTING, null, 'mod_assign_useroverrides');
$navref->add_node($node, $beforekey);
}
// Link to gradebook.
if (has_capability('gradereport/grader:view', $cm->context) &&
has_capability('moodle/grade:viewall', $cm->context)) {

View File

@ -61,6 +61,9 @@ define('ASSIGN_MARKING_WORKFLOW_STATE_INREVIEW', 'inreview');
define('ASSIGN_MARKING_WORKFLOW_STATE_READYFORRELEASE', 'readyforrelease');
define('ASSIGN_MARKING_WORKFLOW_STATE_RELEASED', 'released');
/** ASSIGN_MAX_EVENT_LENGTH = 432000 ; 5 days maximum */
define("ASSIGN_MAX_EVENT_LENGTH", "432000");
// Name of file area for intro attachments.
define('ASSIGN_INTROATTACHMENT_FILEAREA', 'introattachment');
@ -740,6 +743,8 @@ class assign {
$result = false;
}
$this->delete_all_overrides();
// Delete_records will throw an exception if it fails - so no need for error checking here.
$DB->delete_records('assign_submission', array('assignment' => $this->get_instance()->id));
$DB->delete_records('assign_grades', array('assignment' => $this->get_instance()->id));
@ -758,6 +763,170 @@ class assign {
return $result;
}
/**
* Deletes a assign override from the database and clears any corresponding calendar events
*
* @param int $overrideid The id of the override being deleted
* @return bool true on success
*/
public function delete_override($overrideid) {
global $CFG, $DB;
require_once($CFG->dirroot . '/calendar/lib.php');
$cm = get_coursemodule_from_instance('assign', $this->get_context()->id, $this->get_context()->course);
$override = $DB->get_record('assign_overrides', array('id' => $overrideid), '*', MUST_EXIST);
// Delete the events.
$conds = array('modulename' => 'assign',
'instance' => $this->get_context()->id);
if (isset($override->userid)) {
$conds['userid'] = $override->userid;
} else {
$conds['groupid'] = $override->groupid;
}
$events = $DB->get_records('event', $conds);
foreach ($events as $event) {
$eventold = calendar_event::load($event);
$eventold->delete();
}
$DB->delete_records('assign_overrides', array('id' => $overrideid));
// Set the common parameters for one of the events we will be triggering.
$params = array(
'objectid' => $override->id,
'context' => context_module::instance($cm->id),
'other' => array(
'assignid' => $override->assignid
)
);
// Determine which override deleted event to fire.
if (!empty($override->userid)) {
$params['relateduserid'] = $override->userid;
$event = \mod_assign\event\user_override_deleted::create($params);
} else {
$params['other']['groupid'] = $override->groupid;
$event = \mod_assign\event\group_override_deleted::create($params);
}
// Trigger the override deleted event.
$event->add_record_snapshot('assign_overrides', $override);
$event->trigger();
return true;
}
/**
* Deletes all assign overrides from the database and clears any corresponding calendar events
*/
public function delete_all_overrides() {
global $DB;
$overrides = $DB->get_records('assign_overrides', array('assignid' => $this->get_context()->id), 'id');
foreach ($overrides as $override) {
$this->delete_override($override->id);
}
}
/**
* Updates the assign properties with override information for a user.
*
* Algorithm: For each assign setting, if there is a matching user-specific override,
* then use that otherwise, if there are group-specific overrides, return the most
* lenient combination of them. If neither applies, leave the assign setting unchanged.
*
* @param int $userid The userid.
*/
public function update_effective_access($userid) {
$override = $this->override_exists($userid);
// Merge with assign defaults.
$keys = array('duedate', 'cutoffdate', 'allowsubmissionsfromdate');
foreach ($keys as $key) {
if (isset($override->{$key})) {
$this->get_instance()->{$key} = $override->{$key};
}
}
}
/**
* Returns user override
*
* Algorithm: For each assign setting, if there is a matching user-specific override,
* then use that otherwise, if there are group-specific overrides, return the most
* lenient combination of them. If neither applies, leave the assign setting unchanged.
*
* @param int $userid The userid.
* @return override if exist
*/
public function override_exists($userid) {
global $DB;
// Check for user override.
$override = $DB->get_record('assign_overrides', array('assignid' => $this->get_instance()->id, 'userid' => $userid));
if (!$override) {
$override = new stdClass();
$override->duedate = null;
$override->cutoffdate = null;
$override->allowsubmissionsfromdate = null;
}
// Check for group overrides.
$groupings = groups_get_user_groups($this->get_instance()->course, $userid);
if (!empty($groupings[0])) {
// Select all overrides that apply to the User's groups.
list($extra, $params) = $DB->get_in_or_equal(array_values($groupings[0]));
$sql = "SELECT * FROM {assign_overrides}
WHERE groupid $extra AND assignid = ?";
$params[] = $this->get_instance()->id;
$records = $DB->get_records_sql($sql, $params);
// Combine the overrides.
$duedates = array();
$cutoffdates = array();
$allowsubmissionsfromdates = array();
foreach ($records as $gpoverride) {
if (isset($gpoverride->duedate)) {
$duedates[] = $gpoverride->duedate;
}
if (isset($gpoverride->cutoffdate)) {
$cutoffdates[] = $gpoverride->cutoffdate;
}
if (isset($gpoverride->allowsubmissionsfromdate)) {
$allowsubmissionsfromdates[] = $gpoverride->allowsubmissionsfromdate;
}
}
// If there is a user override for a setting, ignore the group override.
if (is_null($override->allowsubmissionsfromdate) && count($allowsubmissionsfromdates)) {
$override->allowsubmissionsfromdate = min($allowsubmissionsfromdates);
}
if (is_null($override->cutoffdate) && count($cutoffdates)) {
if (in_array(0, $cutoffdates)) {
$override->cutoffdate = 0;
} else {
$override->cutoffdate = max($cutoffdates);
}
}
if (is_null($override->duedate) && count($duedates)) {
if (in_array(0, $duedates)) {
$override->duedate = 0;
} else {
$override->duedate = max($duedates);
}
}
}
return $override;
}
/**
* Actual implementation of the reset course functionality, delete all the
* assignment submissions for course $data->courseid.
@ -826,8 +995,41 @@ class assign {
}
}
}
// Remove user overrides.
if (!empty($data->reset_assign_user_overrides)) {
$DB->delete_records_select('assign_overrides',
'assignid IN (SELECT id FROM {assign} WHERE course = ?) AND userid IS NOT NULL', array($data->courseid));
$status[] = array(
'component' => $componentstr,
'item' => get_string('useroverridesdeleted', 'assign'),
'error' => false);
}
// Remove group overrides.
if (!empty($data->reset_assign_group_overrides)) {
$DB->delete_records_select('assign_overrides',
'assignid IN (SELECT id FROM {assign} WHERE course = ?) AND groupid IS NOT NULL', array($data->courseid));
$status[] = array(
'component' => $componentstr,
'item' => get_string('groupoverridesdeleted', 'assign'),
'error' => false);
}
// Updating dates - shift may be negative too.
if ($data->timeshift) {
$DB->execute("UPDATE {assign_overrides}
SET allowsubmissionsfromdate = allowsubmissionsfromdate + ?
WHERE assignid = ? AND allowsubmissionsfromdate <> 0",
array($data->timeshift, $this->get_instance()->id));
$DB->execute("UPDATE {assign_overrides}
SET duedate = duedate + ?
WHERE assignid = ? AND duedate <> 0",
array($data->timeshift, $this->get_instance()->id));
$DB->execute("UPDATE {assign_overrides}
SET cutoffdate = cutoffdate + ?
WHERE assignid =? AND cutoffdate <> 0",
array($data->timeshift, $this->get_instance()->id));
shift_course_mod_dates('assign',
array('duedate', 'allowsubmissionsfromdate', 'cutoffdate'),
$data->timeshift,
@ -2246,6 +2448,27 @@ class assign {
}
$userlist = explode(',', $users);
$keys = array('duedate', 'cutoffdate', 'allowsubmissionsfromdate');
$maxoverride = array('allowsubmissionsfromdate' => 0, 'duedate' => 0, 'cutoffdate' => 0);
foreach ($userlist as $userid) {
// To validate extension date with users overrides.
$override = $this->override_exists($userid);
foreach ($keys as $key) {
if ($override->{$key}) {
if ($maxoverride[$key] < $override->{$key}) {
$maxoverride[$key] = $override->{$key};
}
} else if ($maxoverride[$key] < $this->get_instance()->{$key}) {
$maxoverride[$key] = $this->get_instance()->{$key};
}
}
}
foreach ($keys as $key) {
if ($maxoverride[$key]) {
$this->get_instance()->{$key} = $maxoverride[$key];
}
}
$formparams['userlist'] = $userlist;
$data->selectedusers = $users;
@ -2456,6 +2679,10 @@ class assign {
$assignment = new assign($context, $cm, $course);
// Apply overrides.
$assignment->update_effective_access($USER->id);
$timedue = $assignment->get_instance()->duedate;
if (has_capability('mod/assign:grade', $context)) {
$submitted = $assignment->count_submissions_with_status(ASSIGN_SUBMISSION_STATUS_SUBMITTED);
@ -3257,6 +3484,9 @@ class assign {
$userid = $args['userid'];
$attemptnumber = $args['attemptnumber'];
// Apply overrides.
$this->update_effective_access($userid);
$rownum = 0;
$useridlist = array($userid);
@ -3454,6 +3684,7 @@ class assign {
$user = $DB->get_record('user', array('id' => $userid));
if ($user) {
$this->update_effective_access($userid);
$viewfullnames = has_capability('moodle/site:viewfullnames', $this->get_course_context());
$usersummary = new assign_user_summary($user,
$this->get_course()->id,
@ -3865,6 +4096,8 @@ class assign {
$currentgroup = groups_get_activity_group($this->get_course_module(), true);
$framegrader = new grading_app($userid, $currentgroup, $this);
$this->update_effective_access($userid);
$o .= $this->get_renderer()->render($framegrader);
$o .= $this->view_footer();
@ -5825,6 +6058,27 @@ class assign {
}
$userlist = explode(',', $users);
$keys = array('duedate', 'cutoffdate', 'allowsubmissionsfromdate');
$maxoverride = array('allowsubmissionsfromdate' => 0, 'duedate' => 0, 'cutoffdate' => 0);
foreach ($userlist as $userid) {
// To validate extension date with users overrides.
$override = $this->override_exists($userid);
foreach ($keys as $key) {
if ($override->{$key}) {
if ($maxoverride[$key] < $override->{$key}) {
$maxoverride[$key] = $override->{$key};
}
} else if ($maxoverride[$key] < $this->get_instance()->{$key}) {
$maxoverride[$key] = $this->get_instance()->{$key};
}
}
}
foreach ($keys as $key) {
if ($maxoverride[$key]) {
$this->get_instance()->{$key} = $maxoverride[$key];
}
}
$formparams = array(
'instance' => $this->get_instance(),
'assign' => $this,
@ -5856,7 +6110,6 @@ class assign {
return false;
}
/**
* Save quick grades.
*
@ -8406,3 +8659,102 @@ class assign_portfolio_caller extends portfolio_module_caller_base {
return array(PORTFOLIO_FORMAT_FILE, PORTFOLIO_FORMAT_LEAP2A);
}
}
/**
* Logic to happen when a/some group(s) has/have been deleted in a course.
*
* @param int $courseid The course ID.
* @param int $groupid The group id if it is known
* @return void
*/
function assign_process_group_deleted_in_course($courseid, $groupid = null) {
global $DB;
$params = array('courseid' => $courseid);
if ($groupid) {
$params['groupid'] = $groupid;
// We just update the group that was deleted.
$sql = "SELECT o.id, o.assignid
FROM {assign_overrides} o
JOIN {assign} assign ON assign.id = o.assignid
WHERE assign.course = :courseid
AND o.groupid = :groupid";
} else {
// No groupid, we update all orphaned group overrides for all assign in course.
$sql = "SELECT o.id, o.assignid
FROM {assign_overrides} o
JOIN {assign} assign ON assign.id = o.assignid
LEFT JOIN {groups} grp ON grp.id = o.groupid
WHERE assign.course = :courseid
AND o.groupid IS NOT NULL
AND grp.id IS NULL";
}
$records = $DB->get_records_sql_menu($sql, $params);
if (!$records) {
return; // Nothing to do.
}
$DB->delete_records_list('assign_overrides', 'id', array_keys($records));
}
/**
* Change the sort order of an override
*
* @param int $id of the override
* @param string $move direction of move
* @param int $assignid of the assignment
* @return bool success of operation
*/
function move_group_override($id, $move, $assignid) {
global $DB;
// Get the override object.
if (!$override = $DB->get_record('assign_overrides', array('id' => $id), 'id, sortorder')) {
return false;
}
// Count the number of group overrides.
$overridecountgroup = $DB->count_records('assign_overrides', array('userid' => null, 'assignid' => $assignid));
// Calculate the new sortorder.
if ( ($move == 'up') and ($override->sortorder > 1)) {
$neworder = $override->sortorder - 1;
} else if (($move == 'down') and ($override->sortorder < $overridecountgroup)) {
$neworder = $override->sortorder + 1;
} else {
return false;
}
// Retrieve the override object that is currently residing in the new position.
$params = array('sortorder' => $neworder, 'assignid' => $assignid);
if ($swapoverride = $DB->get_record('assign_overrides', $params, 'id, sortorder')) {
// Swap the sortorders.
$swapoverride->sortorder = $override->sortorder;
$override->sortorder = $neworder;
// Update the override records.
$DB->update_record('assign_overrides', $override);
$DB->update_record('assign_overrides', $swapoverride);
}
reorder_group_overrides($assignid);
return true;
}
/**
* Reorder the overrides starting at the override at the given startorder.
*
* @param int $assignid of the assigment
*/
function reorder_group_overrides($assignid) {
global $DB;
$i = 1;
if ($overrides = $DB->get_records('assign_overrides', array('userid' => null, 'assignid' => $assignid), 'sortorder ASC')) {
foreach ($overrides as $override) {
$f = new stdClass();
$f->id = $override->id;
$f->sortorder = $i++;
$DB->update_record('assign_overrides', $f);
}
}
}

View File

@ -0,0 +1,293 @@
<?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/>.
/**
* Settings form for overrides in the assign module.
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/formslib.php');
require_once($CFG->dirroot . '/mod/assign/mod_form.php');
/**
* Form for editing settings overrides.
*
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class assign_override_form extends moodleform {
/** @var object course module object. */
protected $cm;
/** @var object the assign settings object. */
protected $assign;
/** @var context the assign context. */
protected $context;
/** @var bool editing group override (true) or user override (false). */
protected $groupmode;
/** @var int groupid, if provided. */
protected $groupid;
/** @var int userid, if provided. */
protected $userid;
/**
* Constructor.
* @param moodle_url $submiturl the form action URL.
* @param object $cm course module object.
* @param object $assign the assign settings object.
* @param object $context the assign context.
* @param bool $groupmode editing group override (true) or user override (false).
* @param object $override the override being edited, if it already exists.
*/
public function __construct($submiturl, $cm, $assign, $context, $groupmode, $override) {
$this->cm = $cm;
$this->assign = $assign;
$this->context = $context;
$this->groupmode = $groupmode;
$this->groupid = empty($override->groupid) ? 0 : $override->groupid;
$this->userid = empty($override->userid) ? 0 : $override->userid;
parent::__construct($submiturl, null, 'post');
}
/**
* Define this form - called by the parent constructor
*/
protected function definition() {
global $CFG, $DB;
$cm = $this->cm;
$mform = $this->_form;
$mform->addElement('header', 'override', get_string('override', 'assign'));
if ($this->groupmode) {
// Group override.
if ($this->groupid) {
// There is already a groupid, so freeze the selector.
$groupchoices = array();
$groupchoices[$this->groupid] = groups_get_group_name($this->groupid);
$mform->addElement('select', 'groupid',
get_string('overridegroup', 'assign'), $groupchoices);
$mform->freeze('groupid');
} else {
// Prepare the list of groups.
$groups = groups_get_all_groups($cm->course);
if (empty($groups)) {
// Generate an error.
$link = new moodle_url('/mod/assign/overrides.php', array('cmid' => $cm->id));
print_error('groupsnone', 'assign', $link);
}
$groupchoices = array();
foreach ($groups as $group) {
$groupchoices[$group->id] = $group->name;
}
unset($groups);
if (count($groupchoices) == 0) {
$groupchoices[0] = get_string('none');
}
$mform->addElement('select', 'groupid',
get_string('overridegroup', 'assign'), $groupchoices);
$mform->addRule('groupid', get_string('required'), 'required', null, 'client');
}
} else {
// User override.
if ($this->userid) {
// There is already a userid, so freeze the selector.
$user = $DB->get_record('user', array('id' => $this->userid));
$userchoices = array();
$userchoices[$this->userid] = fullname($user);
$mform->addElement('select', 'userid',
get_string('overrideuser', 'assign'), $userchoices);
$mform->freeze('userid');
} else {
// Prepare the list of users.
$users = get_enrolled_users($this->context, '', 0,
'u.id, u.email, ' . get_all_user_name_fields(true, 'u'));
// Filter users based on any fixed restrictions (groups, profile).
$info = new \core_availability\info_module($cm);
$users = $info->filter_user_list($users);
if (empty($users)) {
// Generate an error.
$link = new moodle_url('/mod/assign/overrides.php', array('cmid' => $cm->id));
print_error('usersnone', 'assign', $link);
}
$userchoices = array();
$canviewemail = in_array('email', get_extra_user_fields($this->context));
foreach ($users as $id => $user) {
if (empty($invalidusers[$id]) || (!empty($override) &&
$id == $override->userid)) {
if ($canviewemail) {
$userchoices[$id] = fullname($user) . ', ' . $user->email;
} else {
$userchoices[$id] = fullname($user);
}
}
}
unset($users);
if (count($userchoices) == 0) {
$userchoices[0] = get_string('none');
}
$mform->addElement('searchableselector', 'userid',
get_string('overrideuser', 'assign'), $userchoices);
$mform->addRule('userid', get_string('required'), 'required', null, 'client');
}
}
$users = $DB->get_fieldset_select('groups_members', 'userid', 'groupid = ?', array($this->groupid));
array_push($users, $this->userid);
$extensionmax = 0;
foreach ($users as $value) {
$extension = $DB->get_record('assign_user_flags', array('assignment' => $this->assign->get_context()->id,
'userid' => $value));
if ($extension) {
if ($extensionmax < $extension->extensionduedate) {
$extensionmax = $extension->extensionduedate;
}
}
}
if ($extensionmax) {
$this->assign->get_context()->extensionduedate = $extensionmax;
}
// Open and close dates.
$mform->addElement('date_time_selector', 'allowsubmissionsfromdate',
get_string('allowsubmissionsfromdate', 'assign'), array('optional' => true));
$mform->setDefault('allowsubmissionsfromdate', $this->assign->get_context()->allowsubmissionsfromdate);
$mform->addElement('date_time_selector', 'duedate', get_string('duedate', 'assign'), array('optional' => true));
$mform->setDefault('duedate', $this->assign->get_context()->duedate);
$mform->addElement('date_time_selector', 'cutoffdate', get_string('cutoffdate', 'assign'), array('optional' => true));
$mform->setDefault('cutoffdate', $this->assign->get_context()->cutoffdate);
if (isset($this->assign->get_context()->extensionduedate)) {
$mform->addElement('static', 'extensionduedate', get_string('extensionduedate', 'assign'),
userdate($this->assign->get_context()->extensionduedate));
}
// Submit buttons.
$mform->addElement('submit', 'resetbutton',
get_string('reverttodefaults', 'assign'));
$buttonarray = array();
$buttonarray[] = $mform->createElement('submit', 'submitbutton',
get_string('save', 'assign'));
$buttonarray[] = $mform->createElement('submit', 'againbutton',
get_string('saveoverrideandstay', 'assign'));
$buttonarray[] = $mform->createElement('cancel');
$mform->addGroup($buttonarray, 'buttonbar', '', array(' '), false);
$mform->closeHeaderBefore('buttonbar');
}
/**
* Validate the submitted form data.
*
* @param array $data array of ("fieldname"=>value) of submitted data
* @param array $files array of uploaded files "element_name"=>tmp_file_path
* @return array of "element_name"=>"error_description" if there are errors
*/
public function validation($data, $files) {
global $COURSE, $DB;
$errors = parent::validation($data, $files);
$mform =& $this->_form;
$assign = $this->assign;
if ($mform->elementExists('userid')) {
if (empty($data['userid'])) {
$errors['userid'] = get_string('required');
}
}
if ($mform->elementExists('groupid')) {
if (empty($data['groupid'])) {
$errors['groupid'] = get_string('required');
}
}
// Ensure that the dates make sense.
if (!empty($data['allowsubmissionsfromdate']) && !empty($data['cutoffdate'])) {
if ($data['cutoffdate'] < $data['allowsubmissionsfromdate']) {
$errors['cutoffdate'] = get_string('cutoffdatefromdatevalidation', 'assign');
}
}
if (!empty($data['allowsubmissionsfromdate']) && !empty($data['duedate'])) {
if ($data['duedate'] < $data['allowsubmissionsfromdate']) {
$errors['duedate'] = get_string('duedatevalidation', 'assign');
}
}
if (!empty($data['cutoffdate']) && !empty($data['duedate'])) {
if ($data['cutoffdate'] < $data['duedate'] ) {
$errors['cutoffdate'] = get_string('cutoffdatevalidation', 'assign');
}
}
// Ensure that override duedate/allowsubmissionsfromdate are before extension date if exist.
if (!empty($assign->get_context()->extensionduedate) && !empty($data['duedate'])) {
if ($assign->get_context()->extensionduedate < $data['duedate']) {
$errors['duedate'] = get_string('extensionnotafterduedate', 'assign');
}
}
if (!empty($assign->get_context()->extensionduedate) && !empty($data['allowsubmissionsfromdate'])) {
if ($assign->get_context()->extensionduedate < $data['allowsubmissionsfromdate']) {
$errors['allowsubmissionsfromdate'] = get_string('extensionnotafterfromdate', 'assign');
}
}
// Ensure that at least one assign setting was changed.
$changed = false;
$keys = array('duedate', 'cutoffdate', 'allowsubmissionsfromdate');
foreach ($keys as $key) {
if ($data[$key] != $assign->get_context()->{$key}) {
$changed = true;
break;
}
}
if (!$changed) {
$errors['allowsubmissionsfromdate'] = get_string('nooverridedata', 'assign');
}
return $errors;
}
}

View File

@ -0,0 +1,96 @@
<?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/>.
/**
* This page handles deleting assigment overrides
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(__FILE__) . '/../../config.php');
require_once($CFG->dirroot.'/mod/assign/lib.php');
require_once($CFG->dirroot.'/mod/assign/locallib.php');
require_once($CFG->dirroot.'/mod/assign/override_form.php');
$overrideid = required_param('id', PARAM_INT);
$confirm = optional_param('confirm', false, PARAM_BOOL);
if (! $override = $DB->get_record('assign_overrides', array('id' => $overrideid))) {
print_error('invalidoverrideid', 'assign');
}
$assign = new assign($DB->get_record('assign', array('id' => $override->assignid), '*', MUST_EXIST), null, null);
if (! $cm = get_coursemodule_from_instance("assign", $assign->get_context()->id, $assign->get_context()->course)) {
print_error('invalidcoursemodule');
}
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$context = context_module::instance($cm->id);
require_login($course, false, $cm);
// Check the user has the required capabilities to modify an override.
require_capability('mod/assign:manageoverrides', $context);
$url = new moodle_url('/mod/assign/overridedelete.php', array('id' => $override->id));
$confirmurl = new moodle_url($url, array('id' => $override->id, 'confirm' => 1));
$cancelurl = new moodle_url('/mod/assign/overrides.php', array('cmid' => $cm->id));
if (!empty($override->userid)) {
$cancelurl->param('mode', 'user');
}
// If confirm is set (PARAM_BOOL) then we have confirmation of intention to delete.
if ($confirm) {
require_sesskey();
$assign->delete_override($override->id);
reorder_group_overrides($assign->get_context()->id);
redirect($cancelurl);
}
// Prepare the page to show the confirmation form.
$stroverride = get_string('override', 'assign');
$title = get_string('deletecheck', null, $stroverride);
$PAGE->set_url($url);
$PAGE->set_pagelayout('admin');
$PAGE->navbar->add($title);
$PAGE->set_title($title);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($assign->get_context()->name, true, array('context' => $context)));
if ($override->groupid) {
$group = $DB->get_record('groups', array('id' => $override->groupid), 'id, name');
$confirmstr = get_string("overridedeletegroupsure", "assign", $group->name);
} else {
$namefields = get_all_user_name_fields(true);
$user = $DB->get_record('user', array('id' => $override->userid),
'id, ' . $namefields);
$confirmstr = get_string("overridedeleteusersure", "assign", fullname($user));
}
echo $OUTPUT->confirm($confirmstr, $confirmurl, $cancelurl);
echo $OUTPUT->footer();

240
mod/assign/overrideedit.php Normal file
View File

@ -0,0 +1,240 @@
<?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/>.
/**
* This page handles editing and creation of assign overrides
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(__FILE__) . '/../../config.php');
require_once($CFG->dirroot.'/mod/assign/lib.php');
require_once($CFG->dirroot.'/mod/assign/locallib.php');
require_once($CFG->dirroot.'/mod/assign/override_form.php');
$cmid = optional_param('cmid', 0, PARAM_INT);
$overrideid = optional_param('id', 0, PARAM_INT);
$action = optional_param('action', null, PARAM_ALPHA);
$reset = optional_param('reset', false, PARAM_BOOL);
$override = null;
if ($overrideid) {
if (! $override = $DB->get_record('assign_overrides', array('id' => $overrideid))) {
print_error('invalidoverrideid', 'assign');
}
$assign = new assign($DB->get_record('assign', array('id' => $override->assignid), '*', MUST_EXIST), null, null);
list($course, $cm) = get_course_and_cm_from_instance($assign->get_context(), 'assign');
} else if ($cmid) {
list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'assign');
$assign = new assign($DB->get_record('assign', array('id' => $cm->instance), '*', MUST_EXIST), null, null);
} else {
print_error('invalidcoursemodule');
}
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
$url = new moodle_url('/mod/assign/overrideedit.php');
if ($action) {
$url->param('action', $action);
}
if ($overrideid) {
$url->param('id', $overrideid);
} else {
$url->param('cmid', $cmid);
}
$PAGE->set_url($url);
require_login($course, false, $cm);
$context = context_module::instance($cm->id);
// Add or edit an override.
require_capability('mod/assign:manageoverrides', $context);
if ($overrideid) {
// Editing an override.
$data = clone $override;
} else {
// Creating a new override.
$data = new stdClass();
}
// Merge assign defaults with data.
$keys = array('duedate', 'cutoffdate', 'allowsubmissionsfromdate');
foreach ($keys as $key) {
if (!isset($data->{$key}) || $reset) {
$data->{$key} = $assign->get_context()->{$key};
}
}
// True if group-based override.
$groupmode = !empty($data->groupid) || ($action === 'addgroup' && empty($overrideid));
// If we are duplicating an override, then clear the user/group and override id
// since they will change.
if ($action === 'duplicate') {
$override->id = $data->id = null;
$override->userid = $data->userid = null;
$override->groupid = $data->groupid = null;
}
$overridelisturl = new moodle_url('/mod/assign/overrides.php', array('cmid' => $cm->id));
if (!$groupmode) {
$overridelisturl->param('mode', 'user');
}
// Setup the form.
$mform = new assign_override_form($url, $cm, $assign, $context, $groupmode, $override);
$mform->set_data($data);
if ($mform->is_cancelled()) {
redirect($overridelisturl);
} else if (optional_param('resetbutton', 0, PARAM_ALPHA)) {
$url->param('reset', true);
redirect($url);
} else if ($fromform = $mform->get_data()) {
// Process the data.
$fromform->assignid = $assign->get_context()->id;
// Replace unchanged values with null.
foreach ($keys as $key) {
if (($fromform->{$key} == $assign->get_context()->{$key})) {
$fromform->{$key} = null;
}
}
// See if we are replacing an existing override.
$userorgroupchanged = false;
if (empty($override->id)) {
$userorgroupchanged = true;
} else if (!empty($fromform->userid)) {
$userorgroupchanged = $fromform->userid !== $override->userid;
} else {
$userorgroupchanged = $fromform->groupid !== $override->groupid;
}
if ($userorgroupchanged) {
$conditions = array(
'assignid' => $assign->get_context()->id,
'userid' => empty($fromform->userid) ? null : $fromform->userid,
'groupid' => empty($fromform->groupid) ? null : $fromform->groupid);
if ($oldoverride = $DB->get_record('assign_overrides', $conditions)) {
// There is an old override, so we merge any new settings on top of
// the older override.
foreach ($keys as $key) {
if (is_null($fromform->{$key})) {
$fromform->{$key} = $oldoverride->{$key};
}
}
$assign->delete_override($oldoverride->id);
}
}
// Set the common parameters for one of the events we may be triggering.
$params = array(
'context' => $context,
'other' => array(
'assignid' => $assign->get_context()->id
)
);
if (!empty($override->id)) {
$fromform->id = $override->id;
$DB->update_record('assign_overrides', $fromform);
// Determine which override updated event to fire.
$params['objectid'] = $override->id;
if (!$groupmode) {
$params['relateduserid'] = $fromform->userid;
$event = \mod_assign\event\user_override_updated::create($params);
} else {
$params['other']['groupid'] = $fromform->groupid;
$event = \mod_assign\event\group_override_updated::create($params);
}
// Trigger the override updated event.
$event->trigger();
} else {
unset($fromform->id);
$fromform->id = $DB->insert_record('assign_overrides', $fromform);
if ($groupmode) {
$fromform->sortorder = $fromform->id;
$overridecountgroup = $DB->count_records('assign_overrides',
array('userid' => null, 'assignid' => $assign->get_context()->id));
$overridecountall = $DB->count_records('assign_overrides', array('assignid' => $assign->get_context()->id));
if ((!$overridecountgroup) && ($overridecountall)) { // No group overrides and there are user overrides.
$fromform->sortorder = 1;
} else {
$fromform->sortorder = $overridecountgroup;
}
$DB->update_record('assign_overrides', $fromform);
}
// Determine which override created event to fire.
$params['objectid'] = $fromform->id;
if (!$groupmode) {
$params['relateduserid'] = $fromform->userid;
$event = \mod_assign\event\user_override_created::create($params);
} else {
$params['other']['groupid'] = $fromform->groupid;
$event = \mod_assign\event\group_override_created::create($params);
}
// Trigger the override created event.
$event->trigger();
}
assign_update_events($assign, $fromform);
if (!empty($fromform->submitbutton)) {
redirect($overridelisturl);
}
// The user pressed the 'again' button, so redirect back to this page.
$url->remove_params('cmid');
$url->param('action', 'duplicate');
$url->param('id', $fromform->id);
redirect($url);
}
// Print the form.
$pagetitle = get_string('editoverride', 'assign');
$PAGE->navbar->add($pagetitle);
$PAGE->set_pagelayout('admin');
$PAGE->set_title($pagetitle);
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($assign->get_context()->name, true, array('context' => $context)));
$mform->display();
echo $OUTPUT->footer();

300
mod/assign/overrides.php Normal file
View File

@ -0,0 +1,300 @@
<?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/>.
/**
* This page handles listing of assign overrides
*
* @package mod_assign
* @copyright 2016 Ilya Tregubov
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once(dirname(__FILE__) . '/../../config.php');
require_once($CFG->dirroot.'/mod/assign/lib.php');
require_once($CFG->dirroot.'/mod/assign/locallib.php');
require_once($CFG->dirroot.'/mod/assign/override_form.php');
$cmid = required_param('cmid', PARAM_INT);
$mode = optional_param('mode', '', PARAM_ALPHA); // One of 'user' or 'group', default is 'group'.
$action = optional_param('action', '', PARAM_ALPHA);
$redirect = $CFG->wwwroot.'/mod/assign/overrides.php?cmid=' . $cmid . '&amp;mode=group';
list($course, $cm) = get_course_and_cm_from_cmid($cmid, 'assign');
$assign = $DB->get_record('assign', array('id' => $cm->instance), '*', MUST_EXIST);
$overridecountgroup = $DB->count_records('assign_overrides', array('userid' => null, 'assignid' => $assign->id));
// Get the course groups.
$groups = groups_get_all_groups($cm->course);
if ($groups === false) {
$groups = array();
}
// Default mode is "group", unless there are no groups.
if ($mode != "user" and $mode != "group") {
if (!empty($groups)) {
$mode = "group";
} else {
$mode = "user";
}
}
$groupmode = ($mode == "group");
$url = new moodle_url('/mod/assign/overrides.php', array('cmid' => $cm->id, 'mode' => $mode));
$PAGE->set_url($url);
require_login($course, false, $cm);
$context = context_module::instance($cm->id);
// Check the user has the required capabilities to list overrides.
require_capability('mod/assign:manageoverrides', $context);
if ($action == 'movegroupoverride') {
$id = required_param('id', PARAM_INT);
$dir = required_param('dir', PARAM_ALPHA);
if (confirm_sesskey()) {
move_group_override($id, $dir, $assign->id);
}
redirect($redirect);
}
// Display a list of overrides.
$PAGE->set_pagelayout('admin');
$PAGE->set_title(get_string('overrides', 'assign'));
$PAGE->set_heading($course->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading(format_string($assign->name, true, array('context' => $context)));
// Delete orphaned group overrides.
$sql = 'SELECT o.id
FROM {assign_overrides} o LEFT JOIN {groups} g
ON o.groupid = g.id
WHERE o.groupid IS NOT NULL
AND g.id IS NULL
AND o.assignid = ?';
$params = array($assign->id);
$orphaned = $DB->get_records_sql($sql, $params);
if (!empty($orphaned)) {
$DB->delete_records_list('assign_overrides', 'id', array_keys($orphaned));
}
// Fetch all overrides.
if ($groupmode) {
$colname = get_string('group');
$sql = 'SELECT o.*, g.name
FROM {assign_overrides} o
JOIN {groups} g ON o.groupid = g.id
WHERE o.assignid = :assignid
ORDER BY o.sortorder';
$params = array('assignid' => $assign->id);
} else {
$colname = get_string('user');
list($sort, $params) = users_order_by_sql('u');
$sql = 'SELECT o.*, ' . get_all_user_name_fields(true, 'u') . '
FROM {assign_overrides} o
JOIN {user} u ON o.userid = u.id
WHERE o.assignid = :assignid
ORDER BY ' . $sort;
$params['assignid'] = $assign->id;
}
$overrides = $DB->get_records_sql($sql, $params);
// Initialise table.
$table = new html_table();
$table->headspan = array(1, 2, 1);
$table->colclasses = array('colname', 'colsetting', 'colvalue', 'colaction');
$table->head = array(
$colname,
get_string('overrides', 'assign'),
get_string('action'),
);
$userurl = new moodle_url('/user/view.php', array());
$groupurl = new moodle_url('/group/overview.php', array('id' => $cm->course));
$overridedeleteurl = new moodle_url('/mod/assign/overridedelete.php');
$overrideediturl = new moodle_url('/mod/assign/overrideedit.php');
$hasinactive = false; // Whether there are any inactive overrides.
foreach ($overrides as $override) {
$fields = array();
$values = array();
$active = true;
// Check for inactive overrides.
if (!$groupmode) {
if (!is_enrolled($context, $override->userid)) {
// User not enrolled.
$active = false;
} else if (!\core_availability\info_module::is_user_visible($cm, $override->userid)) {
// User cannot access the module.
$active = false;
}
}
// Format allowsubmissionsfromdate.
if (isset($override->allowsubmissionsfromdate)) {
$fields[] = get_string('open', 'assign');
$values[] = $override->allowsubmissionsfromdate > 0 ? userdate($override->allowsubmissionsfromdate) : get_string('noopen',
'assign');
}
// Format duedate.
if (isset($override->duedate)) {
$fields[] = get_string('duedate', 'assign');
$values[] = $override->duedate > 0 ? userdate($override->duedate) : get_string('noclose', 'assign');
}
// Format cutoffdate.
if (isset($override->cutoffdate)) {
$fields[] = get_string('cutoffdate', 'assign');
$values[] = $override->cutoffdate > 0 ? userdate($override->cutoffdate) : get_string('noclose', 'assign');
}
// Icons.
$iconstr = '';
if ($active) {
// Edit.
$editurlstr = $overrideediturl->out(true, array('id' => $override->id));
$iconstr = '<a title="' . get_string('edit') . '" href="'. $editurlstr . '">' .
'<img src="' . $OUTPUT->pix_url('t/edit') . '" class="iconsmall" alt="' .
get_string('edit') . '" /></a> ';
// Duplicate.
$copyurlstr = $overrideediturl->out(true,
array('id' => $override->id, 'action' => 'duplicate'));
$iconstr .= '<a title="' . get_string('copy') . '" href="' . $copyurlstr . '">' .
'<img src="' . $OUTPUT->pix_url('t/copy') . '" class="iconsmall" alt="' .
get_string('copy') . '" /></a> ';
}
// Delete.
$deleteurlstr = $overridedeleteurl->out(true,
array('id' => $override->id, 'sesskey' => sesskey()));
$iconstr .= '<a title="' . get_string('delete') . '" href="' . $deleteurlstr . '">' .
'<img src="' . $OUTPUT->pix_url('t/delete') . '" class="iconsmall" alt="' .
get_string('delete') . '" /></a> ';
if ($groupmode) {
$usergroupstr = '<a href="' . $groupurl->out(true,
array('group' => $override->groupid)) . '" >' . $override->name . '</a>';
// Move up.
if ($override->sortorder > 1) {
$iconstr .= '<a title="'.get_string('moveup').'" href="overrides.php?cmid=' . $cmid .
'&amp;id=' . $override->id .'&amp;action=movegroupoverride&amp;dir=up&amp;sesskey='.sesskey().'">
<img src="'.$OUTPUT->pix_url('t/up') . '" alt="'.get_string('moveup').'" class="iconsmall" /></a> ';
} else {
$iconstr .= '<img src="'.$OUTPUT->pix_url('spacer') . '" alt="" class="iconsmall" /> ';
}
// Move down.
if ($override->sortorder < $overridecountgroup) {
$iconstr .= '<a title="'.get_string('movedown').'" href="overrides.php?cmid='.$cmid.
'&amp;id=' . $override->id . '&amp;action=movegroupoverride&amp;dir=down&amp;sesskey='.sesskey().'">
<img src="'.$OUTPUT->pix_url('t/down') . '" alt="'.get_string('movedown').'" class="iconsmall" /></a> ';
} else {
$iconstr .= '<img src="'.$OUTPUT->pix_url('spacer') . '" alt="" class="iconsmall" /> ';
}
} else {
$usergroupstr = '<a href="' . $userurl->out(true,
array('id' => $override->userid)) . '" >' . fullname($override) . '</a>';
}
$class = '';
if (!$active) {
$class = "dimmed_text";
$usergroupstr .= '*';
$hasinactive = true;
}
$usergroupcell = new html_table_cell();
$usergroupcell->rowspan = count($fields);
$usergroupcell->text = $usergroupstr;
$actioncell = new html_table_cell();
$actioncell->rowspan = count($fields);
$actioncell->text = $iconstr;
for ($i = 0; $i < count($fields); ++$i) {
$row = new html_table_row();
$row->attributes['class'] = $class;
if ($i == 0) {
$row->cells[] = $usergroupcell;
}
$cell1 = new html_table_cell();
$cell1->text = $fields[$i];
$row->cells[] = $cell1;
$cell2 = new html_table_cell();
$cell2->text = $values[$i];
$row->cells[] = $cell2;
if ($i == 0) {
$row->cells[] = $actioncell;
}
$table->data[] = $row;
}
}
// Output the table and button.
echo html_writer::start_tag('div', array('id' => 'assignoverrides'));
if (count($table->data)) {
echo html_writer::table($table);
}
if ($hasinactive) {
echo $OUTPUT->notification(get_string('inactiveoverridehelp', 'assign'), 'dimmed_text');
}
echo html_writer::start_tag('div', array('class' => 'buttons'));
$options = array();
if ($groupmode) {
if (empty($groups)) {
// There are no groups.
echo $OUTPUT->notification(get_string('groupsnone', 'assign'), 'error');
$options['disabled'] = true;
}
echo $OUTPUT->single_button($overrideediturl->out(true,
array('action' => 'addgroup', 'cmid' => $cm->id)),
get_string('addnewgroupoverride', 'assign'), 'post', $options);
} else {
$users = array();
// See if there are any users in the assign.
$users = get_enrolled_users($context);
$info = new \core_availability\info_module($cm);
$users = $info->filter_user_list($users);
if (empty($users)) {
// There are no users.
echo $OUTPUT->notification(get_string('usersnone', 'assign'), 'error');
$options['disabled'] = true;
}
echo $OUTPUT->single_button($overrideediturl->out(true,
array('action' => 'adduser', 'cmid' => $cm->id)),
get_string('addnewuseroverride', 'assign'), 'get', $options);
}
echo html_writer::end_tag('div');
echo html_writer::end_tag('div');
// Finish the page.
echo $OUTPUT->footer();

View File

@ -72,9 +72,6 @@
{{#caneditsettings}}
<a href="{{config.wwwroot}}/course/modedit.php?update={{cmid}}&return=1">{{#pix}}t/edit, core,{{#str}}editsettings{{/str}}{{/pix}}</a>
{{/caneditsettings}}
{{#duedate}}
<small data-region="assignment-tooltip" aria-describedby="tooltip-{{uniqid}}">{{#str}}duedatecolon, mod_assign, {{duedatestr}}{{/str}}</small>
{{/duedate}}
</span>
</div>

View File

@ -37,4 +37,4 @@
"profileimageurl": "https://moodle.org/pix/u/f3.png"
}
}}
<h4>{{^blindmarking}}<a href="{{globals.config.wwwroot}}/user/view.php?id={{id}}&course={{courseid}}">{{/blindmarking}}{{#profileimageurl}}<img src="{{profileimageurl}}" class="img-rounded" height="40" role="presentation"/>{{/profileimageurl}} {{fullname}}{{#hasidentity}}<em><small> {{identity}} </small></em>{{/hasidentity}}{{^blindmarking}}</a>{{/blindmarking}}</h4>
<h4>{{^blindmarking}}<a href="{{globals.config.wwwroot}}/user/view.php?id={{id}}&course={{courseid}}">{{/blindmarking}}{{#profileimageurl}}<img src="{{profileimageurl}}" class="img-rounded" height="40" role="presentation"/>{{/profileimageurl}} {{fullname}}{{#hasidentity}}<em><small> {{identity}} </small></em>{{/hasidentity}}{{#duedate}}<em><small>{{#str}}duedatecolon, mod_assign, {{duedatestr}}{{/str}}</small></em>{{/duedate}}{{^blindmarking}}</a>{{/blindmarking}}</h4>

View File

@ -0,0 +1,110 @@
@mod @mod_assign
Feature: Assign reset
In order to reuse past Assignss
As a teacher
I need to remove all previous data.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
| student2 | Sam2 | Student2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
And I log in as "teacher1"
And I follow "Course 1"
And I turn editing mode on
And I add a "Assignment" to section "1" and I fill the form with:
| Assignment name | Test assignment name |
| Description | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_onlinetext_wordlimit_enabled | 1 |
| assignsubmission_onlinetext_wordlimit | 10 |
| assignsubmission_file_enabled | 0 |
Scenario: Use course reset to clear all attempt data
When I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
When I press "Add submission"
And I set the following fields to these values:
| Online text | I'm the student first submission |
And I press "Save changes"
Then I should see "Submitted for grading"
And I should see "I'm the student first submission"
And I should see "Not graded"
And I log out
And I log in as "teacher1"
And I follow "Course 1"
And I follow "Test assignment name"
And I navigate to "View all submissions" node in "Assignment administration"
And I should see "Submitted for grading"
And I navigate to "Reset" node in "Course administration"
And I set the following fields to these values:
| Delete all submissions | 1 |
And I press "Reset course"
And I press "Continue"
And I follow "Course 1"
And I follow "Test assignment name"
And I navigate to "View all submissions" node in "Assignment administration"
Then I should not see "Submitted for grading"
Scenario: Use course reset to remove user overrides.
When I follow "Test assignment name"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Sam1 Student1"
And I navigate to "Reset" node in "Course administration"
And I set the following fields to these values:
| Delete all user overrides | 1 |
And I press "Reset course"
And I press "Continue"
And I follow "Course 1"
And I follow "Test assignment name"
And I navigate to "User overrides" node in "Assignment administration"
Then I should not see "Sam1 Student1"
Scenario: Use course reset to remove group overrides.
When I follow "Test assignment name"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Group 1"
And I navigate to "Reset" node in "Course administration"
And I set the following fields to these values:
| Delete all group overrides | 1 |
And I press "Reset course"
And I press "Continue"
And I follow "Course 1"
And I follow "Test assignment name"
And I navigate to "Group overrides" node in "Assignment administration"
Then I should not see "Group 1"

View File

@ -0,0 +1,248 @@
@mod @mod_assign
Feature: Assign group override
In order to grant a group special access to an assignment
As a teacher
I need to create an override for that group.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
| student2 | Sam2 | Student2 | student2@example.com |
| student3 | Sam3 | Student3 | student3@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
| student3 | C1 | student |
And the following "groups" exist:
| name | course | idnumber |
| Group 1 | C1 | G1 |
| Group 2 | C1 | G2 |
Given the following "group members" exist:
| user | group |
| student1 | G1 |
| student2 | G2 |
| student3 | G1 |
And I log in as "teacher1"
And I follow "Course 1"
And I turn editing mode on
And I add a "Assignment" to section "1" and I fill the form with:
| Assignment name | Test assignment name |
| Description | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_onlinetext_wordlimit_enabled | 1 |
| assignsubmission_onlinetext_wordlimit | 10 |
| assignsubmission_file_enabled | 0 |
Scenario: Add, modify then delete a group override
When I follow "Test assignment name"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
Then I click on "Edit" "link"
And I set the following fields to these values:
| duedate[year] | 2030 |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I click on "Delete" "link"
And I press "Continue"
And I should not see "Group 1"
Scenario: Duplicate a user override
When I follow "Test assignment name"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
Then I click on "copy" "link"
And I set the following fields to these values:
| Override group | Group 2 |
| duedate[year] | 2030 |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I should see "Group 2"
Scenario: Allow a group to have a different due date
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 1 |
| id_allowsubmissionsfromdate_enabled | 0 |
| id_cutoffdate_enabled | 0 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2000 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save and display"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
Then I should see "Saturday, 1 January 2000, 8:00"
And I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "Wednesday, 1 January 2020, 8:00"
Scenario: Allow a group to have a different cut off date
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 0 |
| id_allowsubmissionsfromdate_enabled | 0 |
| id_cutoffdate_enabled | 1 |
| cutoffdate[day] | 1 |
| cutoffdate[month] | January |
| cutoffdate[year] | 2000 |
| cutoffdate[hour] | 08 |
| cutoffdate[minute] | 00 |
And I press "Save and display"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_cutoffdate_enabled | 1 |
| cutoffdate[day] | 1 |
| cutoffdate[month] | January |
| cutoffdate[year] | 2020 |
| cutoffdate[hour] | 08 |
| cutoffdate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
Then I should not see "Make changes to your submission"
And I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "Make changes to your submission"
Scenario: Allow a group to have a different start date
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 0 |
| id_allowsubmissionsfromdate_enabled | 1 |
| id_cutoffdate_enabled | 0 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2020 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save and display"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_allowsubmissionsfromdate_enabled | 1 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2015 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save"
And I should see "Thursday, 1 January 2015, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
Then I should see "This assignment will accept submissions from Wednesday, 1 January 2020, 8:00"
And I should not see "Add submission"
And I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should not see "This assignment will accept submissions from Wednesday, 1 January 2020, 8:00"
Scenario: Add both a user and group override and verify that both are applied correctly
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 0 |
| id_allowsubmissionsfromdate_enabled | 1 |
| id_cutoffdate_enabled | 0 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2030 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save and display"
And I navigate to "Group overrides" node in "Assignment administration"
And I press "Add group override"
And I set the following fields to these values:
| Override group | Group 1 |
| id_allowsubmissionsfromdate_enabled | 1 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2020 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_allowsubmissionsfromdate_enabled | 1 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2021 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save"
And I should see "Friday, 1 January 2021, 8:00"
And I log out
Then I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "This assignment will accept submissions from Friday, 1 January 2021, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "This assignment will accept submissions from Tuesday, 1 January 2030, 8:00"
And I log out
And I log in as "student3"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "This assignment will accept submissions from Wednesday, 1 January 2020, 8:00"

View File

@ -0,0 +1,183 @@
@mod @mod_assign
Feature: Assign user override
In order to grant a student special access to an assignment
As a teacher
I need to create an override for that user.
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Tina | Teacher1 | teacher1@example.com |
| student1 | Sam1 | Student1 | student1@example.com |
| student2 | Sam2 | Student2 | student2@example.com |
And the following "courses" exist:
| fullname | shortname | category |
| Course 1 | C1 | 0 |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| student1 | C1 | student |
| student2 | C1 | student |
And I log in as "teacher1"
And I follow "Course 1"
And I turn editing mode on
And I add a "Assignment" to section "1" and I fill the form with:
| Assignment name | Test assignment name |
| Description | Submit your online text |
| assignsubmission_onlinetext_enabled | 1 |
| assignsubmission_onlinetext_wordlimit_enabled | 1 |
| assignsubmission_onlinetext_wordlimit | 10 |
| assignsubmission_file_enabled | 0 |
Scenario: Add, modify then delete a user override
When I follow "Test assignment name"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
Then I click on "Edit" "link"
And I set the following fields to these values:
| duedate[year] | 2030 |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I click on "Delete" "link"
And I press "Continue"
And I should not see "Sam1 Student1"
Scenario: Duplicate a user override
When I follow "Test assignment name"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
Then I click on "copy" "link"
And I set the following fields to these values:
| Override user | Student2 |
| duedate[year] | 2030 |
And I press "Save"
And I should see "Tuesday, 1 January 2030, 8:00"
And I should see "Sam2 Student2"
Scenario: Allow a user to have a different due date
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 1 |
| id_allowsubmissionsfromdate_enabled | 0 |
| id_cutoffdate_enabled | 0 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2000 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save and display"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_duedate_enabled | 1 |
| duedate[day] | 1 |
| duedate[month] | January |
| duedate[year] | 2020 |
| duedate[hour] | 08 |
| duedate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
Then I should see "Saturday, 1 January 2000, 8:00"
And I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "Wednesday, 1 January 2020, 8:00"
Scenario: Allow a user to have a different cut off date
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 0 |
| id_allowsubmissionsfromdate_enabled | 0 |
| id_cutoffdate_enabled | 1 |
| cutoffdate[day] | 1 |
| cutoffdate[month] | January |
| cutoffdate[year] | 2000 |
| cutoffdate[hour] | 08 |
| cutoffdate[minute] | 00 |
And I press "Save and display"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_cutoffdate_enabled | 1 |
| cutoffdate[day] | 1 |
| cutoffdate[month] | January |
| cutoffdate[year] | 2020 |
| cutoffdate[hour] | 08 |
| cutoffdate[minute] | 00 |
And I press "Save"
And I should see "Wednesday, 1 January 2020, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
Then I should not see "Make changes to your submission"
And I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should see "Make changes to your submission"
Scenario: Allow a user to have a different start date
When I follow "Test assignment name"
And I navigate to "Edit settings" node in "Assignment administration"
And I set the following fields to these values:
| id_duedate_enabled | 0 |
| id_allowsubmissionsfromdate_enabled | 1 |
| id_cutoffdate_enabled | 0 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2020 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save and display"
And I navigate to "User overrides" node in "Assignment administration"
And I press "Add user override"
And I set the following fields to these values:
| Override user | Student1 |
| id_allowsubmissionsfromdate_enabled | 1 |
| allowsubmissionsfromdate[day] | 1 |
| allowsubmissionsfromdate[month] | January |
| allowsubmissionsfromdate[year] | 2015 |
| allowsubmissionsfromdate[hour] | 08 |
| allowsubmissionsfromdate[minute] | 00 |
And I press "Save"
And I should see "Thursday, 1 January 2015, 8:00"
And I log out
And I log in as "student2"
And I follow "Course 1"
And I follow "Test assignment name"
Then I should see "This assignment will accept submissions from Wednesday, 1 January 2020, 8:00"
And I log out
And I log in as "student1"
And I follow "Course 1"
And I follow "Test assignment name"
And I should not see "This assignment will accept submissions from Wednesday, 1 January 2020, 8:00"

View File

@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/assign/tests/base_test.php');
require_once($CFG->dirroot . '/mod/assign/tests/fixtures/event_mod_assign_fixtures.php');
require_once($CFG->dirroot . '/mod/assign/locallib.php');
/**
* Contains the event tests for the module assign.
@ -1023,4 +1024,193 @@ class assign_events_testcase extends mod_assign_base_testcase {
$this->assertEventLegacyLogData($expected, $event);
$this->assertEventContextNotUsed($event);
}
/**
* Test the user override created event.
*
* There is no external API for creating a user override, so the unit test will simply
* create and trigger the event and ensure the event data is returned as expected.
*/
public function test_user_override_created() {
$course = $this->getDataGenerator()->create_course();
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
$params = array(
'objectid' => 1,
'relateduserid' => 2,
'context' => context_module::instance($assign->cmid),
'other' => array(
'assignid' => $assign->id
)
);
$event = \mod_assign\event\user_override_created::create($params);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\mod_assign\event\user_override_created', $event);
$this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test the group override created event.
*
* There is no external API for creating a group override, so the unit test will simply
* create and trigger the event and ensure the event data is returned as expected.
*/
public function test_group_override_created() {
$course = $this->getDataGenerator()->create_course();
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
$params = array(
'objectid' => 1,
'context' => context_module::instance($assign->cmid),
'other' => array(
'assignid' => $assign->id,
'groupid' => 2
)
);
$event = \mod_assign\event\group_override_created::create($params);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\mod_assign\event\group_override_created', $event);
$this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test the user override updated event.
*
* There is no external API for updating a user override, so the unit test will simply
* create and trigger the event and ensure the event data is returned as expected.
*/
public function test_user_override_updated() {
$course = $this->getDataGenerator()->create_course();
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
$params = array(
'objectid' => 1,
'relateduserid' => 2,
'context' => context_module::instance($assign->cmid),
'other' => array(
'assignid' => $assign->id
)
);
$event = \mod_assign\event\user_override_updated::create($params);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\mod_assign\event\user_override_updated', $event);
$this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test the group override updated event.
*
* There is no external API for updating a group override, so the unit test will simply
* create and trigger the event and ensure the event data is returned as expected.
*/
public function test_group_override_updated() {
$course = $this->getDataGenerator()->create_course();
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
$params = array(
'objectid' => 1,
'context' => context_module::instance($assign->cmid),
'other' => array(
'assignid' => $assign->id,
'groupid' => 2
)
);
$event = \mod_assign\event\group_override_updated::create($params);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$event->trigger();
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\mod_assign\event\group_override_updated', $event);
$this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test the user override deleted event.
*/
public function test_user_override_deleted() {
global $DB;
$course = $this->getDataGenerator()->create_course();
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
$this->assign = new assign($assign, null, null);
// Create an override.
$override = new stdClass();
$override->assign = $this->assign->get_context()->id;
$override->userid = 2;
$override->id = $DB->insert_record('assign_overrides', $override);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$this->assign->delete_override($override->id);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\mod_assign\event\user_override_deleted', $event);
$this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
$this->assertEventContextNotUsed($event);
}
/**
* Test the group override deleted event.
*/
public function test_group_override_deleted() {
global $DB;
$course = $this->getDataGenerator()->create_course();
$assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id));
$this->assign = new assign($assign, null, null);
// Create an override.
$override = new stdClass();
$override->assign = $this->assign->get_context()->id;
$override->groupid = 2;
$override->id = $DB->insert_record('assign_overrides', $override);
// Trigger and capture the event.
$sink = $this->redirectEvents();
$this->assign->delete_override($override->id);
$events = $sink->get_events();
$event = reset($events);
// Check that the event data is valid.
$this->assertInstanceOf('\mod_assign\event\group_override_deleted', $event);
$this->assertEquals(context_module::instance($assign->cmid), $event->get_context());
$this->assertEventContextNotUsed($event);
}
}

View File

@ -317,7 +317,7 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$document = new DOMDocument();
@$document->loadHTML($output);
$xpath = new DOMXPath($document);
$this->assertEquals('', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])'));
$this->assertEquals('', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c11"])'));
}
/**
@ -367,20 +367,20 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$this->assertSame(get_string('submissionstatus_submitted', 'assign'), $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c4"]/div[@class="submissionstatussubmitted"])'));
// Check submission last modified date
$this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])')));
$this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])')));
$this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c11"])')));
$this->assertGreaterThan(0, strtotime($xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c11"])')));
// Check group.
$this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c5"])'));
$this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c5"])'));
$this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c8"])'));
$this->assertSame($this->groups[0]->name, $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c8"])'));
// Check submission text.
$this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c9"]/div/div)'));
$this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c9"]/div/div)'));
$this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r0_c12"]/div/div)'));
$this->assertSame('Submission text', $xpath->evaluate('string(//td[@id="mod_assign_grading_r3_c12"]/div/div)'));
// Check comments can be made.
$this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c10"]//textarea)'));
$this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c10"]//textarea)'));
$this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r0_c13"]//textarea)'));
$this->assertSame(1, (int)$xpath->evaluate('count(//td[@id="mod_assign_grading_r3_c13"]//textarea)'));
}
public function test_show_intro() {
@ -513,6 +513,8 @@ class mod_assign_locallib_testcase extends mod_assign_base_testcase {
$data = new stdClass();
$data->reset_assign_submissions = 1;
$data->reset_gradebook_grades = 1;
$data->reset_assign_user_overrides = 1;
$data->reset_assign_group_overrides = 1;
$data->courseid = $this->course->id;
$data->timeshift = 24*60*60;
$this->setUser($this->editingteachers[0]);

View File

@ -47,6 +47,9 @@ $PAGE->set_url($url);
// Update module completion status.
$assign->set_module_viewed();
// Apply overrides.
$assign->update_effective_access($USER->id);
// Get the assign class to
// render the page.
echo $assign->view(optional_param('action', '', PARAM_TEXT));