diff --git a/admin/tool/lp/classes/api.php b/admin/tool/lp/classes/api.php index 67c81cdf9a4..f9a042a07a5 100644 --- a/admin/tool/lp/classes/api.php +++ b/admin/tool/lp/classes/api.php @@ -4236,6 +4236,9 @@ class api { $usercompetency->update(); $evidence->create(); + // Trigger the evidence_created event. + \tool_lp\event\evidence_created::create_from_evidence($evidence, $usercompetency, $recommend)->trigger(); + // The competency was marked as completed, apply the rules. if ($wascompleted) { self::apply_competency_rules_from_usercompetency($usercompetency, $competency); diff --git a/admin/tool/lp/classes/event/evidence_created.php b/admin/tool/lp/classes/event/evidence_created.php new file mode 100644 index 00000000000..70e103e5034 --- /dev/null +++ b/admin/tool/lp/classes/event/evidence_created.php @@ -0,0 +1,174 @@ +. + +/** + * Evidence created event. + * + * @package tool_lp + * @copyright 2016 Jun Pataleta + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +namespace tool_lp\event; + +use core\event\base; +use tool_lp\evidence; +use tool_lp\user_competency; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Evidence created event class. + * + * @property-read array $other { + * Extra information about event. + * + * - int usercompetencyid: The user_competency ID linked to the evidence. + * - int competencyid: The competency ID linked to the evidence from user_competency. + * - int action: The action constant. + * - bool recommend: The recommend flag. + * } + * + * @package tool_lp + * @since Moodle 3.1 + * @copyright 2016 Jun Pataleta + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class evidence_created extends base { + + /** + * Convenience method to instantiate the event. + * + * @param evidence $evidence The evidence. + * @param user_competency $usercompetency The user competency object linked to the evidence. + * @param bool $recommend The recommend flag. + * @return evidence_created + * @throws \coding_exception + */ + public static final function create_from_evidence(evidence $evidence, user_competency $usercompetency, $recommend) { + // Make sure we have a valid evidence. + if (!$evidence->get_id()) { + throw new \coding_exception('The evidence ID must be set.'); + } + + // Make sure we have a valid user competency. + if (!$usercompetency->get_id()) { + throw new \coding_exception('The user competency ID must be set.'); + } + + // Make sure that the a proper user competecy is linked to the evidence. + if ($evidence->get_usercompetencyid() != $usercompetency->get_id()) { + throw new \coding_exception('The user competency linked with this evidence is invalid.'); + } + + $event = static::create([ + 'contextid' => $evidence->get_contextid(), + 'objectid' => $evidence->get_id(), + 'userid' => $evidence->get_actionuserid(), + 'relateduserid' => $usercompetency->get_userid(), + 'other' => [ + 'usercompetencyid' => $usercompetency->get_id(), + 'competencyid' => $usercompetency->get_competencyid(), + 'action' => $evidence->get_action(), + 'recommend' => $recommend + ] + ]); + + // Add record snapshot for the evidence. + $event->add_record_snapshot(evidence::TABLE, $evidence->to_record()); + + // Add record snapshot for the user competency. + $event->add_record_snapshot(user_competency::TABLE, $usercompetency->to_record()); + + return $event; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('eventevidencecreated', 'tool_lp'); + } + + /** + * Returns non-localised description of what happened. + * + * @return string + */ + public function get_description() { + return "The user with id '$this->userid' created an evidence with id '$this->objectid'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + $urlparams = [ + 'id' => $this->other['usercompetencyid'] + ]; + return new \moodle_url('/admin/tool/lp/user_competency.php', $urlparams); + } + + /** + * Initialise the event data. + */ + protected function init() { + $this->data['objecttable'] = evidence::TABLE; + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_TEACHING; + } + + /** + * Get_objectid_mapping method. + * + * @return string the name of the restore mapping the objectid links to + */ + public static function get_objectid_mapping() { + return base::NOT_MAPPED; + } + + /** + * Validate the data. + * + * @throws \coding_exception + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->relateduserid)) { + throw new \coding_exception('The \'relateduserid\' must be set.'); + } + + if (!isset($this->other['usercompetencyid'])) { + throw new \coding_exception('The \'usercompetencyid\' data in \'other\' must be set.'); + } + + if (!isset($this->other['competencyid'])) { + throw new \coding_exception('The \'competencyid\' data in \'other\' must be set.'); + } + + if (!isset($this->other['action'])) { + throw new \coding_exception('The \'action\' data in \'other\' must be set.'); + } + + if (!isset($this->other['recommend'])) { + throw new \coding_exception('The \'recommend\' data in \'other\' must be set.'); + } + } +} diff --git a/admin/tool/lp/lang/en/tool_lp.php b/admin/tool/lp/lang/en/tool_lp.php index 4b58466fa25..66db1cbac4c 100644 --- a/admin/tool/lp/lang/en/tool_lp.php +++ b/admin/tool/lp/lang/en/tool_lp.php @@ -112,6 +112,7 @@ $string['eventcompetencycreated'] = 'Competency created.'; $string['eventcompetencydeleted'] = 'Competency deleted.'; $string['eventcompetencyupdated'] = 'Competency updated.'; $string['eventcompetencyviewed'] = 'Competency viewed.'; +$string['eventevidencecreated'] = 'Evidence created.'; $string['eventplanapproved'] = 'Plan approved.'; $string['eventplancompleted'] = 'Plan completed.'; $string['eventplancreated'] = 'Plan created.'; diff --git a/admin/tool/lp/tests/event_test.php b/admin/tool/lp/tests/event_test.php index 0715b9a1040..c8b769ce117 100644 --- a/admin/tool/lp/tests/event_test.php +++ b/admin/tool/lp/tests/event_test.php @@ -1295,4 +1295,163 @@ class tool_lp_event_testcase extends advanced_testcase { $this->assertEventContextNotUsed($event); $this->assertDebuggingNotCalled(); } + + /** + * Test evidence_created event. + */ + public function test_evidence_created() { + global $USER; + + $this->resetAfterTest(true); + $dg = $this->getDataGenerator(); + $syscontext = context_system::instance(); + + // Create a student. + $student = $dg->create_user(); + + // Create a competency for the course. + $lpg = $dg->get_plugin_generator('tool_lp'); + $framework = $lpg->create_framework(); + $comp = $lpg->create_competency(['competencyframeworkid' => $framework->get_id()]); + + // Trigger and capture the event. + $sink = $this->redirectEvents(); + + // Add evidence. + $recommend = false; + $evidence = api::add_evidence($student->id, $comp, $syscontext, \tool_lp\evidence::ACTION_SUGGEST, + 'commentincontext', 'core', null, $recommend, null, 1); + + // Get event. + $events = $sink->get_events(); + $event = reset($events); + + // Check that the event data is valid. + $this->assertInstanceOf('\tool_lp\event\evidence_created', $event); + $this->assertEquals($evidence->get_contextid(), $event->contextid); + $this->assertEquals($evidence->get_id(), $event->objectid); + $this->assertEquals($evidence->get_actionuserid(), $event->userid); + $this->assertEquals($student->id, $event->relateduserid); + $this->assertEquals($evidence->get_usercompetencyid(), $event->other['usercompetencyid']); + $this->assertEquals($comp->get_id(), $event->other['competencyid']); + $this->assertEquals($evidence->get_action(), $event->other['action']); + $this->assertEquals($recommend, $event->other['recommend']); + + // Test get_name(). + $this->assertEquals(get_string('eventevidencecreated', 'tool_lp'), $event->get_name()); + + // Test get_description(). + $description = "The user with id '$USER->id' created an evidence with id '{$evidence->get_id()}'."; + $this->assertEquals($description, $event->get_description()); + + // Test get_url(). + $url = new moodle_url('/admin/tool/lp/user_competency.php', ['id' => $evidence->get_usercompetencyid()]); + $this->assertEquals($url, $event->get_url()); + + // Test get_objectid_mapping(). + $this->assertEquals(\core\event\base::NOT_MAPPED, $event->get_objectid_mapping()); + + $this->assertEventContextNotUsed($event); + $this->assertDebuggingNotCalled(); + } + + /** + * Test evidence_created event by linking an invalid user competency to an evidence. + */ + public function test_evidence_created_with_invalid_user_competency() { + $this->resetAfterTest(true); + $dg = $this->getDataGenerator(); + $syscontext = context_system::instance(); + + // Create students. + $student = $dg->create_user(); + $student2 = $dg->create_user(); + + // Create a competency for the course. + $lpg = $dg->get_plugin_generator('tool_lp'); + $framework = $lpg->create_framework(); + $comp = $lpg->create_competency(['competencyframeworkid' => $framework->get_id()]); + + // Create a different user competency. + $otheruc = \tool_lp\user_competency::create_relation($student2->id, $comp->get_id()); + $otheruc->create(); + + // Add evidence. + $recommend = false; + $evidence = api::add_evidence($student->id, $comp, $syscontext, \tool_lp\evidence::ACTION_SUGGEST, + 'commentincontext', 'core', null, $recommend, null, 1); + + // We expect this to fail and throw a coding exception. + $this->setExpectedException('coding_exception', 'The user competency linked with this evidence is invalid.'); + \tool_lp\event\evidence_created::create_from_evidence($evidence, $otheruc, $recommend)->trigger(); + } + + /** + * Test creation of evidence_created event with missing data. + * + * These data are validated by \tool_lp\evidence_created::validate_data(). + */ + public function test_evidence_created_with_missing_data() { + $eventdata = [ + 'contextid' => 1, + 'objectid' => 1, + 'userid' => 1 + ]; + + // No relateduserid. + $errormsg = 'The \'relateduserid\' must be set.'; + try { + \tool_lp\event\evidence_created::create($eventdata)->trigger(); + $this->fail('Coding exception should have been thrown: ' . $errormsg); + } catch (coding_exception $e) { + $this->assertContains($errormsg, $e->getMessage()); + } + $eventdata['relateduserid'] = 1; + + // No other['usercompetencyid']. + $errormsg = 'The \'usercompetencyid\' data in \'other\' must be set.'; + try { + \tool_lp\event\evidence_created::create($eventdata)->trigger(); + $this->fail('Coding exception should have been thrown: ' . $errormsg); + } catch (coding_exception $e) { + $this->assertContains($errormsg, $e->getMessage()); + } + $eventdata['other']['usercompetencyid'] = 1; + + // No other['competencyid']. + $errormsg = 'The \'competencyid\' data in \'other\' must be set.'; + try { + \tool_lp\event\evidence_created::create($eventdata)->trigger(); + $this->fail('Coding exception should have been thrown: ' . $errormsg); + } catch (coding_exception $e) { + $this->assertContains($errormsg, $e->getMessage()); + } + $eventdata['other']['competencyid'] = 1; + + + // No other['action']. + $errormsg = 'The \'action\' data in \'other\' must be set.'; + try { + \tool_lp\event\evidence_created::create($eventdata)->trigger(); + $this->fail('Coding exception should have been thrown: ' . $errormsg); + } catch (coding_exception $e) { + $this->assertContains($errormsg, $e->getMessage()); + } + $eventdata['other']['action'] = 1; + + + // No other['recommend']. + $errormsg = 'The \'recommend\' data in \'other\' must be set.'; + try { + \tool_lp\event\evidence_created::create($eventdata)->trigger(); + $this->fail('Coding exception should have been thrown: ' . $errormsg); + } catch (coding_exception $e) { + $this->assertContains($errormsg, $e->getMessage()); + } + $eventdata['other']['recommend'] = 1; + + // Event should be triggered without any problems. + \tool_lp\event\evidence_created::create($eventdata)->trigger(); + } + }