Merge branch 'MDL-68163-master' of https://github.com/syxton/moodle
This commit is contained in:
@@ -86,6 +86,17 @@ if ($action == 'moveselect') {
|
||||
$grade_edit_tree = new grade_edit_tree($gtree, $movingeid, $gpr);
|
||||
|
||||
switch ($action) {
|
||||
case 'duplicate':
|
||||
if ($eid and confirm_sesskey()) {
|
||||
if (!$el = $gtree->locate_element($eid)) {
|
||||
print_error('invalidelementid', '', $returnurl);
|
||||
}
|
||||
|
||||
$object->duplicate();
|
||||
redirect($returnurl);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if ($eid && confirm_sesskey()) {
|
||||
if (!$grade_edit_tree->element_deletable($element)) {
|
||||
|
||||
@@ -149,6 +149,18 @@ class grade_edit_tree {
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
if ($this->element_duplicatable($element)) {
|
||||
$duplicateparams = array();
|
||||
$duplicateparams['id'] = $COURSE->id;
|
||||
$duplicateparams['action'] = 'duplicate';
|
||||
$duplicateparams['eid'] = $eid;
|
||||
$duplicateparams['sesskey'] = sesskey();
|
||||
$aurl = new moodle_url('index.php', $duplicateparams);
|
||||
$duplicateicon = new pix_icon('t/copy', get_string('duplicate'));
|
||||
$icon = new action_menu_link_secondary($aurl, $duplicateicon, get_string('duplicate'));
|
||||
$actionsmenu->add($icon);
|
||||
}
|
||||
|
||||
$aurl = new moodle_url('index.php', array('id' => $COURSE->id, 'action' => 'moveselect', 'eid' => $eid, 'sesskey' => sesskey()));
|
||||
$moveaction .= $OUTPUT->action_icon($aurl, new pix_icon('t/move', get_string('move')));
|
||||
}
|
||||
@@ -460,6 +472,24 @@ class grade_edit_tree {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an element of the grade tree, returns whether it is duplicatable or not (only manual grade items are duplicatable)
|
||||
*
|
||||
* @param array $element
|
||||
* @return bool
|
||||
*/
|
||||
public function element_duplicatable($element) {
|
||||
if ($element['type'] != 'item') {
|
||||
return false;
|
||||
}
|
||||
|
||||
$gradeitem = $element['object'];
|
||||
if ($gradeitem->itemtype != 'mod') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the grade tree and an array of element ids (e.g. c15, i42), and expecting the 'moveafter' URL param,
|
||||
* moves the selected items to the requested location. Then redirects the user to the given $returnurl
|
||||
|
||||
@@ -117,6 +117,29 @@ class behat_grade extends behat_base {
|
||||
"//tr[descendant::*[text() = " . $this->escape($gradeitem) . "]]", 'xpath_element'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicates a grade item or category.
|
||||
*
|
||||
* Teacher must be on the grade setup page.
|
||||
*
|
||||
* @Given /^I duplicate the grade item "(?P<grade_item_string>(?:[^"]|\\")*)"$/
|
||||
* @param string $gradeitem
|
||||
*/
|
||||
public function i_duplicate_the_grade_item($gradeitem) {
|
||||
|
||||
$gradeitem = behat_context_helper::escape($gradeitem);
|
||||
|
||||
if ($this->running_javascript()) {
|
||||
$xpath = "//tr[contains(.,$gradeitem)]//*[contains(@class,'moodle-actionmenu')]//a[contains(@class,'toggle-display')]";
|
||||
if ($this->getSession()->getPage()->findAll('xpath', $xpath)) {
|
||||
$this->execute("behat_general::i_click_on", array($this->escape($xpath), "xpath_element"));
|
||||
}
|
||||
}
|
||||
|
||||
$this->execute("behat_general::i_click_on_in_the", array(get_string('duplicate'), 'link',
|
||||
"//tr[descendant::*[text() = " . $this->escape($gradeitem) . "]]", 'xpath_element'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a calculated manual grade item. Needs a table with item name - idnumber relation.
|
||||
* The step requires you to be in the 'Gradebook setup' page.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
@core @core_grades
|
||||
Feature: We can duplicate grade items that already exist.
|
||||
In order to quickly create grade items that have similar settings.
|
||||
As a teacher
|
||||
I need to duplicate an existing grade item and check that its values are properly duplicated.
|
||||
|
||||
Background:
|
||||
Given the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | topics |
|
||||
And the following "grade categories" exist:
|
||||
| fullname | course |
|
||||
| Category1 | C1 |
|
||||
And the following "activities" exist:
|
||||
| activity | course | idnumber | name | gradecategory |
|
||||
| assign | C1 | a1 | Assignment1 | Category1 |
|
||||
And the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "grade items" exist:
|
||||
| itemname | course | category | idnumber | gradetype | grademax | grademin | gradepass | display | decimals | hidden | weightoverride |
|
||||
| Item1 | C1 | Category1 | 001 | Value | 80.00 | 5.00 | 40.00 | 1 | 1 | 0 | 1 |
|
||||
|
||||
Scenario: Ensure the duplicated grade item settings match the original grade item
|
||||
Given I log in as "teacher1"
|
||||
And I am on "Course 1" course homepage
|
||||
And I navigate to "Setup > Gradebook setup" in the course gradebook
|
||||
And I should not see "Duplicate Category1"
|
||||
And I should not see "Duplicate Assignment1"
|
||||
When I duplicate the grade item "Item1"
|
||||
Then I should see "Item1 (copy)"
|
||||
And I follow "Edit Item1 (copy)"
|
||||
And the field "Item name" matches value "Item1 (copy)"
|
||||
And the field "ID number" matches value ""
|
||||
And the field "Grade type" matches value "Value"
|
||||
And the field "Maximum grade" matches value "80.00"
|
||||
And the field "Minimum grade" matches value "5.00"
|
||||
And the field "Grade to pass" matches value "40.00"
|
||||
And the field "Grade display type" matches value "Real"
|
||||
And the field "Overall decimal places" matches value "1"
|
||||
And the field "Hidden" matches value "0"
|
||||
And the field "Weight adjusted" matches value "1"
|
||||
@@ -163,6 +163,7 @@ $string['dropped'] = 'Dropped';
|
||||
$string['droplowestvalues'] = 'Drop {$a} lowest values';
|
||||
$string['dropxlowest'] = 'Drop X lowest';
|
||||
$string['dropxlowestwarning'] = 'Note: If you use drop x lowest the grading assumes that all items in the category have the same point value. If point values differ results will be unpredictable';
|
||||
$string['duplicatedgradeitem'] = '{$a} (copy)';
|
||||
$string['duplicatescale'] = 'Duplicate scale';
|
||||
$string['edit'] = 'Edit';
|
||||
$string['editcalculation'] = 'Edit calculation';
|
||||
|
||||
@@ -449,6 +449,41 @@ class grade_item extends grade_object {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate grade item.
|
||||
*
|
||||
* @return grade_item The duplicate grade item
|
||||
*/
|
||||
public function duplicate() {
|
||||
// Convert current object to array.
|
||||
$copy = (array) $this;
|
||||
|
||||
if (empty($copy["id"])) {
|
||||
throw new moodle_exception('invalidgradeitemid');
|
||||
}
|
||||
|
||||
// Remove fields that will be either unique or automatically filled.
|
||||
$removekeys = array();
|
||||
$removekeys[] = 'id';
|
||||
$removekeys[] = 'idnumber';
|
||||
$removekeys[] = 'timecreated';
|
||||
$removekeys[] = 'sortorder';
|
||||
foreach ($removekeys as $key) {
|
||||
unset($copy[$key]);
|
||||
}
|
||||
|
||||
// Addendum to name.
|
||||
$copy["itemname"] = get_string('duplicatedgradeitem', 'grades', $copy["itemname"]);
|
||||
|
||||
// Create new grade item.
|
||||
$gradeitem = new grade_item($copy);
|
||||
|
||||
// Insert grade item into database.
|
||||
$gradeitem->insert();
|
||||
|
||||
return $gradeitem;
|
||||
}
|
||||
|
||||
/**
|
||||
* In addition to perform parent::insert(), calls force_regrading() method too.
|
||||
*
|
||||
|
||||
@@ -1050,4 +1050,78 @@ class core_grade_item_testcase extends grade_base_testcase {
|
||||
$this->assertEquals($gradeitem->itemmodule, $event->other['itemmodule']);
|
||||
$this->assertEquals('updatedname', $event->other['itemname']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test grade item duplication expecting success.
|
||||
*/
|
||||
public function test_grade_duplicate_grade_item_success() {
|
||||
$cat = new grade_category();
|
||||
$cat->courseid = $this->courseid;
|
||||
$cat->fullname = 'Grade category';
|
||||
$cat->insert();
|
||||
|
||||
// Method exists.
|
||||
$gi = new grade_item();
|
||||
$this->assertTrue(method_exists($gi, 'duplicate'));
|
||||
|
||||
// Grade item is inserted and valid for duplication.
|
||||
$gi->courseid = $this->courseid;
|
||||
$gi->categoryid = $cat->id;
|
||||
$gi->itemtype = 'manual';
|
||||
$gi->itemname = 'Grade Item 1';
|
||||
$gi->idnumber = '1000';
|
||||
$gi->insert();
|
||||
$gi2 = $gi->duplicate();
|
||||
|
||||
$this->assertEquals($gi->courseid, $gi2->courseid);
|
||||
$this->assertEquals($gi->categoryid, $gi2->categoryid);
|
||||
$this->assertEquals($gi->itemtype, $gi2->itemtype);
|
||||
$this->assertEquals($gi->gradetype, $gi2->gradetype);
|
||||
$this->assertEquals($gi->grademax, $gi2->grademax);
|
||||
$this->assertEquals($gi->grademin, $gi2->grademin);
|
||||
$this->assertEquals($gi->gradepass, $gi2->gradepass);
|
||||
$this->assertEquals($gi->display, $gi2->display);
|
||||
$this->assertEquals($gi->decimals, $gi2->decimals);
|
||||
$this->assertEquals($gi->hidden, $gi2->hidden);
|
||||
$this->assertEquals($gi->weightoverride, $gi2->weightoverride);
|
||||
|
||||
$this->assertNotEquals($gi->id, $gi2->id);
|
||||
$this->assertNotEquals($gi->idnumber, $gi2->idnumber);
|
||||
$this->assertNotEquals($gi->sortorder, $gi2->sortorder);
|
||||
$this->assertNotEquals($gi->itemname, $gi2->itemname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test grade item duplication exception expected with incomplete grade item.
|
||||
*/
|
||||
public function test_grade_duplicate_grade_item_incomplete() {
|
||||
// Grade item is not valid because it is empty.
|
||||
$gi = new grade_item();
|
||||
$gi->courseid = $this->courseid;
|
||||
$this->expectException("moodle_exception");
|
||||
$gi2 = $gi->duplicate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test grade item duplication exception expected because item must be in db.
|
||||
*/
|
||||
public function test_grade_duplicate_grade_item_not_in_db() {
|
||||
$cat = new grade_category();
|
||||
$cat->courseid = $this->courseid;
|
||||
$cat->fullname = 'Grade category';
|
||||
$cat->insert();
|
||||
|
||||
// Grade item is valid for insertion but is not inserted into db.
|
||||
// Duplicate method throws an exception.
|
||||
$gi = new grade_item();
|
||||
$gi->courseid = $this->courseid;
|
||||
$gi->categoryid = $cat->id;
|
||||
$gi->itemtype = 'manual';
|
||||
$gi->itemname = 'Grade Item 1';
|
||||
$gi->idnumber = '1000';
|
||||
|
||||
$this->expectException("moodle_exception");
|
||||
$gi2 = $gi->duplicate();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user