From 20e1e4bd914390079cbc37fd480a27c14c9b63fd Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 31 Aug 2016 11:06:35 +0800 Subject: [PATCH] Add events to track usage Fixes #13 Fixes #14 --- amd/build/usertours.min.js | 2 +- amd/src/usertours.js | 46 ++++++-- classes/event/step_shown.php | 123 ++++++++++++++++++++ classes/event/tour_ended.php | 123 ++++++++++++++++++++ classes/event/tour_reset.php | 110 ++++++++++++++++++ classes/event/tour_started.php | 109 +++++++++++++++++ classes/external/tour.php | 206 ++++++++++++++++++++++++++------- db/services.php | 10 ++ lang/en/local_usertours.php | 4 + 9 files changed, 680 insertions(+), 53 deletions(-) create mode 100644 classes/event/step_shown.php create mode 100644 classes/event/tour_ended.php create mode 100644 classes/event/tour_reset.php create mode 100644 classes/event/tour_started.php diff --git a/amd/build/usertours.min.js b/amd/build/usertours.min.js index 413c571..09397eb 100644 --- a/amd/build/usertours.min.js +++ b/amd/build/usertours.min.js @@ -1 +1 @@ -define(["core/ajax","local_usertours/bootstrap-tour","jquery","core/templates","core/str"],function(a,b,c,d,e){var f={tourId:null,currentTour:null,context:null,init:function(a,b,d){f.tourId=a,f.context=d,"undefined"==typeof b&&(b=!0),b&&f.fetchTour(a),f.addResetLink(),c("body").on("click",'[data-action="local_usertours/resetpagetour"]',function(a){a.preventDefault(),f.resetTourState(f.tourId)})},fetchTour:function(b){c.when(a.call([{methodname:"local_usertours_fetch_tour",args:{tourid:b,context:f.context}}])[0],d.render("local_usertours/tourstep",{})).then(function(a,c){f.startBootstrapTour(b,c[0],a.tourConfig)})},addResetLink:function(){e.get_string("resettouronpage","local_usertours").done(function(a){c("footer, .logininfo").last().append('
'+a+"
")})},startBootstrapTour:function(a,c,d){f.currentTour&&(d.onEnd=null,f.currentTour.end()),d.onEnd=f.markTourComplete,d.template=c,f.currentTour=new b(d),f.currentTour.init(!0),f.currentTour.start(!0)},markTourComplete:function(){a.call([{methodname:"local_usertours_complete_tour",args:{tourid:f.tourId}}])},resetTourState:function(b){a.call([{methodname:"local_usertours_reset_tour",args:{path:window.location.href,tourid:b},done:function(a){a.startTour&&f.fetchTour(a.startTour)}}])}};return{init:f.init,resetTourState:f.resetTourState}}); \ No newline at end of file +define(["core/ajax","local_usertours/bootstrap-tour","jquery","core/templates","core/str"],function(a,b,c,d,e){var f={tourId:null,currentTour:null,context:null,init:function(a,b,d){f.tourId=a,f.context=d,"undefined"==typeof b&&(b=!0),b&&f.fetchTour(a),f.addResetLink(),c("body").on("click",'[data-action="local_usertours/resetpagetour"]',function(a){a.preventDefault(),f.resetTourState(f.tourId)})},fetchTour:function(b){c.when(a.call([{methodname:"local_usertours_fetch_tour",args:{tourid:b,context:f.context,pageurl:window.location.href}}])[0],d.render("local_usertours/tourstep",{})).then(function(a,c){f.startBootstrapTour(b,c[0],a.tourConfig)})},addResetLink:function(){e.get_string("resettouronpage","local_usertours").done(function(a){c("footer, .logininfo").last().append('
'+a+"
")})},startBootstrapTour:function(a,c,d){f.currentTour&&(d.onEnd=null,f.currentTour.end()),d.onEnd=f.markTourComplete,d.onShown=f.markStepShown,d.template=c,f.currentTour=new b(d),f.currentTour.init(!0),f.currentTour.start(!0)},markStepShown:function(b){a.call([{methodname:"local_usertours_step_shown",args:{tourid:f.tourId,context:f.context,pageurl:window.location.href,stepid:b.getStep(b.getCurrentStep()).stepid,stepindex:b.getCurrentStep()}}])},markTourComplete:function(b){a.call([{methodname:"local_usertours_complete_tour",args:{tourid:f.tourId,context:f.context,pageurl:window.location.href,stepid:b.getStep(b.getCurrentStep()).stepid,stepindex:b.getCurrentStep()}}])},resetTourState:function(b){a.call([{methodname:"local_usertours_reset_tour",args:{tourid:b,context:f.context,pageurl:window.location.href},done:function(a){a.startTour&&f.fetchTour(a.startTour)}}])}};return{init:f.init,resetTourState:f.resetTourState}}); \ No newline at end of file diff --git a/amd/src/usertours.js b/amd/src/usertours.js index 3c04091..c798995 100644 --- a/amd/src/usertours.js +++ b/amd/src/usertours.js @@ -50,8 +50,9 @@ function(ajax, BootstrapTour, $, templates, str) { { methodname: 'local_usertours_fetch_tour', args: { - tourid: tourId, - context: usertours.context + tourid: tourId, + context: usertours.context, + pageurl: window.location.href, } } ])[0], @@ -88,12 +89,16 @@ function(ajax, BootstrapTour, $, templates, str) { */ startBootstrapTour: function(tourId, template, tourConfig) { if (usertours.currentTour) { + // End the current tour, but disable end tour handler. tourConfig.onEnd = null; usertours.currentTour.end(); } + + // Add the various handlers. tourConfig.onEnd = usertours.markTourComplete; + tourConfig.onShown = usertours.markStepShown; - // Add the templtae to the configuration. + // Add the template to the configuration. // This enables translations of the buttons. tourConfig.template = template; @@ -103,17 +108,41 @@ function(ajax, BootstrapTour, $, templates, str) { usertours.currentTour.start(true); }, + /** + * Mark the specified step as being shownd by the user. + * + * @param Tour tour The data from the step. + */ + markStepShown: function(tour) { + ajax.call([ + { + methodname: 'local_usertours_step_shown', + args: { + tourid: usertours.tourId, + context: usertours.context, + pageurl: window.location.href, + stepid: tour.getStep(tour.getCurrentStep()).stepid, + stepindex: tour.getCurrentStep(), + } + } + ]); + }, + /** * Mark the specified tour as being completed by the user. * - * @param int tourId The ID of the tour to mark complete. + * @param Tour our The data from the tour. */ - markTourComplete: function() { + markTourComplete: function(tour) { ajax.call([ { methodname: 'local_usertours_complete_tour', args: { - tourid: usertours.tourId + tourid: usertours.tourId, + context: usertours.context, + pageurl: window.location.href, + stepid: tour.getStep(tour.getCurrentStep()).stepid, + stepindex: tour.getCurrentStep(), } } ]); @@ -127,8 +156,9 @@ function(ajax, BootstrapTour, $, templates, str) { { methodname: 'local_usertours_reset_tour', args: { - path: window.location.href, - tourid: tourId + tourid: tourId, + context: usertours.context, + pageurl: window.location.href, }, done: function(response) { if (response.startTour) { diff --git a/classes/event/step_shown.php b/classes/event/step_shown.php new file mode 100644 index 0000000..f953569 --- /dev/null +++ b/classes/event/step_shown.php @@ -0,0 +1,123 @@ +. + +/** + * The local_usertours step_shown event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_usertours\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The local_usertours step_shown event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @property-read array $other { + * Extra information about the event. + * + * - int tourid: The id of the tour + * - string pageurl: The URL of the page viewing the tour + * } + */ +class step_shown extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'usertours_steps'; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('event_step_shown', 'local_usertours'); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->other['tourid'])) { + throw new \coding_exception('The \'tourid\' value must be set in other.'); + } + + if (!isset($this->other['stepindex'])) { + throw new \coding_exception('The \'stepindex\' value must be set in other.'); + } + + if (!isset($this->other['pageurl'])) { + throw new \coding_exception('The \'pageurl\' value must be set in other.'); + } + } + + public static function get_other_mapping() { + return [ + 'pageurl' => \core\event\base::NOT_MAPPED, + 'tourid' => [ + 'db' => 'usertours_tours', + 'restore' => \core\event\base::NOT_MAPPED, + ], + 'stepindex' => \core\event\base::NOT_MAPPED, + ]; + } + + public static function get_objectid_mapping() { + return [ + 'db' => 'usertours_steps', + 'restore' => \core\event\base::NOT_MAPPED, + ]; + } + + /** + * Returns non-localised event description with id's for admin use only. + * + * @return string + */ + public function get_description() { + return "The user with id '{$this->userid}' has viewed the tour with id " . + "'{$this->other['tourid']}' at step index " . + "'{$this->other['stepindex']}' (id '{$this->objectid}') on the page with URL " . + "'{$this->other['pageurl']}'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return \local_usertours\helper::get_edit_step_link($this->other['tourid'], $this->objectid); + } +} diff --git a/classes/event/tour_ended.php b/classes/event/tour_ended.php new file mode 100644 index 0000000..a8186b9 --- /dev/null +++ b/classes/event/tour_ended.php @@ -0,0 +1,123 @@ +. + +/** + * The local_usertours tour_ended event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_usertours\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The local_usertours tour_ended event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @property-read array $other { + * Extra information about the event. + * + * - int tourid: The id of the tour + * - string pageurl: The URL of the page viewing the tour + * } + */ +class tour_ended extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'usertours_tours'; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('event_tour_ended', 'local_usertours'); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->other['stepindex'])) { + throw new \coding_exception('The \'stepindex\' value must be set in other.'); + } + + if (!isset($this->other['stepid'])) { + throw new \coding_exception('The \'stepid\' value must be set in other.'); + } + + if (!isset($this->other['pageurl'])) { + throw new \coding_exception('The \'pageurl\' value must be set in other.'); + } + } + + public static function get_other_mapping() { + return [ + 'stepindex' => \core\event\base::NOT_MAPPED, + 'stepid' => [ + 'db' => 'usertours_steps', + 'restore' => \core\event\base::NOT_MAPPED, + ], + 'pageurl' => \core\event\base::NOT_MAPPED, + ]; + } + + public static function get_objectid_mapping() { + return [ + 'db' => 'usertours_tours', + 'restore' => \core\event\base::NOT_MAPPED, + ]; + } + + /** + * Returns non-localised event description with id's for admin use only. + * + * @return string + */ + public function get_description() { + return "The user with id '{$this->userid}' has ended the tour with id " . + "'{$this->objectid}' at step index " . + "'{$this->other['stepindex']}' (id '{$this->other['stepid']}') on the page with URL " . + "'{$this->other['pageurl']}'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return \local_usertours\helper::get_view_tour_link($this->objectid); + } +} diff --git a/classes/event/tour_reset.php b/classes/event/tour_reset.php new file mode 100644 index 0000000..6aa3845 --- /dev/null +++ b/classes/event/tour_reset.php @@ -0,0 +1,110 @@ +. + +/** + * The local_usertours tour_reset event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_usertours\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The local_usertours tour_reset event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @property-read array $other { + * Extra information about the event. + * + * - int tourid: The id of the tour + * - string pageurl: The URL of the page viewing the tour + * } + */ +class tour_reset extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'usertours_tours'; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('event_tour_reset', 'local_usertours'); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->other['pageurl'])) { + throw new \coding_exception('The \'pageurl\' value must be set in other.'); + } + } + + public static function get_other_mapping() { + return [ + 'pageurl' => \core\event\base::NOT_MAPPED, + ]; + } + + public static function get_objectid_mapping() { + return [ + 'db' => 'usertours_tours', + 'restore' => \core\event\base::NOT_MAPPED, + ]; + } + + /** + * Returns non-localised event description with id's for admin use only. + * + * @return string + */ + public function get_description() { + return "The user with id " . + "'{$this->userid}' has reset the state of tour with id " . + "'{$this->objectid}' on the page with URL " . + "'{$this->other['pageurl']}'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return \local_usertours\helper::get_view_tour_link($this->objectid); + } +} diff --git a/classes/event/tour_started.php b/classes/event/tour_started.php new file mode 100644 index 0000000..f839c4a --- /dev/null +++ b/classes/event/tour_started.php @@ -0,0 +1,109 @@ +. + +/** + * The local_usertours tour_started event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace local_usertours\event; + +defined('MOODLE_INTERNAL') || die(); + +/** + * The local_usertours tour_started event. + * + * @package local_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * + * @property-read array $other { + * Extra information about the event. + * + * - int tourid: The id of the tour + * - string pageurl: The URL of the page viewing the tour + * } + */ +class tour_started extends \core\event\base { + + /** + * Init method. + */ + protected function init() { + $this->data['crud'] = 'c'; + $this->data['edulevel'] = self::LEVEL_PARTICIPATING; + $this->data['objecttable'] = 'usertours_tours'; + } + + /** + * Returns localised general event name. + * + * @return string + */ + public static function get_name() { + return get_string('event_tour_started', 'local_usertours'); + } + + /** + * Custom validation. + * + * @throws \coding_exception + * @return void + */ + protected function validate_data() { + parent::validate_data(); + + if (!isset($this->other['pageurl'])) { + throw new \coding_exception('The \'pageurl\' value must be set in other.'); + } + } + + public static function get_other_mapping() { + return [ + 'pageurl' => \core\event\base::NOT_MAPPED, + ]; + } + + public static function get_objectid_mapping() { + return [ + 'db' => 'usertours_tours', + 'restore' => \core\event\base::NOT_MAPPED, + ]; + } + + /** + * Returns non-localised event description with id's for admin use only. + * + * @return string + */ + public function get_description() { + return "The user with id '{$this->userid}' " . + "has started the tour with '{$this->objectid}' " . + "on the page with URL '{$this->other['pageurl']}'."; + } + + /** + * Returns relevant URL. + * + * @return \moodle_url + */ + public function get_url() { + return \local_usertours\helper::get_view_tour_link($this->objectid); + } +} diff --git a/classes/external/tour.php b/classes/external/tour.php index 752cc28..58b32b9 100644 --- a/classes/external/tour.php +++ b/classes/external/tour.php @@ -43,18 +43,20 @@ class tour extends external_api { * * @param int $tourid The ID of the tour to fetch. * @param int $context The Context ID of the current page. + * @param string $pageurl The path of the current page. * @return array As described in fetch_tour_returns */ - public static function fetch_tour($tourid, $context) { + public static function fetch_tour($tourid, $context, $pageurl) { global $PAGE; - $context = \context_helper::instance_by_id($context); - self::validate_context($context); - $params = self::validate_parameters(self::fetch_tour_parameters(), [ - 'tourid' => $tourid, - 'context' => $context->id, - ]); + 'tourid' => $tourid, + 'context' => $context, + 'pageurl' => $pageurl, + ]); + + $context = \context_helper::instance_by_id($params['context']); + self::validate_context($context); $tour = tourinstance::instance($params['tourid']); if (!$tour->should_show_for_user()) { @@ -63,6 +65,14 @@ public static function fetch_tour($tourid, $context) { $touroutput = new \local_usertours\output\tour($tour); + \local_usertours\event\tour_started::create([ + 'contextid' => $context->id, + 'objectid' => $tourid, + 'other' => [ + 'pageurl' => $pageurl, + ], + ])->trigger(); + return [ 'tourConfig' => $touroutput->export_for_template($PAGE->get_renderer('core')), ]; @@ -75,8 +85,9 @@ public static function fetch_tour($tourid, $context) { */ public static function fetch_tour_parameters() { return new external_function_parameters([ - 'tourid' => new external_value(PARAM_INT, 'Tour ID'), - 'context' => new external_value(PARAM_INT, 'Context ID'), + 'tourid' => new external_value(PARAM_INT, 'Tour ID'), + 'context' => new external_value(PARAM_INT, 'Context ID'), + 'pageurl' => new external_value(PARAM_URL, 'Page URL'), ]); } @@ -89,26 +100,7 @@ public static function fetch_tour_returns() { return new external_single_structure([ 'tourConfig' => new external_single_structure([ 'name' => new external_value(PARAM_RAW, 'Tour ID'), - 'steps' => new external_multiple_structure( - new external_single_structure([ - 'title' => new external_value(PARAM_TEXT, - 'Step Title'), - 'content' => new external_value(PARAM_RAW, - 'Step Content'), - 'element' => new external_value(PARAM_TEXT, - 'Step Target'), - 'placement' => new external_value(PARAM_TEXT, - 'Step Placement'), - 'delay' => new external_value(PARAM_INT, - 'Delay before showing the step (ms)', VALUE_OPTIONAL), - 'backdrop' => new external_value(PARAM_BOOL, - 'Whether a backdrop should be used', VALUE_OPTIONAL), - 'reflex' => new external_value(PARAM_BOOL, - 'Whether to move to the next step when the target element is clicked', VALUE_OPTIONAL), - 'orphan' => new external_value(PARAM_BOOL, - 'Whether to display the step even if it could not be found', VALUE_OPTIONAL), - ]) - ), + 'steps' => new external_multiple_structure(self::step_structure_returns()), ]) ]); } @@ -116,23 +108,38 @@ public static function fetch_tour_returns() { /** * Reset the specified tour for the current user. * - * @param string $path The path of the current page requesting the reset. * @param int $tourid The ID of the tour. + * @param int $context The Context ID of the current page. + * @param string $pageurl The path of the current page requesting the reset. * @return array As described in reset_tour_returns */ - public static function reset_tour($path, $tourid) { - global $PAGE; - $PAGE->set_context(\context_system::instance()); - self::validate_context($PAGE->context); + public static function reset_tour($tourid, $context, $pageurl) { + $params = self::validate_parameters(self::reset_tour_parameters(), [ + 'tourid' => $tourid, + 'context' => $context, + 'pageurl' => $pageurl, + ]); - $tour = tourinstance::instance($tourid); + $context = \context_helper::instance_by_id($params['context']); + self::validate_context($context); + + $tour = tourinstance::instance($params['tourid']); $tour->request_user_reset(); $result = []; - if ($tourinstance = \local_usertours\manager::get_matching_tours(new \moodle_url($path))) { + if ($tourinstance = \local_usertours\manager::get_matching_tours(new \moodle_url($params['pageurl']))) { if ($tour->get_id() === $tourinstance->get_id()) { $result['startTour'] = $tour->get_id(); + + \local_usertours\event\tour_reset::create([ + 'contextid' => $context->id, + 'objectid' => $params['tourid'], + 'other' => [ + 'pageurl' => $params['pageurl'], + ], + ])->trigger(); + } } @@ -146,8 +153,9 @@ public static function reset_tour($path, $tourid) { */ public static function reset_tour_parameters() { return new external_function_parameters([ - 'path' => new external_value(PARAM_URL, 'Current page location'), 'tourid' => new external_value(PARAM_INT, 'Tour ID'), + 'context' => new external_value(PARAM_INT, 'Context ID'), + 'pageurl' => new external_value(PARAM_URL, 'Current page location'), ]); } @@ -168,26 +176,48 @@ public static function reset_tour_returns() { * @param int $tourid The ID of the tour. * @return array As described in complete_tour_returns */ - public static function complete_tour($tourid) { - global $PAGE; - $PAGE->set_context(\context_system::instance()); - self::validate_context($PAGE->context); + public static function complete_tour($tourid, $context, $pageurl, $stepid, $stepindex) { require_login(); - $tour = tourinstance::instance($tourid); + $params = self::validate_parameters(self::complete_tour_parameters(), [ + 'tourid' => $tourid, + 'context' => $context, + 'pageurl' => $pageurl, + 'stepid' => $stepid, + 'stepindex' => $stepindex, + ]); + + $context = \context_helper::instance_by_id($params['context']); + self::validate_context($context); + + $tour = tourinstance::instance($params['tourid']); $tour->mark_user_completed(); + \local_usertours\event\tour_ended::create([ + 'contextid' => $context->id, + 'objectid' => $params['tourid'], + 'other' => [ + 'pageurl' => $params['pageurl'], + 'stepid' => $params['stepid'], + 'stepindex' => $params['stepindex'], + ], + ])->trigger(); + return []; } /** - * The parameters for complete_tour f. + * The parameters for complete_tour. * * @return external_function_parameters */ public static function complete_tour_parameters() { return new external_function_parameters([ - 'tourid' => new external_value(PARAM_INT, 'Tour ID'), + 'tourid' => new external_value(PARAM_INT, 'Tour ID'), + 'context' => new external_value(PARAM_INT, 'Context ID'), + 'pageurl' => new external_value(PARAM_URL, 'Page URL'), + 'stepid' => new external_value(PARAM_INT, 'Step ID'), + 'stepindex' => new external_value(PARAM_INT, 'Step Number'), ]); } @@ -199,4 +229,92 @@ public static function complete_tour_parameters() { public static function complete_tour_returns() { return new external_single_structure([]); } + + /** + * Mark the specified toru step as shown for the current user. + * + * @param int $tourid The ID of the tour. + * @param int $context The Context ID of the current page. + * @param string $pageurl The path of the current page. + * @param int $stepindex The step index + * @return array As described in complete_tour_returns + */ + public static function step_shown($tourid, $context, $pageurl, $stepid, $stepindex) { + require_login(); + + $params = self::validate_parameters(self::step_shown_parameters(), [ + 'tourid' => $tourid, + 'context' => $context, + 'pageurl' => $pageurl, + 'stepid' => $stepid, + 'stepindex' => $stepindex, + ]); + + $context = \context_helper::instance_by_id($params['context']); + self::validate_context($context); + + \local_usertours\event\step_shown::create([ + 'contextid' => $context->id, + 'objectid' => $params['stepid'], + 'other' => [ + 'pageurl' => $params['pageurl'], + 'tourid' => $params['tourid'], + 'stepindex' => $params['stepindex'], + ], + ])->trigger(); + + return []; + } + + /** + * The parameters for step_shown. + * + * @return external_function_parameters + */ + public static function step_shown_parameters() { + return new external_function_parameters([ + 'tourid' => new external_value(PARAM_INT, 'Tour ID'), + 'context' => new external_value(PARAM_INT, 'Context ID'), + 'pageurl' => new external_value(PARAM_URL, 'Page URL'), + 'stepid' => new external_value(PARAM_INT, 'Step ID'), + 'stepindex' => new external_value(PARAM_INT, 'Step Number'), + ]); + } + + /** + * The return configuration for step_shown. + * + * @return external_single_structure + */ + public static function step_shown_returns() { + return new external_single_structure([]); + } + + /** + * The standard return structure for a step. + * + * @return external_multiple_structure + */ + public static function step_structure_returns() { + return new external_single_structure([ + 'title' => new external_value(PARAM_TEXT, + 'Step Title'), + 'content' => new external_value(PARAM_RAW, + 'Step Content'), + 'element' => new external_value(PARAM_TEXT, + 'Step Target'), + 'placement' => new external_value(PARAM_TEXT, + 'Step Placement'), + 'delay' => new external_value(PARAM_INT, + 'Delay before showing the step (ms)', VALUE_OPTIONAL), + 'backdrop' => new external_value(PARAM_BOOL, + 'Whether a backdrop should be used', VALUE_OPTIONAL), + 'reflex' => new external_value(PARAM_BOOL, + 'Whether to move to the next step when the target element is clicked', VALUE_OPTIONAL), + 'orphan' => new external_value(PARAM_BOOL, + 'Whether to display the step even if it could not be found', VALUE_OPTIONAL), + 'stepid' => new external_value(PARAM_INT, + 'The actual ID of the step', VALUE_OPTIONAL), + ]); + } } diff --git a/db/services.php b/db/services.php index 9caf214..6e866d0 100644 --- a/db/services.php +++ b/db/services.php @@ -48,6 +48,15 @@ 'ajax' => true, ), + 'local_usertours_step_shown' => array( + 'classname' => 'local_usertours\external\tour', + 'methodname' => 'step_shown', + 'description' => 'Mark the specified step as completed for the current user', + 'type' => 'write', + 'capabilities' => '', + 'ajax' => true, + ), + 'local_usertours_complete_tour' => array( 'classname' => 'local_usertours\external\tour', 'methodname' => 'complete_tour', @@ -56,6 +65,7 @@ 'capabilities' => '', 'ajax' => true, ), + 'local_usertours_reset_tour' => array( 'classname' => 'local_usertours\external\tour', 'methodname' => 'reset_tour', diff --git a/lang/en/local_usertours.php b/lang/en/local_usertours.php index 0698cee..285c5e4 100644 --- a/lang/en/local_usertours.php +++ b/lang/en/local_usertours.php @@ -146,3 +146,7 @@ '; $string['sharedtourslink'] = 'Tour repository'; $string['viewtour_info'] = 'This is the \'{$a->tourname}\' tour. It applies to the path \'{$a->path}\'.'; +$string['event_tour_started'] = 'Tour started'; +$string['event_tour_reset'] = 'Tour reset'; +$string['event_tour_ended'] = 'Tour ended'; +$string['event_step_shown'] = 'Step shown';