diff --git a/admin/tool/usertours/classes/manager.php b/admin/tool/usertours/classes/manager.php index c7e5b3e533f..d5e4ad07749 100644 --- a/admin/tool/usertours/classes/manager.php +++ b/admin/tool/usertours/classes/manager.php @@ -720,6 +720,13 @@ class manager { * @param int $direction */ protected static function _move_tour(tour $tour, $direction) { + // We can't move the first tour higher, nor the last tour any lower. + if (($tour->is_first_tour() && $direction == helper::MOVE_UP) || + ($tour->is_last_tour() && $direction == helper::MOVE_DOWN)) { + + return; + } + $currentsortorder = $tour->get_sortorder(); $targetsortorder = $currentsortorder + $direction; diff --git a/admin/tool/usertours/tests/manager_test.php b/admin/tool/usertours/tests/manager_test.php index bffecb32f7c..913c3e1b86e 100644 --- a/admin/tool/usertours/tests/manager_test.php +++ b/admin/tool/usertours/tests/manager_test.php @@ -122,6 +122,83 @@ class tool_usertours_manager_testcase extends advanced_testcase { $rcm->invokeArgs($manager, $arguments); } + /** + * Data provider for test_move_tour + * + * @return array + */ + public function move_tour_provider() { + $alltours = [ + ['name' => 'Tour 1'], + ['name' => 'Tour 2'], + ['name' => 'Tour 3'], + ]; + + return [ + 'Move up' => [ + $alltours, + 'Tour 2', + \tool_usertours\helper::MOVE_UP, + 0, + ], + 'Move down' => [ + $alltours, + 'Tour 2', + \tool_usertours\helper::MOVE_DOWN, + 2, + ], + 'Move up (first)' => [ + $alltours, + 'Tour 1', + \tool_usertours\helper::MOVE_UP, + 0, + ], + 'Move down (last)' => [ + $alltours, + 'Tour 3', + \tool_usertours\helper::MOVE_DOWN, + 2, + ], + ]; + } + + /** + * Test moving tours (changing sortorder) + * + * @dataProvider move_tour_provider + * + * @param array $alltours + * @param string $movetourname + * @param int $direction + * @param int $expectedsortorder + * @return void + */ + public function test_move_tour($alltours, $movetourname, $direction, $expectedsortorder) { + global $DB; + + $this->resetAfterTest(); + + // Clear out existing tours so ours are the only ones, otherwise we can't predict the sortorder. + $DB->delete_records('tool_usertours_tours'); + + foreach ($alltours as $tourconfig) { + $this->helper_create_tour((object) $tourconfig); + } + + // Load our tour to move. + $record = $DB->get_record('tool_usertours_tours', ['name' => $movetourname]); + $tour = \tool_usertours\tour::load_from_record($record); + + // Call protected method via reflection. + $class = new ReflectionClass(\tool_usertours\manager::class); + $method = $class->getMethod('_move_tour'); + $method->setAccessible(true); + $method->invokeArgs(null, [$tour, $direction]); + + // Assert expected sortorder. + $this->assertEquals($expectedsortorder, $tour->get_sortorder()); + } + /** * Data Provider for get_matching_tours tests. *