diff --git a/admin/tool/recyclebin/tests/events_test.php b/admin/tool/recyclebin/tests/events_test.php index d10fa932005fa..c3ea0e6847773 100644 --- a/admin/tool/recyclebin/tests/events_test.php +++ b/admin/tool/recyclebin/tests/events_test.php @@ -216,12 +216,18 @@ public function test_course_bin_item_restored() { $sink = $this->redirectEvents(); $rb->restore_item($item); $events = $sink->get_events(); - $event = reset($events); - - // Check that the event contains the expected values. - $this->assertInstanceOf('\tooL_recyclebin\event\course_bin_item_restored', $event); - $this->assertEquals(context_course::instance($course->id), $event->get_context()); - $this->assertEquals($item->id, $event->objectid); - $this->assertEventContextNotUsed($event); + $eventscount = 0; + + foreach ($events as $event) { + if ($event instanceof \tooL_recyclebin\event\course_bin_item_restored) { + // Check that the event contains the expected values. + $this->assertEquals(context_course::instance($course->id), $event->get_context()); + $this->assertEquals($item->id, $event->objectid); + $this->assertEventContextNotUsed($event); + $eventscount++; + } + } + // Only one course_bin_item_restored event should be triggered. + $this->assertEquals(1, $eventscount); } } diff --git a/backup/moodle2/restore_stepslib.php b/backup/moodle2/restore_stepslib.php index 683e90225bee5..0d6518d3bfb64 100644 --- a/backup/moodle2/restore_stepslib.php +++ b/backup/moodle2/restore_stepslib.php @@ -245,6 +245,9 @@ protected function process_grade_item($data) { } $newitemid = $DB->insert_record('grade_items', $data); + $data->id = $newitemid; + $gradeitem = new grade_item($data); + core\event\grade_item_created::create_from_grade_item($gradeitem)->trigger(); } $this->set_mapping('grade_item', $oldid, $newitemid); } diff --git a/lang/en/grades.php b/lang/en/grades.php index 0594b6d431208..ac318d60310c8 100644 --- a/lang/en/grades.php +++ b/lang/en/grades.php @@ -194,6 +194,7 @@ $string['errorupdatinggradecategoryaggregation'] = 'Error updating the aggregation type of grade category ID {$a->id}'; $string['errorupdatinggradeitemaggregationcoef'] = 'Error updating the aggregation coefficient (weight or extra credit) of grade item ID {$a->id}'; $string['eventgradedeleted'] = 'Grade deleted'; +$string['eventgradeitemcreated'] = 'Grade item created'; $string['eventgradelettercreated'] = 'Grade letter created'; $string['eventgradeletterdeleted'] = 'Grade letter deleted'; $string['eventgradeletterupdated'] = 'Grade letter updated'; diff --git a/lib/classes/event/grade_item_created.php b/lib/classes/event/grade_item_created.php new file mode 100644 index 0000000000000..0f98cd2ece4b0 --- /dev/null +++ b/lib/classes/event/grade_item_created.php @@ -0,0 +1,146 @@ +. + +/** + * Grade item created event. + * + * @package core + * @copyright 2019 Dmitrii Metelkin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace core\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Grade item created event class. + * + * @package core + * @since Moodle 3.8 + * @copyright 2019 Dmitrii Metelkin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class grade_item_created extends base { + + /** @var \grade_item $gradeitem */ + protected $gradeitem; + + /** + * Init method. + * + * @return void + */ + protected function init() { + $this->data['objecttable'] = 'grade_items'; + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_OTHER; + } + + /** + * Return localised event name. + * + * @return string + */ + public static function get_name() { + return get_string('eventgradeitemcreated', 'core_grades'); + } + + /** + * Utility method to create a new event. + * + * @param \grade_item $gradeitem + * @return grade_item_created + */ + public static function create_from_grade_item(\grade_item $gradeitem) { + $event = self::create([ + 'objectid' => $gradeitem->id, + 'courseid' => $gradeitem->courseid, + 'context' => \context_course::instance($gradeitem->courseid), + 'other' => [ + 'itemname' => $gradeitem->itemname, + 'itemtype' => $gradeitem->itemtype, + 'itemmodule' => $gradeitem->itemmodule, + ], + ]); + + $event->gradeitem = $gradeitem; + + return $event; + } + + /** + * Get grade object. + * + * @throws \coding_exception + * @return \grade_item + */ + public function get_grade_item() { + if ($this->is_restored()) { + throw new \coding_exception('get_grade_item() is intended for event observers only'); + } + + if (!isset($this->gradeitem)) { + $this->gradeitem = \grade_item::fetch(['id' => $this->objectid]); + } + + return $this->gradeitem; + } + + /** + * Returns description of what happened. + * + * @return string + */ + public function get_description() { + return "The user with id '" . $this->userid . "' created a grade item with id '" . $this->objectid . "'" . + " of type '" . $this->other['itemtype'] . "' and name '" . $this->other['itemname'] . "'" . + " in the course with the id '" . $this->courseid . "'."; + } + + /** + * Returns relevant URL. + * @return \moodle_url + */ + public function get_url() { + $url = new \moodle_url('/grade/edit/tree/index.php'); + $url->param('id', $this->courseid); + + return $url; + } + + /** + * Custom validation. + * + * @throws \coding_exception when validation does not pass. + */ + protected function validate_data() { + parent::validate_data(); + + if (!array_key_exists('itemname', $this->other)) { + throw new \coding_exception('The \'itemname\' value must be set in other.'); + } + + if (!array_key_exists('itemtype', $this->other)) { + throw new \coding_exception('The \'itemtype\' value must be set in other.'); + } + + if (!array_key_exists('itemmodule', $this->other)) { + throw new \coding_exception('The \'itemmodule\' value must be set in other.'); + } + } + +} diff --git a/lib/grade/grade_item.php b/lib/grade/grade_item.php index 769f69dfd3c53..cc7c9d5dacb9f 100644 --- a/lib/grade/grade_item.php +++ b/lib/grade/grade_item.php @@ -479,6 +479,10 @@ public function insert($source=null) { if (parent::insert($source)) { // force regrading of items if needed $this->force_regrading(); + + $event = \core\event\grade_item_created::create_from_grade_item($this); + $event->trigger(); + return $this->id; } else { diff --git a/lib/grade/tests/grade_item_test.php b/lib/grade/tests/grade_item_test.php index 2bda9684a98b6..8158c55d7b284 100644 --- a/lib/grade/tests/grade_item_test.php +++ b/lib/grade/tests/grade_item_test.php @@ -67,6 +67,7 @@ public function test_grade_item() { $this->sub_test_update_final_grade(); $this->sub_test_grade_item_can_control_visibility(); $this->sub_test_grade_item_fix_sortorder(); + $this->sub_test_grade_item_created_event(); } protected function sub_test_grade_item_construct() { @@ -977,4 +978,37 @@ public function test_set_aggregation_fields_for_aggregation() { $this->assertEquals($todefaults['weightoverride'], $gi->weightoverride); } + /** + * Test that grade item event triggered when a grade item is created. + */ + protected function sub_test_grade_item_created_event() { + $sink = $this->redirectEvents(); + + $gradeitem = new grade_item(); + + $gradeitem->courseid = $this->courseid; + $gradeitem->categoryid = $this->grade_categories[1]->id; + $gradeitem->itemname = 'unittestgradeitem4'; + $gradeitem->itemtype = 'mod'; + $gradeitem->itemmodule = 'quiz'; + $gradeitem->iteminfo = 'Grade item used for unit testing'; + + $gradeitem->insert(); + + $result = $sink->get_events(); + $sink->close(); + + $this->assertCount(1, $result); + + $event = reset($result); + $this->assertEventContextNotUsed($event); + + $eventgradeitem = $event->get_grade_item(); + + $this->assertInstanceOf('grade_item', $eventgradeitem); + $this->assertEquals($gradeitem->id, $eventgradeitem->id); + $this->assertEquals($gradeitem->itemname, $event->other['itemname']); + $this->assertEquals($gradeitem->itemtype, $event->other['itemtype']); + $this->assertEquals($gradeitem->itemmodule, $event->other['itemmodule']); + } }