From 1093e43bdaceed02cc9330f080b9aaffb87bc41f Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Thu, 20 Oct 2016 09:55:46 +0800 Subject: [PATCH] MDL-56516 tool_usertours: Cache tours and steps --- admin/tool/usertours/classes/cache.php | 135 +++++++ admin/tool/usertours/classes/helper.php | 10 +- admin/tool/usertours/classes/manager.php | 14 +- admin/tool/usertours/classes/step.php | 20 ++ admin/tool/usertours/classes/tour.php | 7 + admin/tool/usertours/db/caches.php | 42 +++ .../tool/usertours/lang/en/tool_usertours.php | 2 + admin/tool/usertours/tests/cache_test.php | 340 ++++++++++++++++++ admin/tool/usertours/tests/helper_trait.php | 105 ++++++ admin/tool/usertours/tests/manager_test.php | 21 +- admin/tool/usertours/tests/step_test.php | 21 ++ admin/tool/usertours/version.php | 2 +- 12 files changed, 688 insertions(+), 31 deletions(-) create mode 100644 admin/tool/usertours/classes/cache.php create mode 100644 admin/tool/usertours/db/caches.php create mode 100644 admin/tool/usertours/tests/cache_test.php create mode 100644 admin/tool/usertours/tests/helper_trait.php diff --git a/admin/tool/usertours/classes/cache.php b/admin/tool/usertours/classes/cache.php new file mode 100644 index 00000000000..6c81a0ae633 --- /dev/null +++ b/admin/tool/usertours/classes/cache.php @@ -0,0 +1,135 @@ +. + +/** + * Cache manager. + * + * @package tool_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace tool_usertours; + +defined('MOODLE_INTERNAL') || die(); + +/** + * Cache manager. + * + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class cache { + /** + * @var CACHENAME_TOUR The name of the cache used for storing tours. + */ + const CACHENAME_TOUR = 'tourdata'; + + /** + * @var CACHEKEY_TOUR The name of the key used for storing tours. + */ + const CACHEKEY_TOUR = 'tours'; + + /** + * @var CACHENAME_STEP The name of the cache used for storing steps. + */ + const CACHENAME_STEP = 'stepdata'; + + /** + * Fetch all enabled tours. + */ + public static function get_enabled_tourdata() { + global $DB; + + $cache = \cache::make('tool_usertours', self::CACHENAME_TOUR); + + $data = $cache->get(self::CACHEKEY_TOUR); + if ($data === false) { + $sql = << 0 + ORDER BY t.sortorder ASC +EOF; + + $data = $DB->get_records_sql($sql); + $cache->set('tours', $data); + } + + return $data; + } + + /** + * Fetch all enabled tours matching the specified target. + * + * @param string $targetmatch The URL to match. + */ + public static function get_matching_tourdata($targetmatch) { + $tours = self::get_enabled_tourdata(); + + return array_filter($tours, function($tour) use ($targetmatch) { + $pattern = preg_quote($tour->pathmatch, '@'); + $pattern = str_replace('%', '.*', $pattern); + return !!preg_match("@{$pattern}@", $targetmatch); + }); + } + + /** + * Notify of changes to any tour to clear the tour cache. + */ + public static function notify_tour_change() { + $cache = \cache::make('tool_usertours', self::CACHENAME_TOUR); + $cache->delete(self::CACHEKEY_TOUR); + } + + /** + * Fetch the tour data for the specified tour. + * + * @param int $tourid The ID of the tour to fetch steps for + */ + public static function get_stepdata($tourid) { + global $DB; + + $cache = \cache::make('tool_usertours', self::CACHENAME_STEP); + + $data = $cache->get($tourid); + if ($data === false) { + $sql = <<get_records_sql($sql, ['tourid' => $tourid]); + $cache->set($tourid, $data); + } + + return $data; + } + /** + * Notify of changes to any step to clear the step cache for that tour. + * + * @param int $tourid The ID of the tour to clear the step cache for + */ + public static function notify_step_change($tourid) { + $cache = \cache::make('tool_usertours', self::CACHENAME_STEP); + $cache->delete($tourid); + } +} diff --git a/admin/tool/usertours/classes/helper.php b/admin/tool/usertours/classes/helper.php index d27db08b97d..99beffe7f04 100644 --- a/admin/tool/usertours/classes/helper.php +++ b/admin/tool/usertours/classes/helper.php @@ -432,6 +432,11 @@ class helper { } $index++; } + + // Notify the cache that a tour has changed. + // Tours are only stored in the cache if there are steps. + // If there step count has changed for some reason, this will change the potential cache results. + cache::notify_tour_change(); } @@ -442,11 +447,8 @@ class helper { * @return stdClass[] */ public static function get_steps($tourid) { - global $DB; + $steps = cache::get_stepdata($tourid); - $order = 'sortorder ASC'; - - $steps = $DB->get_records('tool_usertours_steps', array('tourid' => $tourid), $order); $return = []; foreach ($steps as $step) { $return[$step->id] = step::load_from_record($step); diff --git a/admin/tool/usertours/classes/manager.php b/admin/tool/usertours/classes/manager.php index 2362ac2575c..d9589fc33aa 100644 --- a/admin/tool/usertours/classes/manager.php +++ b/admin/tool/usertours/classes/manager.php @@ -559,22 +559,14 @@ class manager { * @return tour */ public static function get_matching_tours(\moodle_url $pageurl) { - global $DB, $PAGE; + global $PAGE; - $sql = <<get_records_sql($sql, array( - $pageurl->out_as_local_url(), - )); + $tours = cache::get_matching_tourdata($pageurl->out_as_local_url()); foreach ($tours as $record) { $tour = tour::load_from_record($record); - if ($tour->is_enabled() && $tour->matches_all_filters($PAGE->context) && $tour->count_steps() > 0) { + if ($tour->is_enabled() && $tour->matches_all_filters($PAGE->context)) { return $tour; } } diff --git a/admin/tool/usertours/classes/step.php b/admin/tool/usertours/classes/step.php index b30fccd1166..af06965f02b 100644 --- a/admin/tool/usertours/classes/step.php +++ b/admin/tool/usertours/classes/step.php @@ -485,8 +485,19 @@ class step { $this->id = $DB->insert_record('tool_usertours_steps', $record); } + $this->get_tour()->reset_step_sortorder(); + $this->reload(); + // Notify of a change to the step configuration. + // This must be done separately to tour change notifications. + cache::notify_step_change($this->get_tourid()); + + // Notify the cache that a tour has changed. + // Tours are only stored in the cache if there are steps. + // If there step count has changed for some reason, this will change the potential cache results. + cache::notify_tour_change(); + return $this; } @@ -502,6 +513,15 @@ class step { $DB->delete_records('tool_usertours_steps', array('id' => $this->id)); $this->get_tour()->reset_step_sortorder(); + + // Notify of a change to the step configuration. + // This must be done separately to tour change notifications. + cache::notify_step_change($this->get_id()); + + // Notify the cache that a tour has changed. + // Tours are only stored in the cache if there are steps. + // If there step count has changed for some reason, this will change the potential cache results. + cache::notify_tour_change(); } /** diff --git a/admin/tool/usertours/classes/tour.php b/admin/tool/usertours/classes/tour.php index b628744d9aa..473a077fa58 100644 --- a/admin/tool/usertours/classes/tour.php +++ b/admin/tool/usertours/classes/tour.php @@ -523,6 +523,9 @@ class tour { $this->reload(); + // Notify the cache that a tour has changed. + cache::notify_tour_change(); + return $this; } @@ -566,6 +569,10 @@ class tour { $index++; } + // Notify of a change to the step configuration. + // Note: Do not notify of a tour change here. This is only a step change for a tour. + cache::notify_step_change($this->get_id()); + return $this; } diff --git a/admin/tool/usertours/db/caches.php b/admin/tool/usertours/db/caches.php new file mode 100644 index 00000000000..3ae3c8fb4c7 --- /dev/null +++ b/admin/tool/usertours/db/caches.php @@ -0,0 +1,42 @@ +. + +/** + * Plugin cache definitions. + * + * @package tool_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$definitions = array( + 'tourdata' => array( + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => true, + 'simpledata' => true, + 'staticacceleration' => true, + 'staticaccelerationsize' => 1, + ), + 'stepdata' => array( + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => true, + 'simpledata' => true, + 'staticacceleration' => true, + 'staticaccelerationsize' => 1, + ), +); diff --git a/admin/tool/usertours/lang/en/tool_usertours.php b/admin/tool/usertours/lang/en/tool_usertours.php index 9d3fae6efa6..67a395f143d 100644 --- a/admin/tool/usertours/lang/en/tool_usertours.php +++ b/admin/tool/usertours/lang/en/tool_usertours.php @@ -27,6 +27,8 @@ $string['appliesto'] = 'Applies to'; $string['block'] = 'Block'; $string['block_named'] = 'Block named \'{$a}\''; $string['bottom'] = 'Bottom'; +$string['cachedef_stepdata'] = 'List of User Tour steps'; +$string['cachedef_tourdata'] = 'List of enabled User Tours information which are fetched on every page'; $string['description'] = 'Description'; $string['confirmstepremovalquestion'] = 'Are you sure that you wish to remove this step?'; $string['confirmstepremovaltitle'] = 'Confirm step removal'; diff --git a/admin/tool/usertours/tests/cache_test.php b/admin/tool/usertours/tests/cache_test.php new file mode 100644 index 00000000000..fdbdde0b0aa --- /dev/null +++ b/admin/tool/usertours/tests/cache_test.php @@ -0,0 +1,340 @@ +. + +/** + * Tests for cache. + * + * @package tool_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once(__DIR__ . '/helper_trait.php'); + +/** + * Tests for cache. + * + * @package tool_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class cache_testcase extends advanced_testcase { + // There are shared helpers for these tests in the helper trait. + use tool_usertours_helper_trait; + + /** + * Test that get_enabled_tourdata does not return disabled tours. + */ + public function test_get_enabled_tourdata_disabled() { + $this->resetAfterTest(); + + $tour = $this->helper_create_tour((object)['enabled' => false]); + $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEmpty($matches); + } + + /** + * Test that get_enabled_tourdata does not return an enabled but empty tour. + */ + public function test_get_enabled_tourdata_enabled_no_steps() { + $this->resetAfterTest(); + + $this->helper_create_tour(); + + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEmpty($matches); + } + + /** + * Test that get_enabled_tourdata returns a tour with steps. + */ + public function test_get_enabled_tourdata_enabled() { + $this->resetAfterTest(); + + // Create two tours. Only the second has steps. + $this->helper_create_tour(); + $tour2 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); + + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertNotEmpty($matches); + $this->assertCount(1, $matches); + + $match = array_shift($matches); + $this->assertEquals($tour2->get_id(), $match->id); + } + + /** + * Test that get_enabled_tourdata returns tours in the correct sortorder + */ + public function test_get_enabled_tourdata_enabled_sortorder() { + $this->resetAfterTest(); + + $tour1 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); + $tour2 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); + + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertNotEmpty($matches); + $this->assertCount(2, $matches); + + $match = array_shift($matches); + $this->assertEquals($tour1->get_id(), $match->id); + $match = array_shift($matches); + $this->assertEquals($tour2->get_id(), $match->id); + } + + /** + * Test that caching prevents additional DB reads. + */ + public function test_get_enabled_tourdata_single_fetch() { + global $DB; + + $this->resetAfterTest(); + + $tour1 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); + $tour2 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); + + // Only one read for the first call. + $startreads = $DB->perf_get_reads(); + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + // No subsequent reads for any further calls. + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + } + + /** + * Data provider for get_matching_tourdata. + * + * @return array + */ + public function get_matching_tourdata_provider() { + $tourconfigs = [ + (object) [ + 'name' => 'my_exact_1', + 'pathmatch' => '/my/view.php' + ], + (object) [ + 'name' => 'my_failed_regex', + 'pathmatch' => '/my/*.php' + ], + (object) [ + 'name' => 'my_glob_1', + 'pathmatch' => '/my/%' + ], + (object) [ + 'name' => 'my_glob_2', + 'pathmatch' => '/my/%' + ], + ]; + + return [ + 'Matches expected glob' => [ + $tourconfigs, + '/my/index.php', + ['my_glob_1', 'my_glob_2'], + ], + 'Matches expected glob and exact' => [ + $tourconfigs, + '/my/view.php', + ['my_exact_1', 'my_glob_1', 'my_glob_2'], + ], + ]; + } + + /** + * Tests for the get_matching_tourdata function. + * + * @dataProvider get_matching_tourdata_provider + * @param array $tourconfigs The configuration for the tours to create + * @param string $targetmatch The match to be tested + * @param array $expected An array containing the ordered names of the expected tours + */ + public function test_get_matching_tourdata($tourconfigs, $targetmatch, $expected) { + $this->resetAfterTest(); + foreach ($tourconfigs as $tourconfig) { + $tour = $this->helper_create_tour($tourconfig); + $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + } + + $matches = \tool_usertours\cache::get_matching_tourdata((new moodle_url($targetmatch))->out_as_local_url()); + $this->assertCount(count($expected), $matches); + + for ($i = 0; $i < count($matches); $i++) { + $match = array_shift($matches); + $this->assertEquals($expected[$i], $match->name); + } + } + + /** + * Test that notify_tour_change clears the cache. + */ + public function test_notify_tour_change() { + global $DB; + + $this->resetAfterTest(); + + $tour1 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); + $tour2 = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour2->get_id()]); + + // Only one read for the first call. + $startreads = $DB->perf_get_reads(); + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + // No subsequent reads for any further calls. + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + // Reset. + \tool_usertours\cache::notify_tour_change(); + + // An additional DB read now. + $startreads = $DB->perf_get_reads(); + $matches = \tool_usertours\cache::get_enabled_tourdata(); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + } + + /** + * Test that get_stepdata returns an empty array when no steps were found. + */ + public function test_get_stepdata_no_steps() { + $this->resetAfterTest(); + + $tour = $this->helper_create_tour((object)['enabled' => false]); + + $data = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertInternalType('array', $data); + $this->assertEmpty($data); + } + + /** + * Test that get_stepdata returns an empty array when no steps were found. + */ + public function test_get_stepdata_correct_tour() { + $this->resetAfterTest(); + + $tour1 = $this->helper_create_tour((object)['enabled' => false]); + $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); + $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); + $this->helper_create_step((object) ['tourid' => $tour1->get_id()]); + $tour2 = $this->helper_create_tour((object)['enabled' => false]); + + $data = \tool_usertours\cache::get_stepdata($tour1->get_id()); + $this->assertInternalType('array', $data); + $this->assertCount(3, $data); + + $data = \tool_usertours\cache::get_stepdata($tour2->get_id()); + $this->assertInternalType('array', $data); + $this->assertEmpty($data); + } + + /** + * Test that get_stepdata returns an array containing multiple steps in + * the same order. + * + * This is very difficult to determine because the act of changing the + * order will likely change the DB natural sorting. + */ + public function test_get_stepdata_ordered_steps() { + $this->resetAfterTest(); + + $tour = $this->helper_create_tour((object)['enabled' => false]); + $steps = []; + $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + $steps[] = $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + $steps[0]->set_sortorder(10)->persist(); + + $data = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertInternalType('array', $data); + $this->assertCount(4, $data); + + // Re-order the steps. + usort($steps, function($a, $b) { + return ($a->get_sortorder() < $b->get_sortorder()) ? -1 : 1; + }); + + for ($i = 0; $i < count($data); $i++) { + $step = array_shift($data); + $this->assertEquals($steps[$i]->get_id(), $step->id); + } + } + + /** + * Test that caching prevents additional DB reads. + */ + public function test_get_stepdata_single_fetch() { + global $DB; + + $this->resetAfterTest(); + + $tour = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + + // Only one read for the first call. + $startreads = $DB->perf_get_reads(); + $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + // No subsequent reads for any further calls. + $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + } + + /** + * Test that notify_step_change clears the cache. + */ + public function test_notify_step_change() { + global $DB; + + $this->resetAfterTest(); + + $tour = $this->helper_create_tour(); + $this->helper_create_step((object) ['tourid' => $tour->get_id()]); + + // Only one read for the first call. + $startreads = $DB->perf_get_reads(); + $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + // No subsequent reads for any further calls. + $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + + // Reset. + \tool_usertours\cache::notify_step_change($tour->get_id()); + + // An additional DB read now. + $startreads = $DB->perf_get_reads(); + $matches = \tool_usertours\cache::get_stepdata($tour->get_id()); + $this->assertEquals(1, $DB->perf_get_reads() - $startreads); + } +} diff --git a/admin/tool/usertours/tests/helper_trait.php b/admin/tool/usertours/tests/helper_trait.php new file mode 100644 index 00000000000..aab15de5ccf --- /dev/null +++ b/admin/tool/usertours/tests/helper_trait.php @@ -0,0 +1,105 @@ +. + +/** + * Helpers for unit tests. + * + * @package tool_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +/** + * Helpers for unit tests. + * + * @package tool_usertours + * @copyright 2016 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +trait tool_usertours_helper_trait { + /** + * A helper to create an empty tour. + * + * @param stdClass $tourconfig The configuration for the new tour + * @param bool $persist Whether to persist the data + * @return \tool_usertours\tour + */ + public function helper_create_tour(\stdClass $tourconfig = null, $persist = true) { + $minvalues = [ + 'id' => null, + 'pathmatch' => '/my/%', + 'enabled' => true, + 'name' => '', + 'description' => '', + 'configdata' => '', + ]; + + if ($tourconfig === null) { + $tourconfig = new \stdClass(); + } + + foreach ($minvalues as $key => $value) { + if (!isset($tourconfig->$key)) { + $tourconfig->$key = $value; + } + } + + $tour = \tool_usertours\tour::load_from_record($tourconfig, true); + if ($persist) { + $tour->persist(true); + } + + return $tour; + } + + /** + * A helper to create an empty step for the specified tour. + * + * @param stdClass $stepconfig The configuration for the new step + * @param bool $persist Whether to persist the data + * @return \tool_usertours\step + */ + public function helper_create_step(\stdClass $stepconfig = null, $persist = true) { + $minvalues = [ + 'id' => null, + 'title' => '', + 'content' => '', + 'targettype' => \tool_usertours\target::TARGET_UNATTACHED, + 'targetvalue' => '', + 'sortorder' => 0, + 'configdata' => '', + ]; + + if ($stepconfig === null) { + $stepconfig = new \stdClass(); + } + + foreach ($minvalues as $key => $value) { + if (!isset($stepconfig->$key)) { + $stepconfig->$key = $value; + } + } + + $step = \tool_usertours\step::load_from_record($stepconfig, true); + if ($persist) { + $step->persist(true); + } + + return $step; + } +} diff --git a/admin/tool/usertours/tests/manager_test.php b/admin/tool/usertours/tests/manager_test.php index aa7a6bfac2b..f32727a9bbe 100644 --- a/admin/tool/usertours/tests/manager_test.php +++ b/admin/tool/usertours/tests/manager_test.php @@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die(); global $CFG; require_once($CFG->libdir . '/formslib.php'); +require_once(__DIR__ . '/helper_trait.php'); /** * Tests for step. @@ -34,7 +35,9 @@ require_once($CFG->libdir . '/formslib.php'); * @copyright 2016 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class manager_testcase extends advanced_testcase { +class tool_usertours_manager_testcase extends advanced_testcase { + // There are shared helpers for these tests in the helper trait. + use tool_usertours_helper_trait; /** * @var moodle_database @@ -243,25 +246,14 @@ class manager_testcase extends advanced_testcase { $tourconfig->id = null; $tour = \tool_usertours\tour::load_from_record($tourconfig, true); $tour->persist(true); - - $stepconfig = (object) [ - 'id' => null, - 'tourid' => $tour->get_id(), - 'title' => '', - 'content' => '', - 'targettype' => \tool_usertours\target::TARGET_UNATTACHED, - 'targetvalue' => '', - 'sortorder' => 0, - 'configdata' => '', - ]; - $step = \tool_usertours\step::load_from_record($stepconfig, true); - $step->persist(true); + $this->helper_create_step((object) ['tourid' => $tour->get_id()]); } $match = \tool_usertours\manager::get_matching_tours(new moodle_url($url)); if ($expected === null) { $this->assertNull($match); } else { + $this->assertNotNull($match); $this->assertEquals($expected, $match->get_name()); } } @@ -289,5 +281,4 @@ class manager_testcase extends advanced_testcase { $this->assertNull(\tool_usertours\manager::get_matching_tours(new moodle_url($url))); } - } diff --git a/admin/tool/usertours/tests/step_test.php b/admin/tool/usertours/tests/step_test.php index 444d2dab669..0c20d647d6c 100644 --- a/admin/tool/usertours/tests/step_test.php +++ b/admin/tool/usertours/tests/step_test.php @@ -551,6 +551,11 @@ class step_testcase extends advanced_testcase { $rcp->setAccessible(true); $rcp->setValue($step, true); + $tour = $this->createMock(\tool_usertours\tour::class); + $rcp = $rc->getProperty('tour'); + $rcp->setAccessible(true); + $rcp->setValue($step, $tour); + $this->assertSame($step, $step->persist()); } @@ -590,6 +595,12 @@ class step_testcase extends advanced_testcase { ->method('reload') ; + $tour = $this->createMock(\tool_usertours\tour::class); + $rc = new \ReflectionClass(\tool_usertours\step::class); + $rcp = $rc->getProperty('tour'); + $rcp->setAccessible(true); + $rcp->setValue($step, $tour); + $this->assertSame($step, $step->persist(true)); } @@ -635,6 +646,11 @@ class step_testcase extends advanced_testcase { $rcp->setAccessible(true); $rcp->setValue($step, true); + $tour = $this->createMock(\tool_usertours\tour::class); + $rcp = $rc->getProperty('tour'); + $rcp->setAccessible(true); + $rcp->setValue($step, $tour); + $this->assertSame($step, $step->persist()); } @@ -678,6 +694,11 @@ class step_testcase extends advanced_testcase { $rcp->setAccessible(true); $rcp->setValue($step, 42); + $tour = $this->createMock(\tool_usertours\tour::class); + $rcp = $rc->getProperty('tour'); + $rcp->setAccessible(true); + $rcp->setValue($step, $tour); + $this->assertSame($step, $step->persist(true)); } diff --git a/admin/tool/usertours/version.php b/admin/tool/usertours/version.php index 827b68ebc16..6711935dd16 100644 --- a/admin/tool/usertours/version.php +++ b/admin/tool/usertours/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2016101800; // The current module version (Date: YYYYMMDDXX). +$plugin->version = 2016102001; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2016052300; // Requires this Moodle version. $plugin->component = 'tool_usertours'; // Full name of the plugin (used for diagnostics).