diff --git a/admin/tool/usertours/classes/external/tour.php b/admin/tool/usertours/classes/external/tour.php index 0430b1febe4..9ecad8e43ac 100644 --- a/admin/tool/usertours/classes/external/tour.php +++ b/admin/tool/usertours/classes/external/tour.php @@ -189,6 +189,7 @@ class tour extends external_api { self::validate_context($context); $tour = tourinstance::instance($params['tourid']); + $tour->mark_user_completed(); \tool_usertours\event\tour_ended::create([ diff --git a/admin/tool/usertours/classes/helper.php b/admin/tool/usertours/classes/helper.php index f782127cc89..8327dbd0ed4 100644 --- a/admin/tool/usertours/classes/helper.php +++ b/admin/tool/usertours/classes/helper.php @@ -21,9 +21,9 @@ use core\output\inplace_editable; /** * Tour helper. * - * @package tool_usertours * @copyright 2016 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package tool_usertours */ class helper { /** diff --git a/admin/tool/usertours/classes/local/forms/edittour.php b/admin/tool/usertours/classes/local/forms/edittour.php index 165de32bc55..cf6f50402cd 100644 --- a/admin/tool/usertours/classes/local/forms/edittour.php +++ b/admin/tool/usertours/classes/local/forms/edittour.php @@ -29,6 +29,7 @@ defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); require_once($CFG->libdir . '/formslib.php'); use tool_usertours\helper; +use tool_usertours\tour; /** * Form for editing tours. @@ -88,6 +89,17 @@ class edittour extends \moodleform { $mform->addElement('checkbox', 'displaystepnumbers', get_string('displaystepnumbers', 'tool_usertours')); $mform->addHelpButton('displaystepnumbers', 'displaystepnumbers', 'tool_usertours'); + $mform->addElement( + 'select', + 'showtourwhen', + get_string('showtourwhen', 'tool_usertours'), + [ + tour::SHOW_TOUR_UNTIL_COMPLETE => get_string('showtouruntilcomplete', 'tool_usertours'), + tour::SHOW_TOUR_ON_EACH_PAGE_VISIT => get_string('showtoureachtime', 'tool_usertours'), + ] + ); + $mform->setDefault('showtourwhen', tour::SHOW_TOUR_UNTIL_COMPLETE); + // Configuration. $this->tour->add_config_to_form($mform); diff --git a/admin/tool/usertours/classes/manager.php b/admin/tool/usertours/classes/manager.php index 7ce2915c351..cd9c22ebfee 100644 --- a/admin/tool/usertours/classes/manager.php +++ b/admin/tool/usertours/classes/manager.php @@ -363,6 +363,7 @@ class manager { $tour->set_enabled(!empty($data->enabled)); $tour->set_endtourlabel($data->endtourlabel); $tour->set_display_step_numbers(!empty($data->displaystepnumbers)); + $tour->set_showtourwhen($data->showtourwhen); foreach (configuration::get_defaultable_keys() as $key) { $tour->set_config($key, $data->$key); diff --git a/admin/tool/usertours/classes/tour.php b/admin/tool/usertours/classes/tour.php index e9cb318fae1..61001c5745d 100644 --- a/admin/tool/usertours/classes/tour.php +++ b/admin/tool/usertours/classes/tour.php @@ -52,6 +52,12 @@ class tour { */ const TOUR_REQUESTED_BY_USER = 'tool_usertours_tour_reset_time_'; + /** @var int Whether to show the tour only until it has been marked complete */ + const SHOW_TOUR_UNTIL_COMPLETE = 1; + + /** @var int Whether to show the tour every time a page matches */ + const SHOW_TOUR_ON_EACH_PAGE_VISIT = 2; + /** * @var $id The tour ID. */ @@ -641,6 +647,11 @@ class tour { return false; } + if ($this->get_showtourwhen() === self::SHOW_TOUR_ON_EACH_PAGE_VISIT) { + // The tour should be shown on every page visit. + return true; + } + if ($tourcompletiondate = get_user_preferences(self::TOUR_LAST_COMPLETED_BY_USER . $this->get_id(), null)) { if ($tourresetdate = get_user_preferences(self::TOUR_REQUESTED_BY_USER . $this->get_id(), null)) { if ($tourresetdate >= $tourcompletiondate) { @@ -763,6 +774,7 @@ class tour { */ public function prepare_data_for_form() { $data = $this->to_record(); + $data->showtourwhen = $this->get_showtourwhen(); foreach (configuration::get_defaultable_keys() as $key) { $data->$key = $this->get_config($key, configuration::get_default_value($key)); } @@ -860,4 +872,29 @@ class tour { public function get_display_step_numbers(): bool { return $this->displaystepnumbers; } + + /** + * Set the value for the when to show the tour. + * + * @see self::SHOW_TOUR_UNTIL_COMPLETE + * @see self::SHOW_TOUR_ON_EACH_PAGE_VISIT + * + * @param int $value + * @return self + */ + public function set_showtourwhen(int $value): tour { + return $this->set_config('showtourwhen', $value); + } + + /** + * When to show the tour. + * + * @see self::SHOW_TOUR_UNTIL_COMPLETE + * @see self::SHOW_TOUR_ON_EACH_PAGE_VISIT + * + * @return int + */ + public function get_showtourwhen(): int { + return $this->get_config('showtourwhen', self::SHOW_TOUR_UNTIL_COMPLETE); + } } diff --git a/admin/tool/usertours/lang/en/tool_usertours.php b/admin/tool/usertours/lang/en/tool_usertours.php index 0672417b728..815806de4a9 100644 --- a/admin/tool/usertours/lang/en/tool_usertours.php +++ b/admin/tool/usertours/lang/en/tool_usertours.php @@ -36,6 +36,9 @@ $string['description_help'] = 'The description of a tour may be added as plain t Alternatively, a language string ID may be entered in the format identifier,component (with no brackets or space after the comma).'; $string['displaystepnumbers'] = 'Display step numbers'; $string['displaystepnumbers_help'] = 'Whether to display a step number count e.g. 1/4, 2/4 etc. to indicate the length of the user tour.'; +$string['showtourwhen'] = 'Show tour'; +$string['showtoureachtime'] = 'each time a filter matches it'; +$string['showtouruntilcomplete'] = 'until it has been closed'; $string['confirmstepremovalquestion'] = 'Are you sure that you wish to remove this step?'; $string['confirmstepremovaltitle'] = 'Confirm step removal'; $string['confirmtourremovalquestion'] = 'Are you sure that you wish to remove this tour?'; diff --git a/admin/tool/usertours/tests/behat/tour_prevents_completion.feature b/admin/tool/usertours/tests/behat/tour_prevents_completion.feature new file mode 100644 index 00000000000..0b2e687be9f --- /dev/null +++ b/admin/tool/usertours/tests/behat/tour_prevents_completion.feature @@ -0,0 +1,29 @@ +@tool @tool_usertours +Feature: Prevent yours from being marked as complete + In order to impart key information + As an administrator + I can prevent a user tour from being marked as complete + + Background: + Given I log in as "admin" + And I add a new user tour with: + | Name | First tour | + | Description | My first tour | + | Apply to URL match | FRONTPAGE | + | Tour is enabled | 1 | + | Show with backdrop | 1 | + # 2 = tour::SHOW_TOUR_ON_EACH_PAGE_VISIT + | Show tour | 2 | + And I add steps to the "First tour" tour: + | targettype | Title | id_content | Content type | + | Display in middle of page | Welcome | Welcome tour. | Manual | + + @javascript + Scenario: Ending the tour should not mark it as complete + # Changing the window viewport to mobile so we will have the footer section. + Given I am on site homepage + And I should see "Welcome" + And I press "Got it" + And I should not see "Welcome" + When I am on site homepage + Then I should see "Welcome" diff --git a/admin/tool/usertours/tests/tour_test.php b/admin/tool/usertours/tests/tour_test.php index ab8ba1ded7f..ac34e75015f 100644 --- a/admin/tool/usertours/tests/tour_test.php +++ b/admin/tool/usertours/tests/tour_test.php @@ -98,6 +98,10 @@ class tour_test extends \advanced_testcase { 'config', ['key', 'value'], ], + 'showtourwhen' => [ + 'showtourwhen', + [0], + ], ]; } @@ -598,30 +602,44 @@ class tour_test extends \advanced_testcase { null, null, null, + [], true, ], 'Completed by user before majorupdatetime' => [ $time - DAYSECS, null, $time, + [], true, ], 'Completed by user since majorupdatetime' => [ $time, null, $time - DAYSECS, + [], false, ], 'Requested by user before current completion' => [ $time, $time - DAYSECS, - null, + $time - MINSECS, + [], false, ], 'Requested by user since completion' => [ $time - DAYSECS, $time, + 'null', + [], + true, + ], + 'Tour will show on each load' => [ + $time, + $time - DAYSECS, null, + [ + 'showtourwhen' => tour::SHOW_TOUR_ON_EACH_PAGE_VISIT, + ], true, ], ]; @@ -634,9 +652,16 @@ class tour_test extends \advanced_testcase { * @param mixed $completiondate The user's completion date for this tour * @param mixed $requesteddate The user's last requested date for this tour * @param mixed $updateddate The date this tour was last updated + * @param mixed $config The tour config to apply * @param string $expectation The expected tour key */ - public function test_should_show_for_user($completiondate, $requesteddate, $updateddate, $expectation): void { + public function test_should_show_for_user( + $completiondate, + $requesteddate, + $updateddate, + $config, + $expectation, + ): void { // Uses user preferences so we must be in a user context. $this->resetAfterTest(); $this->setAdminUser(); @@ -644,7 +669,6 @@ class tour_test extends \advanced_testcase { $tour = $this->getMockBuilder(tour::class) ->onlyMethods([ 'get_id', - 'get_config', 'is_enabled', ]) ->getMock(); @@ -652,6 +676,10 @@ class tour_test extends \advanced_testcase { $tour->method('is_enabled') ->willReturn(true); + foreach ($config as $key => $value) { + $tour->set_config($key, $value); + } + $id = rand(1, 100); $tour->method('get_id') ->willReturn($id); @@ -665,9 +693,7 @@ class tour_test extends \advanced_testcase { } if ($updateddate !== null) { - $tour->expects($this->once()) - ->method('get_config') - ->willReturn($updateddate); + $tour->set_config('majorupdatetime', $updateddate); } $this->assertEquals($expectation, $tour->should_show_for_user());