From d76a0eec399c91fa81cff64ace3857aac0abd33e Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Tue, 6 Aug 2013 14:23:03 +0800 Subject: [PATCH 1/2] MDL-39962 - Events: Replace the legacy event workshop_viewed This also includes the abstract class course_module_viewed. --- .../allocation/scheduled/classes/observer.php | 82 ++++++++++++++ .../allocation/scheduled/db/events.php | 15 +-- mod/workshop/allocation/scheduled/lib.php | 47 -------- .../classes/event/course_module_viewed.php | 106 ++++++++++++++++++ mod/workshop/lang/en/workshop.php | 1 + mod/workshop/view.php | 34 +++--- 6 files changed, 214 insertions(+), 71 deletions(-) create mode 100644 mod/workshop/allocation/scheduled/classes/observer.php create mode 100644 mod/workshop/classes/event/course_module_viewed.php diff --git a/mod/workshop/allocation/scheduled/classes/observer.php b/mod/workshop/allocation/scheduled/classes/observer.php new file mode 100644 index 0000000000000..90ddfd6b8191a --- /dev/null +++ b/mod/workshop/allocation/scheduled/classes/observer.php @@ -0,0 +1,82 @@ +. + +/** + * Event observers for workshopallocation_scheduled. + * + * @package workshopallocation_scheduled + * @copyright 2013 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace workshopallocation_scheduled; +defined('MOODLE_INTERNAL') || die(); + +/** + * Class for workshopallocation_scheduled observers. + * + * @package workshopallocation_scheduled + * @copyright 2013 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class observer { + + /** + * Triggered when the '\mod_workshop\event\course_module_viewed' event is triggered. + * + * This does the same job as {@link workshopallocation_scheduled_cron()} but for the + * single workshop. The idea is that we do not need to wait for cron to execute. + * Displaying the workshop main view.php can trigger the scheduled allocation, too. + * + * @param \mod_workshop\event\course_module_viewed $event + * @return bool + */ + public static function workshop_viewed($event) { + global $DB; + + $workshop = $event->get_record_snapshot('workshop', $event->objectid); + $course = $event->get_record_snapshot('course', $event->courseid); + $cm = $event->get_record_snapshot('course_modules', $event->contextinstanceid); + + $workshop = new \workshop($workshop, $cm, $course); + $now = time(); + + // Non-expensive check to see if the scheduled allocation can even happen. + if ($workshop->phase == \workshop::PHASE_SUBMISSION and $workshop->submissionend > 0 and $workshop->submissionend < $now) { + + // Make sure the scheduled allocation has been configured for this workshop, that it has not + // been executed yet and that the passed workshop record is still valid. + $sql = "SELECT a.id + FROM {workshopallocation_scheduled} a + JOIN {workshop} w ON a.workshopid = w.id + WHERE w.id = :workshopid + AND a.enabled = 1 + AND w.phase = :phase + AND w.submissionend > 0 + AND w.submissionend < :now + AND (a.timeallocated IS NULL OR a.timeallocated < w.submissionend)"; + $params = array('workshopid' => $workshop->id, 'phase' => \workshop::PHASE_SUBMISSION, 'now' => $now); + + if ($DB->record_exists_sql($sql, $params)) { + // Allocate submissions for assessments. + $allocator = $workshop->allocator_instance('scheduled'); + $result = $allocator->execute(); + // Todo inform the teachers about the results. + } + } + return true; + } +} diff --git a/mod/workshop/allocation/scheduled/db/events.php b/mod/workshop/allocation/scheduled/db/events.php index d9137fc881ab5..33c0c1713bd97 100644 --- a/mod/workshop/allocation/scheduled/db/events.php +++ b/mod/workshop/allocation/scheduled/db/events.php @@ -27,14 +27,9 @@ defined('MOODLE_INTERNAL') || die(); -$handlers = array( - - // The workshop main page is displayed to the user - 'workshop_viewed' => array( - 'handlerfile' => '/mod/workshop/allocation/scheduled/lib.php', - 'handlerfunction' => 'workshopallocation_scheduled_workshop_viewed', - 'schedule' => 'instant', - 'internal' => 1, - ), - +$observers = array( + array( + 'eventname' => '\mod_workshop\event\course_module_viewed', + 'callback' => '\workshopallocation_scheduled\observer::workshop_viewed', + ) ); diff --git a/mod/workshop/allocation/scheduled/lib.php b/mod/workshop/allocation/scheduled/lib.php index 8809e93def272..11095a97b584a 100644 --- a/mod/workshop/allocation/scheduled/lib.php +++ b/mod/workshop/allocation/scheduled/lib.php @@ -285,50 +285,3 @@ function workshopallocation_scheduled_cron() { // todo inform the teachers about the results } } - -//////////////////////////////////////////////////////////////////////////////// -// Events API -//////////////////////////////////////////////////////////////////////////////// - -/** - * Handler for the 'workshop_viewed' event - * - * This does the same job as {@link workshopallocation_scheduled_cron()} but for the - * single workshop. The idea is that we do not need to wait forcron to execute. - * Displaying the workshop main view.php can trigger the scheduled allocation, too. - * - * @param stdClass $event event data - * @return bool - */ -function workshopallocation_scheduled_workshop_viewed($event) { - global $DB; - - $workshop = $event->workshop; - $now = time(); - - // Non-expensive check to see if the scheduled allocation can even happen. - if ($workshop->phase == workshop::PHASE_SUBMISSION and $workshop->submissionend > 0 and $workshop->submissionend < $now) { - - // Make sure the scheduled allocation has been configured for this workshop, that it has not - // been executed yet and that the passed workshop record is still valid. - $sql = "SELECT a.id - FROM {workshopallocation_scheduled} a - JOIN {workshop} w ON a.workshopid = w.id - WHERE w.id = :workshopid - AND a.enabled = 1 - AND w.phase = :phase - AND w.submissionend > 0 - AND w.submissionend < :now - AND (a.timeallocated IS NULL OR a.timeallocated < w.submissionend)"; - $params = array('workshopid' => $workshop->id, 'phase' => workshop::PHASE_SUBMISSION, 'now' => $now); - - if ($DB->record_exists_sql($sql, $params)) { - // Allocate submissions for assessments. - $allocator = $workshop->allocator_instance('scheduled'); - $result = $allocator->execute(); - // todo inform the teachers about the results - } - } - - return true; -} diff --git a/mod/workshop/classes/event/course_module_viewed.php b/mod/workshop/classes/event/course_module_viewed.php new file mode 100644 index 0000000000000..88226cdd6ffb2 --- /dev/null +++ b/mod/workshop/classes/event/course_module_viewed.php @@ -0,0 +1,106 @@ +. + +/** + * This file contains an event for when a workshop activity is viewed. + * + * @package mod_workshop + * @copyright 2013 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_workshop\event; +defined('MOODLE_INTERNAL') || die(); + +/** + * Event for when a workshop activity is viewed. + * + * @package mod_workshop + * @copyright 2013 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class course_module_viewed extends \core\event\content_viewed { + + /** + * Init method. + */ + protected function init() { + $this->data['crud'] = 'r'; + $this->data['level'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'workshop'; + } + + /** + * Does this event replace a legacy event? + * + * @return string legacy event name + */ + public static function get_legacy_eventname() { + return 'workshop_viewed'; + } + + /** + * Returns non-localised description of what happened. + * + * @return string + */ + public function get_description() { + return 'User with id ' . $this->userid . ' viewed content ' . $this->get_url() . ' In phase ' . $this->other['content']; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('workshopviewed', 'workshop'); + } + + /** + * Returns relevant URL. + * @return \moodle_url + */ + public function get_url() { + $url = '/mod/workshop/view.php'; + return new \moodle_url($url, array('id'=>$this->context->instanceid)); + } + + /** + * Legacy event data if get_legacy_eventname() is not empty. + * + * @return mixed + */ + protected function get_legacy_eventdata() { + global $USER; + + $workshop = $this->get_record_snapshot('workshop', $this->objectid); + $course = $this->get_record_snapshot('course', $this->courseid); + $cm = $this->get_record_snapshot('course_modules', $this->context->instanceid); + $workshop = new \workshop($workshop, $cm, $course); + return (object)array('workshop' => $workshop, 'user' => $USER); + } + + /** + * replace add_to_log() statement. + * + * @return array of parameters to be passed to legacy add_to_log() function. + */ + protected function get_legacy_logdata() { + $url = new \moodle_url('view.php', array('id' => $this->context->instanceid)); + return array($this->courseid, 'workshop', 'view', $url->out(), $this->objectid, $this->context->instanceid); + } +} diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php index 9c99b1e92968f..ef53bf0e3e9d3 100644 --- a/mod/workshop/lang/en/workshop.php +++ b/mod/workshop/lang/en/workshop.php @@ -311,6 +311,7 @@ $string['workshop:viewauthorpublished'] = 'View authors of published submissions'; $string['workshop:viewpublishedsubmissions'] = 'View published submissions'; $string['workshop:viewreviewernames'] = 'View reviewer names'; +$string['workshopviewed'] = 'Workshop viewed'; $string['yourassessment'] = 'Your assessment'; $string['yourgrades'] = 'Your grades'; $string['yoursubmission'] = 'Your submission'; diff --git a/mod/workshop/view.php b/mod/workshop/view.php index 7272cfc964f0b..dfa245f2be141 100644 --- a/mod/workshop/view.php +++ b/mod/workshop/view.php @@ -41,30 +41,37 @@ $eval = optional_param('eval', null, PARAM_PLUGIN); if ($id) { - $cm = get_coursemodule_from_id('workshop', $id, 0, false, MUST_EXIST); - $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); - $workshop = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST); + $cm = get_coursemodule_from_id('workshop', $id, 0, false, MUST_EXIST); + $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST); + $workshoprecord = $DB->get_record('workshop', array('id' => $cm->instance), '*', MUST_EXIST); } else { - $workshop = $DB->get_record('workshop', array('id' => $w), '*', MUST_EXIST); - $course = $DB->get_record('course', array('id' => $workshop->course), '*', MUST_EXIST); - $cm = get_coursemodule_from_instance('workshop', $workshop->id, $course->id, false, MUST_EXIST); + $workshoprecord = $DB->get_record('workshop', array('id' => $w), '*', MUST_EXIST); + $course = $DB->get_record('course', array('id' => $workshoprecord->course), '*', MUST_EXIST); + $cm = get_coursemodule_from_instance('workshop', $workshoprecord->id, $course->id, false, MUST_EXIST); } require_login($course, true, $cm); require_capability('mod/workshop:view', $PAGE->context); -$workshop = new workshop($workshop, $cm, $course); -$workshop->log('view'); +$workshop = new workshop($workshoprecord, $cm, $course); // Mark viewed $completion = new completion_info($course); $completion->set_module_viewed($cm); -// Fire the event -events_trigger('workshop_viewed', (object)array( - 'workshop' => $workshop, - 'user' => $USER, -)); +$eventdata = array(); +$eventdata['objectid'] = $workshop->id; +$eventdata['context'] = $workshop->context; +$eventdata['courseid'] = $course->id; +$eventdata['other']['content'] = $workshop->phase; + +$PAGE->set_url($workshop->view_url()); +$event = \mod_workshop\event\course_module_viewed::create($eventdata); +$event->add_record_snapshot('course', $course); +$event->add_record_snapshot('workshop', $workshoprecord); +$event->add_record_snapshot('course_modules', $cm); +$event->set_page_detail(); +$event->trigger(); // If the phase is to be switched, do it asap. This just has to happen after triggering // the event so that the scheduled allocator had a chance to allocate submissions. @@ -82,7 +89,6 @@ $USER->editing = $editmode; } -$PAGE->set_url($workshop->view_url()); $PAGE->set_title($workshop->name); $PAGE->set_heading($course->fullname); From b97d94ffbb5b8ce2c4f275d7d6ed3d778149bd46 Mon Sep 17 00:00:00 2001 From: Adrian Greeve Date: Mon, 12 Aug 2013 11:38:39 +0800 Subject: [PATCH 2/2] MDL-39962 - Events: Replace lefacy event lti_unknown_service_api call. --- .../event/unknown_service_api_called.php | 95 +++++++++++++++++++ mod/lti/lang/en/lti.php | 1 + mod/lti/service.php | 18 ++-- 3 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 mod/lti/classes/event/unknown_service_api_called.php diff --git a/mod/lti/classes/event/unknown_service_api_called.php b/mod/lti/classes/event/unknown_service_api_called.php new file mode 100644 index 0000000000000..dad8f78bdb636 --- /dev/null +++ b/mod/lti/classes/event/unknown_service_api_called.php @@ -0,0 +1,95 @@ +. + +/** + * This file contains an event for an unknown service API call. + * + * @package mod_lti + * @copyright 2013 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_lti\event; +defined('MOODLE_INTERNAL') || die(); + +/** + * Event for when something happens with an unknown lti service API call. + * + * @package mod_lti + * @copyright 2013 Adrian Greeve + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class unknown_service_api_called extends \core\event\base { + + /** Old data to be used for the legacy event. */ + protected $legacydata; + + /** + * Set method for legacy data. + * + * @param stdClass $data legacy event data. + */ + public function set_legacy_data($data) { + $this->legacydata = $data; + } + + /** + * Init method. + */ + protected function init() { + $this->data['objecttable'] = 'lti'; + $this->data['crud'] = 'r'; + $this->data['level'] = self::LEVEL_OTHER; + $this->data['context'] = \context_system::instance(); + } + + /** + * Returns localised description of what happened. + * + * @return string + */ + public function get_description() { + return 'An unknown call to a service api was made.'; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('ltiunknownserviceapicall', 'mod_lti'); + } + + /** + * Does this event replace a legacy event? + * + * @return null|string legacy event name + */ + public static function get_legacy_eventname() { + return 'lti_unknown_service_api_call'; + } + + /** + * Legacy event data if get_legacy_eventname() is not empty. + * + * @return mixed + */ + protected function get_legacy_eventdata() { + return $this->legacydata; + } + +} diff --git a/mod/lti/lang/en/lti.php b/mod/lti/lang/en/lti.php index 606e2d6110af7..7f5f8a3451283 100644 --- a/mod/lti/lang/en/lti.php +++ b/mod/lti/lang/en/lti.php @@ -237,6 +237,7 @@

'; $string['lti_tool_request_added'] = 'Tool configuration request successfully submitted. You may need to contact an administrator to complete the tool configuration.'; $string['lti_tool_request_existing'] = 'A tool configuration for the tool domain has already been submitted.'; +$string['ltiunknownserviceapicall'] = 'LTI unknown service API call.'; $string['main_admin'] = 'General help'; $string['main_admin_help'] = 'External tools allow Moodle users to seamlessly interact with learning resources hosted remotely. Through a special launch protocol, the remote tool will have access to some general information about the launching user. For example, diff --git a/mod/lti/service.php b/mod/lti/service.php index b96f566294e5f..be8e2d6d38624 100644 --- a/mod/lti/service.php +++ b/mod/lti/service.php @@ -145,19 +145,23 @@ //Fire an event if we get a web service request which we don't support directly. //This will allow others to extend the LTI services, which I expect to be a common //use case, at least until the spec matures. - $data = new stdClass(); - $data->body = $rawbody; - $data->xml = $xml; - $data->messagetype = $messagetype; - $data->consumerkey = $consumerkey; - $data->sharedsecret = $sharedsecret; + // Please note that you will have to change $eventdata['other']['body'] into an xml + // element in an event observer as done above. + $eventdata = array(); + $eventdata['other'] = array(); + $eventdata['other']['body'] = $rawbody; + $eventdata['other']['messagetype'] = $messagetype; + $eventdata['other']['consumerkey'] = $consumerkey; + $eventdata['other']['sharedsecret'] = $sharedsecret; //If an event handler handles the web service, it should set this global to true //So this code knows whether to send an "operation not supported" or not. global $lti_web_service_handled; $lti_web_service_handled = false; - events_trigger('lti_unknown_service_api_call', $data); + $event = \mod_lti\event\unknown_service_api_called::create($eventdata); + $event->set_legacy_data($eventdata); + $event->trigger(); if (!$lti_web_service_handled) { $responsexml = lti_get_response_xml(