Merge branch 'master' into install_master

This commit is contained in:
AMOS bot
2024-03-14 00:13:23 +00:00
547 changed files with 11719 additions and 6348 deletions
-2
View File
@@ -227,7 +227,6 @@ class core_adminpresets_generator extends \component_generator_base {
public function access_protected($object, string $property) {
$reflection = new ReflectionClass($object);
$property = $reflection->getProperty($property);
$property->setAccessible(true);
return $property->getValue($object);
}
@@ -244,7 +243,6 @@ class core_adminpresets_generator extends \component_generator_base {
// Set method accessibility.
$method = new ReflectionMethod(manager::class, 'get_setting');
$method->setAccessible(true);
// Get the proper adminpresets_setting instance.
$settingpage = $adminroot->locate($category);
+12
View File
@@ -135,6 +135,18 @@ if ($hassiteconfig) {
$temp->add($setting);
$ADMIN->add('authsettings', $temp);
// Toggle password visiblity icon.
$temp->add(new admin_setting_configselect('loginpasswordtoggle',
new lang_string('auth_loginpasswordtoggle', 'auth'),
new lang_string('auth_loginpasswordtoggle_desc', 'auth'),
TOGGLE_SENSITIVE_SMALL_SCREENS_ONLY,
[
TOGGLE_SENSITIVE_DISABLED => get_string('disabled', 'admin'),
TOGGLE_SENSITIVE_ENABLED => get_string('enabled', 'admin'),
TOGGLE_SENSITIVE_SMALL_SCREENS_ONLY => get_string('smallscreensonly', 'admin'),
],
));
$temp = new admin_externalpage('authtestsettings', get_string('testsettings', 'core_auth'), new moodle_url("/auth/test_settings.php"), 'moodle/site:config', true);
$ADMIN->add('authsettings', $temp);
@@ -2079,7 +2079,6 @@ class expired_contexts_test extends \advanced_testcase {
$rc = new \ReflectionClass(\tool_dataprivacy\expired_contexts_manager::class);
$rcm = $rc->getMethod('get_progress');
$rcm->setAccessible(true);
$this->assertInstanceOf(\text_progress_trace::class, $rcm->invoke($manager));
}
@@ -2094,7 +2093,6 @@ class expired_contexts_test extends \advanced_testcase {
$rc = new \ReflectionClass(\tool_dataprivacy\expired_contexts_manager::class);
$rcm = $rc->getMethod('get_progress');
$rcm->setAccessible(true);
$this->assertSame($mytrace, $rcm->invoke($manager));
}
@@ -41,7 +41,6 @@ class filtered_userlist_test extends \advanced_testcase {
$rc = new \ReflectionClass(\tool_dataprivacy\filtered_userlist::class);
$rcm = $rc->getMethod('set_userids');
$rcm->setAccessible(true);
$rcm->invoke($userlist, $initial);
@@ -84,7 +84,6 @@ class locale_test extends \advanced_testcase {
$loc = new locale();
$rc = new \ReflectionClass(locale::class);
$rm = $rc->getMethod('set_locale');
$rm->setAccessible(true);
// Capture current locale for later restore (funnily, using the set_locale() method itself.
$originallocale = $rm->invokeArgs($loc, [LC_ALL, 0]);
@@ -70,7 +70,6 @@ class manager_test extends advanced_testcase {
// We're testing a private method, so we need to setup reflector magic.
$method = new ReflectionMethod('\tool_licensemanager\manager', 'edit');
$method->setAccessible(true); // Allow accessing of private method.
$method->invoke($manager, \tool_licensemanager\manager::ACTION_UPDATE, $testlicense->shortname);
// Should not create a new license when updating an existing license.
@@ -90,7 +89,6 @@ class manager_test extends advanced_testcase {
// We're testing a private method, so we need to setup reflector magic.
$method = new ReflectionMethod('\tool_licensemanager\manager', 'edit');
$method->setAccessible(true); // Allow accessing of private method.
// Attempt to update a license that doesn't exist.
$formdata = [
@@ -111,7 +109,6 @@ class manager_test extends advanced_testcase {
// We're testing a private method, so we need to setup reflector magic.
$method = new ReflectionMethod('\tool_licensemanager\manager', 'edit');
$method->setAccessible(true); // Allow accessing of private method.
// Attempt to update a license without passing license shortname.
$formdata = [
@@ -148,7 +145,6 @@ class manager_test extends advanced_testcase {
// We're testing a private method, so we need to setup reflector magic.
$method = new ReflectionMethod('\tool_licensemanager\manager', 'edit');
$method->setAccessible(true); // Allow accessing of private method.
$method->invoke($manager, \tool_licensemanager\manager::ACTION_CREATE, $formdata['shortname']);
// Should create a new license in database.
@@ -180,7 +176,6 @@ class manager_test extends advanced_testcase {
// We're testing a private method, so we need to setup reflector magic.
$method = new ReflectionMethod('\tool_licensemanager\manager', 'change_license_order');
$method->setAccessible(true); // Allow accessing of private method.
$method->invoke($manager, \tool_licensemanager\manager::ACTION_MOVE_UP, 'cc-nc-4.0');
$licenseorder = array_keys(license_manager::get_licenses());
@@ -39,7 +39,6 @@ class factor_test extends \advanced_testcase {
$emailfactorclass = new \factor_email\factor('email');
$rc = new \ReflectionClass($emailfactorclass::class);
$rcm = $rc->getMethod('check_verification_code');
$rcm->setAccessible(true);
// Assigned email to be used in getting the email factor.
$USER->email = '[email protected]';
@@ -76,7 +75,6 @@ class factor_test extends \advanced_testcase {
// Cleans up email records once MFA passed.
$rcm = $rc->getMethod('post_pass_state');
$rcm->setAccessible(true);
$rcm->invoke($emailfactorclass);
// Check if the email records have been deleted.
@@ -154,7 +154,6 @@ class factor_test extends \advanced_testcase {
// Check verification code.
$rcm = $rc->getMethod('check_verification_code');
$rcm->setAccessible(true);
$this->assertTrue($rcm->invoke($smsfactor, $secretcode));
// Test that calling the revoke on the generic type revokes all.
@@ -50,7 +50,6 @@ class factor_test extends \advanced_testcase {
set_config('expireovernight', 0, 'factor_token');
$method = new \ReflectionMethod($this->factor, 'calculate_expiry_time');
$method->setAccessible(true);
// Test that non-overnight timestamps are just exactly as configured.
// We don't need to care about 0 or negative ints, they will just make the cookie expire immediately.
@@ -95,7 +94,6 @@ class factor_test extends \advanced_testcase {
public function test_calculate_expiry_time_for_overnight_expiry_with_one_day_expiry($timestamp) {
// Setup configuration.
$method = new \ReflectionMethod($this->factor, 'calculate_expiry_time');
$method->setAccessible(true);
set_config('expireovernight', 1, 'factor_token');
set_config('expiry', DAYSECS, 'factor_token');
@@ -144,7 +142,6 @@ class factor_test extends \advanced_testcase {
public function test_calculate_expiry_time_for_overnight_expiry_with_two_day_expiry($timestamp) {
// Setup configuration.
$method = new \ReflectionMethod($this->factor, 'calculate_expiry_time');
$method->setAccessible(true);
set_config('expireovernight', 1, 'factor_token');
set_config('expiry', 2 * DAYSECS, 'factor_token');
@@ -195,7 +192,6 @@ class factor_test extends \advanced_testcase {
public function test_calculate_expiry_time_for_overnight_expiry_with_three_hour_expiry($timestamp) {
// Setup configuration.
$method = new \ReflectionMethod($this->factor, 'calculate_expiry_time');
$method->setAccessible(true);
set_config('expireovernight', 1, 'factor_token');
set_config('expiry', 3 * HOURSECS, 'factor_token');
@@ -240,7 +236,6 @@ class factor_test extends \advanced_testcase {
public function test_calculate_expiry_time_for_overnight_expiry_with_an_hour_expiry($timestamp) {
// Setup configuration.
$method = new \ReflectionMethod($this->factor, 'calculate_expiry_time');
$method->setAccessible(true);
set_config('expireovernight', 1, 'factor_token');
set_config('expiry', HOURSECS, 'factor_token');
@@ -42,7 +42,6 @@ class secret_manager_test extends \advanced_testcase {
// Mutate the sessionid using reflection.
$reflectedsessionid = new \ReflectionProperty($secman, 'sessionid');
$reflectedsessionid->setAccessible(true);
$reflectedsessionid->setValue($secman, 'fakesession');
$sec1 = $secman->create_secret(1800, false);
@@ -97,7 +96,6 @@ class secret_manager_test extends \advanced_testcase {
// Let's make stuff public using reflection.
$reflectedscanner = new \ReflectionClass($secman);
$reflectedmethod = $reflectedscanner->getMethod('add_secret_to_db');
$reflectedmethod->setAccessible(true);
// Now add a secret and confirm it creates the correct record.
$reflectedmethod->invoke($secman, 'code', 1800);
@@ -164,7 +162,6 @@ class secret_manager_test extends \advanced_testcase {
// Session locked code from the same session id.
// Mutate the sessionid using reflection.
$reflectedsessionid = new \ReflectionProperty($secman, 'sessionid');
$reflectedsessionid->setAccessible(true);
$reflectedsessionid->setValue($secman, 'fakesession');
$secret = $secman->create_secret(1800, true);
@@ -227,7 +224,6 @@ class secret_manager_test extends \advanced_testcase {
$reflectedscanner = new \ReflectionClass($secman);
$reflectedmethod = $reflectedscanner->getMethod('has_active_secret');
$reflectedmethod->setAccessible(true);
// DB secrets.
$this->assertFalse($reflectedmethod->invoke($secman));
@@ -244,7 +240,6 @@ class secret_manager_test extends \advanced_testcase {
// Now check a secret with session involvement.
// Mutate the sessionid using reflection.
$reflectedsessionid = new \ReflectionProperty($secman, 'sessionid');
$reflectedsessionid->setAccessible(true);
$reflectedsessionid->setValue($secman, 'fakesession');
$this->assertFalse($reflectedmethod->invoke($secman, true));
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_mobile\local\hooks\output;
namespace tool_mobile\local\hook\output;
/**
* Allows plugins to add any elements to the page <head> html tag
@@ -23,14 +23,13 @@ namespace tool_mobile\local\hooks\output;
* @copyright 2023 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class standard_head_html_prepend {
class before_standard_head_html_generation {
/**
* Callback to add head elements.
*
* @param \core\hook\output\standard_head_html_prepend $hook
* @param \core\hook\output\before_standard_head_html_generation $hook
*/
public static function callback(\core\hook\output\standard_head_html_prepend $hook): void {
public static function callback(\core\hook\output\before_standard_head_html_generation $hook): void {
global $CFG, $PAGE;
// Smart App Banners meta tag is only displayed if mobile services are enabled and configured.
if (!empty($CFG->enablemobilewebservice)) {
@@ -45,7 +44,7 @@ class standard_head_html_prepend {
if (!empty($mobilesettings->androidappid)) {
$mobilemanifesturl = "$CFG->wwwroot/$CFG->admin/tool/mobile/mobile.webmanifest.php";
$hook->add_html('<link rel="manifest" href="'.$mobilemanifesturl.'" />');
$hook->add_html('<link rel="manifest" href="' . $mobilemanifesturl . '" />');
}
}
}
+2 -2
View File
@@ -26,8 +26,8 @@ defined('MOODLE_INTERNAL') || die();
$callbacks = [
[
'hook' => core\hook\output\standard_head_html_prepend::class,
'callback' => 'tool_mobile\local\hooks\output\standard_head_html_prepend::callback',
'hook' => core\hook\output\before_standard_head_html_generation::class,
'callback' => 'tool_mobile\local\hook\output\before_standard_head_html_generation::callback',
'priority' => 0,
],
];
+1 -1
View File
@@ -23,7 +23,7 @@
*/
defined('MOODLE_INTERNAL') || die();
$plugin->version = 2023100900; // The current plugin version (Date: YYYYMMDDXX).
$plugin->version = 2024022600; // The current plugin version (Date: YYYYMMDDXX).
$plugin->requires = 2023100400; // Requires this Moodle version.
$plugin->component = 'tool_mobile'; // Full name of the plugin (used for diagnostics).
$plugin->dependencies = [
+3 -12
View File
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours;
/**
* Cache manager.
*
@@ -21,17 +23,6 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @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 <[email protected]>
* @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.
@@ -97,7 +88,7 @@ EOF;
}
$target = $targetmatch->out_as_local_url();
return array_filter($tours, function($tour) use ($possiblematches, $target) {
return array_filter($tours, function ($tour) use ($possiblematches, $target) {
if (in_array($tour->pathmatch, $possiblematches)) {
return true;
}
+8 -19
View File
@@ -14,26 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Step configuration detail class.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
defined('MOODLE_INTERNAL') || die();
/**
* Step configuration detail class.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @package tool_usertours
* @copyright 2024 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class configuration {
/**
* @var TOURDEFAULT
*/
@@ -60,7 +50,7 @@ class configuration {
* @return mixed
*/
public static function get_default_value($key) {
switch($key) {
switch ($key) {
case 'placement':
return 'bottom';
case 'orphan':
@@ -77,7 +67,7 @@ class configuration {
* @return mixed
*/
public static function get_step_default_value($key) {
switch($key) {
switch ($key) {
case 'placement':
case 'orphan':
case 'backdrop':
@@ -94,10 +84,10 @@ class configuration {
*/
public static function get_placement_options($default = null) {
$values = [
'top' => get_string('above', 'tool_usertours'),
'bottom' => get_string('below', 'tool_usertours'),
'left' => get_string('left', 'tool_usertours'),
'right' => get_string('right', 'tool_usertours'),
'top' => get_string('above', 'tool_usertours'),
'bottom' => get_string('below', 'tool_usertours'),
'left' => get_string('left', 'tool_usertours'),
'right' => get_string('right', 'tool_usertours'),
];
if ($default === null) {
@@ -114,5 +104,4 @@ class configuration {
return $values;
}
}
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The tool_usertours step_shown event.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\event;
defined('MOODLE_INTERNAL') || die();
/**
* The tool_usertours step_shown event.
*
@@ -41,7 +31,6 @@ defined('MOODLE_INTERNAL') || die();
* }
*/
class step_shown extends \core\event\base {
/**
* Init method.
*/
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The tool_usertours tour_ended event.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\event;
defined('MOODLE_INTERNAL') || die();
/**
* The tool_usertours tour_ended event.
*
@@ -41,7 +31,6 @@ defined('MOODLE_INTERNAL') || die();
* }
*/
class tour_ended extends \core\event\base {
/**
* Init method.
*/
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The tool_usertours tour_reset event.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\event;
defined('MOODLE_INTERNAL') || die();
/**
* The tool_usertours tour_reset event.
*
@@ -41,7 +31,6 @@ defined('MOODLE_INTERNAL') || die();
* }
*/
class tour_reset extends \core\event\base {
/**
* Init method.
*/
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* The tool_usertours tour_started event.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\event;
defined('MOODLE_INTERNAL') || die();
/**
* The tool_usertours tour_started event.
*
@@ -41,7 +31,6 @@ defined('MOODLE_INTERNAL') || die();
* }
*/
class tour_started extends \core\event\base {
/**
* Init method.
*/
+95 -71
View File
@@ -43,10 +43,10 @@ class tour extends external_api {
global $PAGE;
$params = self::validate_parameters(self::fetch_and_start_tour_parameters(), [
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
]);
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
]);
$context = \context_helper::instance_by_id($params['context']);
self::validate_context($context);
@@ -60,8 +60,8 @@ class tour extends external_api {
\tool_usertours\event\tour_started::create([
'contextid' => $context->id,
'objectid' => $tour->get_id(),
'other' => [
'objectid' => $tour->get_id(),
'other' => [
'pageurl' => $params['pageurl'],
],
])->trigger();
@@ -78,9 +78,9 @@ class tour extends external_api {
*/
public static function fetch_and_start_tour_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'),
'tourid' => new external_value(PARAM_INT, 'Tour ID'),
'context' => new external_value(PARAM_INT, 'Context ID'),
'pageurl' => new external_value(PARAM_URL, 'Page URL'),
]);
}
@@ -91,12 +91,12 @@ class tour extends external_api {
*/
public static function fetch_and_start_tour_returns() {
return new external_single_structure([
'tourconfig' => new external_single_structure([
'name' => new external_value(PARAM_RAW, 'Tour Name'),
'steps' => new external_multiple_structure(self::step_structure_returns()),
'endtourlabel' => new external_value(PARAM_RAW, 'Label of the end tour button'),
'tourconfig' => new external_single_structure([
'name' => new external_value(PARAM_RAW, 'Tour Name'),
'steps' => new external_multiple_structure(self::step_structure_returns()),
'endtourlabel' => new external_value(PARAM_RAW, 'Label of the end tour button'),
'displaystepnumbers' => new external_value(PARAM_BOOL, 'display step number'),
], 'Tour config', VALUE_OPTIONAL)
], 'Tour config', VALUE_OPTIONAL),
]);
}
@@ -110,10 +110,10 @@ class tour extends external_api {
*/
public static function reset_tour($tourid, $context, $pageurl) {
$params = self::validate_parameters(self::reset_tour_parameters(), [
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
]);
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
]);
$context = \context_helper::instance_by_id($params['context']);
self::validate_context($context);
@@ -130,9 +130,9 @@ class tour extends external_api {
\tool_usertours\event\tour_reset::create([
'contextid' => $context->id,
'objectid' => $params['tourid'],
'other' => [
'pageurl' => $params['pageurl'],
'objectid' => $params['tourid'],
'other' => [
'pageurl' => $params['pageurl'],
],
])->trigger();
break;
@@ -149,9 +149,9 @@ class tour extends external_api {
*/
public static function reset_tour_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, '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'),
]);
}
@@ -162,7 +162,7 @@ class tour extends external_api {
*/
public static function reset_tour_returns() {
return new external_single_structure([
'startTour' => new external_value(PARAM_INT, 'Tour ID', VALUE_OPTIONAL),
'startTour' => new external_value(PARAM_INT, 'Tour ID', VALUE_OPTIONAL),
]);
}
@@ -178,25 +178,26 @@ class tour extends external_api {
*/
public static function complete_tour($tourid, $context, $pageurl, $stepid, $stepindex) {
$params = self::validate_parameters(self::complete_tour_parameters(), [
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
'stepid' => $stepid,
'stepindex' => $stepindex,
]);
'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();
\tool_usertours\event\tour_ended::create([
'contextid' => $context->id,
'objectid' => $params['tourid'],
'other' => [
'pageurl' => $params['pageurl'],
'stepid' => $params['stepid'],
'objectid' => $params['tourid'],
'other' => [
'pageurl' => $params['pageurl'],
'stepid' => $params['stepid'],
'stepindex' => $params['stepindex'],
],
])->trigger();
@@ -211,10 +212,10 @@ class tour extends external_api {
*/
public static function complete_tour_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_LOCALURL, 'Page URL'),
'stepid' => new external_value(PARAM_INT, 'Step ID'),
'tourid' => new external_value(PARAM_INT, 'Tour ID'),
'context' => new external_value(PARAM_INT, 'Context ID'),
'pageurl' => new external_value(PARAM_LOCALURL, 'Page URL'),
'stepid' => new external_value(PARAM_INT, 'Step ID'),
'stepindex' => new external_value(PARAM_INT, 'Step Number'),
]);
}
@@ -240,12 +241,12 @@ class tour extends external_api {
*/
public static function step_shown($tourid, $context, $pageurl, $stepid, $stepindex) {
$params = self::validate_parameters(self::step_shown_parameters(), [
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
'stepid' => $stepid,
'stepindex' => $stepindex,
]);
'tourid' => $tourid,
'context' => $context,
'pageurl' => $pageurl,
'stepid' => $stepid,
'stepindex' => $stepindex,
]);
$context = \context_helper::instance_by_id($params['context']);
self::validate_context($context);
@@ -257,11 +258,11 @@ class tour extends external_api {
\tool_usertours\event\step_shown::create([
'contextid' => $context->id,
'objectid' => $params['stepid'],
'objectid' => $params['stepid'],
'other' => [
'pageurl' => $params['pageurl'],
'tourid' => $params['tourid'],
'other' => [
'pageurl' => $params['pageurl'],
'tourid' => $params['tourid'],
'stepindex' => $params['stepindex'],
],
])->trigger();
@@ -276,10 +277,10 @@ class tour extends external_api {
*/
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'),
'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'),
]);
}
@@ -300,24 +301,47 @@ class tour extends external_api {
*/
public static function step_structure_returns() {
return new external_single_structure([
'title' => new external_value(PARAM_RAW,
'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),
'title' => new external_value(
PARAM_RAW,
'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
),
]);
}
}
+75 -87
View File
@@ -14,29 +14,18 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tour helper.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
use core\output\inplace_editable;
use tool_usertours\local\clientside_filter\clientside_filter;
defined('MOODLE_INTERNAL') || die();
/**
* Tour helper.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @package tool_usertours
*/
class helper {
/**
* @var MOVE_UP
*/
@@ -158,10 +147,10 @@ class helper {
*/
public static function get_reset_tour_for_all_link($tourid) {
return new \moodle_url('/admin/tool/usertours/configure.php', [
'id' => $tourid,
'action' => manager::ACTION_RESETFORALL,
'sesskey' => sesskey(),
]);
'id' => $tourid,
'action' => manager::ACTION_RESETFORALL,
'sesskey' => sesskey(),
]);
}
/**
@@ -204,9 +193,9 @@ class helper {
*/
public static function get_export_tour_link($tourid) {
$link = new \moodle_url('/admin/tool/usertours/configure.php', [
'action' => manager::ACTION_EXPORTTOUR,
'id' => $tourid,
]);
'action' => manager::ACTION_EXPORTTOUR,
'id' => $tourid,
]);
return $link;
}
@@ -219,8 +208,8 @@ class helper {
*/
public static function get_duplicate_tour_link($tourid) {
$link = new \moodle_url('/admin/tool/usertours/configure.php', [
'action' => manager::ACTION_DUPLICATETOUR,
'id' => $tourid,
'action' => manager::ACTION_DUPLICATETOUR,
'id' => $tourid,
]);
return $link;
@@ -234,10 +223,10 @@ class helper {
*/
public static function get_delete_tour_link($tourid) {
return new \moodle_url('/admin/tool/usertours/configure.php', [
'id' => $tourid,
'action' => manager::ACTION_DELETETOUR,
'sesskey' => sesskey(),
]);
'id' => $tourid,
'action' => manager::ACTION_DELETETOUR,
'sesskey' => sesskey(),
]);
}
/**
@@ -262,18 +251,17 @@ class helper {
* @param array $options Display options.
* @return string
*/
public static function format_icon_link($url, $icon, $alt, $iconcomponent = 'moodle', $options = array()) {
public static function format_icon_link($url, $icon, $alt, $iconcomponent = 'moodle', $options = []) {
global $OUTPUT;
return $OUTPUT->action_icon(
$url,
new \pix_icon($icon, $alt, $iconcomponent, [
'title' => $alt,
]),
null,
$options
);
$url,
new \pix_icon($icon, $alt, $iconcomponent, [
'title' => $alt,
]),
null,
$options
);
}
/**
@@ -282,7 +270,7 @@ class helper {
* @param array $options Display options.
* @return string
*/
public static function get_filler_icon($options = array()) {
public static function get_filler_icon($options = []) {
global $OUTPUT;
return \html_writer::span(
@@ -299,10 +287,10 @@ class helper {
*/
public static function get_delete_step_link($stepid) {
return new \moodle_url('/admin/tool/usertours/configure.php', [
'action' => manager::ACTION_DELETESTEP,
'id' => $stepid,
'sesskey' => sesskey(),
]);
'action' => manager::ACTION_DELETESTEP,
'id' => $stepid,
'sesskey' => sesskey(),
]);
}
/**
@@ -314,16 +302,16 @@ class helper {
public static function render_tourname_inplace_editable(tour $tour): inplace_editable {
$name = format_text(static::get_string_from_input($tour->get_name()), FORMAT_HTML);
return new inplace_editable(
'tool_usertours',
'tourname',
$tour->get_id(),
true,
\html_writer::link(
$tour->get_view_link(),
$name
),
$tour->get_name()
);
'tool_usertours',
'tourname',
$tour->get_id(),
true,
\html_writer::link(
$tour->get_view_link(),
$name
),
$tour->get_name()
);
}
/**
@@ -335,13 +323,13 @@ class helper {
public static function render_tourdescription_inplace_editable(tour $tour): inplace_editable {
$description = format_text(static::get_string_from_input($tour->get_description()), FORMAT_HTML);
return new inplace_editable(
'tool_usertours',
'tourdescription',
$tour->get_id(),
true,
$description,
$tour->get_description()
);
'tool_usertours',
'tourdescription',
$tour->get_id(),
true,
$description,
$tour->get_description()
);
}
/**
@@ -364,15 +352,15 @@ class helper {
}
$editable = new inplace_editable(
'tool_usertours',
'tourenabled',
$tour->get_id(),
true,
$OUTPUT->pix_icon($icon, $alt, 'moodle', [
'title' => $alt,
]),
$value
);
'tool_usertours',
'tourenabled',
$tour->get_id(),
true,
$OUTPUT->pix_icon($icon, $alt, 'moodle', [
'title' => $alt,
]),
$value
);
$editable->set_type_toggle();
return $editable;
@@ -388,16 +376,16 @@ class helper {
$title = format_text(static::get_string_from_input($step->get_title()), FORMAT_HTML);
return new inplace_editable(
'tool_usertours',
'stepname',
$step->get_id(),
true,
\html_writer::link(
$step->get_edit_link(),
$title
),
$step->get_title()
);
'tool_usertours',
'stepname',
$step->get_id(),
true,
\html_writer::link(
$step->get_edit_link(),
$title
),
$step->get_title()
);
}
/**
@@ -408,7 +396,7 @@ class helper {
public static function get_tours() {
global $DB;
$tours = $DB->get_records('tool_usertours_tours', array(), 'sortorder ASC');
$tours = $DB->get_records('tool_usertours_tours', [], 'sortorder ASC');
$return = [];
foreach ($tours as $tour) {
$return[$tour->id] = tour::load_from_record($tour);
@@ -435,7 +423,7 @@ class helper {
public static function get_tour_from_sortorder($sortorder) {
global $DB;
$tour = $DB->get_record('tool_usertours_tours', array('sortorder' => $sortorder));
$tour = $DB->get_record('tool_usertours_tours', ['sortorder' => $sortorder]);
return tour::load_from_record($tour);
}
@@ -460,7 +448,7 @@ class helper {
$index = 0;
foreach ($tours as $tour) {
if ($tour->sortorder != $index) {
$DB->set_field('tool_usertours_tours', 'sortorder', $index, array('id' => $tour->id));
$DB->set_field('tool_usertours_tours', 'sortorder', $index, ['id' => $tour->id]);
}
$index++;
}
@@ -508,7 +496,7 @@ class helper {
public static function get_step_from_sortorder($tourid, $sortorder) {
global $DB;
$step = $DB->get_record('tool_usertours_steps', array('tourid' => $tourid, 'sortorder' => $sortorder));
$step = $DB->get_record('tool_usertours_steps', ['tourid' => $tourid, 'sortorder' => $sortorder]);
return step::load_from_record($step);
}
@@ -538,11 +526,11 @@ class helper {
if ($tours) {
$filters = static::get_all_clientside_filters();
$tourdetails = array_map(function($tour) use ($filters) {
$tourdetails = array_map(function ($tour) use ($filters) {
return [
'tourId' => $tour->get_id(),
'startTour' => $tour->should_show_for_user(),
'filtervalues' => $tour->get_client_filter_values($filters),
'tourId' => $tour->get_id(),
'startTour' => $tour->should_show_for_user(),
'filtervalues' => $tour->get_client_filter_values($filters),
];
}, $tours);
@@ -552,8 +540,8 @@ class helper {
}
$PAGE->requires->js_call_amd('tool_usertours/usertours', 'init', [
$tourdetails,
$filternames,
$tourdetails,
$filternames,
]);
}
}
@@ -567,7 +555,7 @@ class helper {
$filters = \core_component::get_component_classes_in_namespace('tool_usertours', 'local\filter');
$filters = array_keys($filters);
$filters = array_filter($filters, function($filterclass) {
$filters = array_filter($filters, function ($filterclass) {
$rc = new \ReflectionClass($filterclass);
return $rc->isInstantiable();
});
@@ -586,7 +574,7 @@ class helper {
$filters = \core_component::get_component_classes_in_namespace('tool_usertours', 'local\clientside_filter');
$filters = array_keys($filters);
$filters = array_filter($filters, function($filterclass) {
$filters = array_filter($filters, function ($filterclass) {
$rc = new \ReflectionClass($filterclass);
return $rc->isInstantiable();
});
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Clientside filter base.
*
* @package tool_usertours
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\clientside_filter;
defined('MOODLE_INTERNAL') || die();
use stdClass;
use tool_usertours\local\filter\base;
use tool_usertours\tour;
@@ -33,6 +23,7 @@ use tool_usertours\tour;
/**
* Clientside filter base.
*
* @package tool_usertours
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -46,10 +37,10 @@ abstract class clientside_filter extends base {
public static function get_client_side_values(tour $tour): stdClass {
$data = (object) [];
if (is_a(static::class, clientside_filter::class, true)) {
if (is_a(static::class, self::class, true)) {
$data->filterdata = $tour->get_filter_values(static::get_filter_name());
}
return $data;
}
}
}
@@ -14,13 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Selector filter.
*
* @package tool_usertours
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\clientside_filter;
use stdClass;
@@ -29,6 +22,7 @@ use tool_usertours\tour;
/**
* Course filter.
*
* @package tool_usertours
* @copyright 2020 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -107,7 +101,7 @@ class cssselector extends clientside_filter {
// Filter values might not exist for tours that were created before this filter existed.
if (!$filtervalues) {
return new stdClass;
return new stdClass();
}
return (object) $filtervalues;
@@ -13,29 +13,19 @@
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Access Date filter.
*
* @package tool_usertours
* @copyright 2019 Tom Dickman <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use context;
use tool_usertours\tour;
/**
* Access date filter. Used to determine if USER should see a tour based on a particular access date.
*
* @package tool_usertours
* @copyright 2019 Tom Dickman <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class accessdate extends base {
/**
* Access date filtering constant for setting base date as account creation date.
*/
@@ -74,12 +64,11 @@ class accessdate extends base {
*/
public static function get_filter_options() {
return array(
return [
self::FILTER_ACCOUNT_CREATION => get_string('filter_date_account_creation', 'tool_usertours'),
self::FILTER_FIRST_LOGIN => get_string('filter_date_first_login', 'tool_usertours'),
self::FILTER_LAST_LOGIN => get_string('filter_date_last_login', 'tool_usertours'),
);
];
}
/**
@@ -96,8 +85,14 @@ class accessdate extends base {
$range = "{$key}_range";
$enabled = "{$key}_enabled";
$mform->addElement('advcheckbox', $enabled, get_string($key, 'tool_usertours'),
get_string('filter_accessdate_enabled', 'tool_usertours'), null, array(0, 1));
$mform->addElement(
'advcheckbox',
$enabled,
get_string($key, 'tool_usertours'),
get_string('filter_accessdate_enabled', 'tool_usertours'),
null,
[0, 1]
);
$mform->addHelpButton($enabled, $enabled, 'tool_usertours');
$mform->addElement('select', $key, ' ', self::get_filter_options());
@@ -110,7 +105,6 @@ class accessdate extends base {
]);
$mform->setDefault($range, 90 * DAYSECS);
$mform->hideIf($range, $enabled, 'notchecked');
}
/**
@@ -224,4 +218,4 @@ class accessdate extends base {
}
return $result;
}
}
}
@@ -14,24 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Filter base.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour;
use context;
/**
* Filter base.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -14,24 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Category filter.
*
* @package tool_usertours
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour;
use context;
/**
* Category filter.
*
* @package tool_usertours
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -14,24 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Course filter.
*
* @package tool_usertours
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour;
use context;
/**
* Course filter.
*
* @package tool_usertours
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -14,24 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Course format filter.
*
* @package tool_usertours
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour;
use context;
/**
* Course format filter.
*
* @package tool_usertours
* @copyright 2017 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -14,24 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Theme filter.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour;
use context;
/**
* Theme filter.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -106,7 +97,7 @@ class role extends base {
}
// Use a request cache to save on DB queries.
// We may be checking multiple tours and they'll all be for the same userid, and contextid
// We may be checking multiple tours and they'll all be for the same userid, and contextid.
$cache = \cache::make_from_params(\cache_store::MODE_REQUEST, 'tool_usertours', 'filter_role');
// Get all of the roles used in this context, including special roles such as user, and frontpageuser.
@@ -14,24 +14,15 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Theme filter.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\filter;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour;
use context;
/**
* Theme filter.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -98,7 +98,7 @@ class editstep extends \moodleform {
// Content type.
$typeoptions = [
static::CONTENTTYPE_LANGSTRING => get_string('content_type_langstring', 'tool_usertours'),
static::CONTENTTYPE_MANUAL => get_string('content_type_manual', 'tool_usertours')
static::CONTENTTYPE_MANUAL => get_string('content_type_manual', 'tool_usertours'),
];
$mform->addElement('select', 'contenttype', get_string('content_type', 'tool_usertours'), $typeoptions);
$mform->addHelpButton('contenttype', 'content_type', 'tool_usertours');
@@ -114,7 +114,7 @@ class editstep extends \moodleform {
'maxbytes' => $CFG->maxbytes,
'maxfiles' => EDITOR_UNLIMITED_FILES,
'changeformat' => 1,
'trusttext' => true
'trusttext' => true,
];
$objs = $mform->createElement('editor', 'content', get_string('content', 'tool_usertours'), null, $editoroptions);
// TODO: MDL-68540 We need to add the editor to a group element because editor element will not work with hideIf.
@@ -28,7 +28,8 @@ defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once($CFG->libdir . '/formslib.php');
use \tool_usertours\helper;
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);
@@ -39,7 +39,6 @@ require_once($CFG->libdir . '/tablelib.php');
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class step_list extends \flexible_table {
/**
* @var int $tourid The id of the tour.
*/
@@ -54,25 +53,25 @@ class step_list extends \flexible_table {
parent::__construct('steps');
$this->tourid = $tourid;
$baseurl = new \moodle_url('/tool/usertours/configure.php', array(
$baseurl = new \moodle_url('/tool/usertours/configure.php', [
'id' => $tourid,
));
]);
$this->define_baseurl($baseurl);
// Column definition.
$this->define_columns(array(
$this->define_columns([
'title',
'content',
'target',
'actions',
));
]);
$this->define_headers(array(
get_string('title', 'tool_usertours'),
$this->define_headers([
get_string('title', 'tool_usertours'),
get_string('content', 'tool_usertours'),
get_string('target', 'tool_usertours'),
get_string('target', 'tool_usertours'),
get_string('actions', 'tool_usertours'),
));
]);
$this->set_attribute('class', 'admintable generaltable steptable');
$this->setup();
@@ -98,8 +97,14 @@ class step_list extends \flexible_table {
protected function col_content(step $step) {
$content = $step->get_content();
$systemcontext = \context_system::instance();
$content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $systemcontext->id,
'tool_usertours', 'stepcontent', $step->get_id());
$content = file_rewrite_pluginfile_urls(
$content,
'pluginfile.php',
$systemcontext->id,
'tool_usertours',
'stepcontent',
$step->get_id()
);
$content = helper::get_string_from_input($content);
$content = step::get_step_image_from_input($content);
@@ -135,8 +140,11 @@ class step_list extends \flexible_table {
if ($step->is_last_step()) {
$actions[] = helper::get_filler_icon();
} else {
$actions[] = helper::format_icon_link($step->get_movedown_link(), 't/down',
get_string('movestepdown', 'tool_usertours'));
$actions[] = helper::format_icon_link(
$step->get_movedown_link(),
't/down',
get_string('movestepdown', 'tool_usertours')
);
}
$actions[] = helper::format_icon_link($step->get_edit_link(), 't/edit', get_string('edit'));
@@ -38,7 +38,6 @@ require_once($CFG->libdir . '/tablelib.php');
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tour_list extends \flexible_table {
/** @var int The count of all tours. */
protected int $tourcount = 0;
@@ -52,21 +51,21 @@ class tour_list extends \flexible_table {
$this->define_baseurl($baseurl);
// Column definition.
$this->define_columns(array(
$this->define_columns([
'name',
'description',
'appliesto',
'enabled',
'actions',
));
]);
$this->define_headers(array(
$this->define_headers([
get_string('name', 'tool_usertours'),
get_string('description', 'tool_usertours'),
get_string('appliesto', 'tool_usertours'),
get_string('enabled', 'tool_usertours'),
get_string('actions', 'tool_usertours'),
));
]);
$this->set_attribute('class', 'admintable generaltable');
$this->setup();
@@ -129,22 +128,32 @@ class tour_list extends \flexible_table {
if ($tour->is_first_tour()) {
$actions[] = helper::get_filler_icon();
} else {
$actions[] = helper::format_icon_link($tour->get_moveup_link(), 't/up',
get_string('movetourup', 'tool_usertours'));
$actions[] = helper::format_icon_link(
$tour->get_moveup_link(),
't/up',
get_string('movetourup', 'tool_usertours')
);
}
if ($tour->is_last_tour($this->tourcount)) {
$actions[] = helper::get_filler_icon();
} else {
$actions[] = helper::format_icon_link($tour->get_movedown_link(), 't/down',
get_string('movetourdown', 'tool_usertours'));
$actions[] = helper::format_icon_link(
$tour->get_movedown_link(),
't/down',
get_string('movetourdown', 'tool_usertours')
);
}
$actions[] = helper::format_icon_link($tour->get_view_link(), 't/viewdetails', get_string('view'));
$actions[] = helper::format_icon_link($tour->get_edit_link(), 't/edit', get_string('edit'));
$actions[] = helper::format_icon_link($tour->get_duplicate_link(), 't/copy', get_string('duplicate'));
$actions[] = helper::format_icon_link($tour->get_export_link(), 't/export',
get_string('exporttour', 'tool_usertours'), 'tool_usertours');
$actions[] = helper::format_icon_link(
$tour->get_export_link(),
't/export',
get_string('exporttour', 'tool_usertours'),
'tool_usertours'
);
$actions[] = helper::format_icon_link($tour->get_delete_link(), 't/delete', get_string('delete'), null, [
'data-action' => 'delete',
'data-id' => $tour->get_id(),
@@ -14,23 +14,14 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Target base.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\target;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\step;
/**
* Target base.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours\local\target;
/**
* Block target.
*
@@ -21,21 +23,7 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\target;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\step;
/**
* Block target.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class block extends base {
/**
* Convert the target value to a valid CSS selector for use in the
* output configuration.
@@ -101,8 +89,12 @@ class block extends base {
* @param MoodleQuickForm $mform The form to add configuration to.
*/
public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
$mform->hideIf('targetvalue_block', 'targettype', 'noteq',
\tool_usertours\target::get_target_constant_for_class(self::class));
$mform->hideIf(
'targetvalue_block',
'targettype',
'noteq',
\tool_usertours\target::get_target_constant_for_class(self::class)
);
}
/**
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours\local\target;
/**
* Selector target.
*
@@ -21,21 +23,7 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\target;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\step;
/**
* Selector target.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class selector extends base {
/**
* Convert the target value to a valid CSS selector for use in the
* output configuration.
@@ -91,8 +79,12 @@ class selector extends base {
* @param MoodleQuickForm $mform The form to add configuration to.
*/
public static function add_disabled_constraints_to_form(\MoodleQuickForm $mform) {
$mform->hideIf('targetvalue_selector', 'targettype', 'noteq',
\tool_usertours\target::get_target_constant_for_class(self::class));
$mform->hideIf(
'targetvalue_selector',
'targettype',
'noteq',
\tool_usertours\target::get_target_constant_for_class(self::class)
);
}
/**
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours\local\target;
/**
* A step designed to be orphaned.
*
@@ -21,19 +23,6 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\local\target;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\step;
/**
* A step designed to be orphaned.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class unattached extends base {
/**
* @var array $forcedsettings The settings forced by this type.
+9 -17
View File
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tour manager.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\local\forms;
use tool_usertours\local\table;
use core\notification;
@@ -33,11 +23,11 @@ use core\notification;
/**
* Tour manager.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class manager {
/**
* @var ACTION_LISTTOURS The action to get the list of tours.
*/
@@ -163,7 +153,7 @@ class manager {
$PAGE->set_primary_active_tab('siteadminnode');
// Add the main content.
switch($action) {
switch ($action) {
case self::ACTION_NEWTOUR:
case self::ACTION_EDITTOUR:
$this->edit_tour(optional_param('id', null, PARAM_INT));
@@ -356,7 +346,6 @@ class manager {
if ($id) {
$tour = tour::instance($id);
$PAGE->navbar->add(helper::get_string_from_input($tour->get_name()), $tour->get_edit_link());
} else {
$tour = new tour();
$PAGE->navbar->add(get_string('newtour', 'tool_usertours'), $tour->get_edit_link());
@@ -374,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);
@@ -403,6 +393,7 @@ class manager {
foreach (helper::get_all_filters() as $filterclass) {
$filterclass::prepare_filter_values_for_form($tour, $data);
}
$form->set_data($data);
}
@@ -568,7 +559,7 @@ class manager {
require_sesskey();
$tour = $DB->get_record('tool_usertours_tours', array('id' => $tourid));
$tour = $DB->get_record('tool_usertours_tours', ['id' => $tourid]);
$tour->enabled = $visibility;
$DB->update_record('tool_usertours_tours', $tour);
@@ -784,9 +775,10 @@ class manager {
*/
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)) {
if (
($tour->is_first_tour() && $direction == helper::MOVE_UP) ||
($tour->is_last_tour() && $direction == helper::MOVE_DOWN)
) {
return;
}
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours\output;
/**
* Renderer.
*
@@ -21,16 +23,5 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\output;
defined('MOODLE_INTERNAL') || die();
/**
* Renderer.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends \plugin_renderer_base {
}
+18 -13
View File
@@ -38,7 +38,6 @@ use tool_usertours\step as stepsource;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class step implements \renderable {
/**
* @var The step instance.
*/
@@ -65,8 +64,14 @@ class step implements \renderable {
$content = $step->get_content();
$systemcontext = \context_system::instance();
$content = file_rewrite_pluginfile_urls($content, 'pluginfile.php', $systemcontext->id,
'tool_usertours', 'stepcontent', $step->get_id());
$content = file_rewrite_pluginfile_urls(
$content,
'pluginfile.php',
$systemcontext->id,
'tool_usertours',
'stepcontent',
$step->get_id()
);
$content = helper::get_string_from_input($content);
$content = $step::get_step_image_from_input($content);
@@ -74,17 +79,17 @@ class step implements \renderable {
$result = (object) [
'stepid' => $step->get_id(),
'title' => \core_external\util::format_text(
helper::get_string_from_input($step->get_title()),
FORMAT_HTML,
$PAGE->context->id,
'tool_usertours'
)[0],
helper::get_string_from_input($step->get_title()),
FORMAT_HTML,
$PAGE->context->id,
'tool_usertours'
)[0],
'content' => \core_external\util::format_text(
$content,
$step->get_contentformat(),
$PAGE->context->id,
'tool_usertours'
)[0],
$content,
$step->get_contentformat(),
$PAGE->context->id,
'tool_usertours'
)[0],
'element' => $step->get_target()->convert_to_css(),
];
+4 -14
View File
@@ -14,6 +14,10 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours\output;
use tool_usertours\tour as toursource;
/**
* Tour renderable.
*
@@ -21,21 +25,7 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\output;
defined('MOODLE_INTERNAL') || die();
use tool_usertours\tour as toursource;
/**
* Tour renderable.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tour implements \renderable {
/**
* @var The tour instance.
*/
@@ -14,25 +14,16 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for tool_usertours.
*
* @package tool_usertours
* @copyright 2018 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\privacy;
use \core_privacy\local\request\writer;
use \core_privacy\local\metadata\collection;
use \core_privacy\local\request\transform;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\request\writer;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\transform;
/**
* Implementation of the privacy subsystem plugin provider for the user tours feature.
*
* @package tool_usertours
* @copyright 2018 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -41,9 +32,7 @@ class provider implements
\core_privacy\local\metadata\provider,
// This plugin has some sitewide user preferences to export.
\core_privacy\local\request\user_preference_provider
{
\core_privacy\local\request\user_preference_provider {
/**
* Returns meta data about this system.
*
+18 -24
View File
@@ -14,6 +14,11 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours;
use context_system;
use stdClass;
/**
* Step class.
*
@@ -21,22 +26,7 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
use context_system;
use stdClass;
defined('MOODLE_INTERNAL') || die();
/**
* Step class.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class step {
/**
* @var int $id The id of the step.
*/
@@ -137,7 +127,7 @@ class step {
global $DB;
return $this->reload_from_record(
$DB->get_record('tool_usertours_steps', array('id' => $id))
$DB->get_record('tool_usertours_steps', ['id' => $id])
);
}
@@ -414,7 +404,7 @@ class step {
*/
public function get_config($key = null, $default = null) {
if ($this->config === null) {
$this->config = (object) array();
$this->config = (object) [];
}
if ($key === null) {
@@ -448,7 +438,7 @@ class step {
*/
public function set_config($key, $value) {
if ($this->config === null) {
$this->config = (object) array();
$this->config = (object) [];
}
if ($value === null) {
@@ -497,7 +487,7 @@ class step {
'name' => $file->get_filename(),
'path' => $file->get_filepath(),
'content' => base64_encode($file->get_content()),
'encode' => 'base64'
'encode' => 'base64',
];
}
@@ -635,7 +625,7 @@ class step {
return;
}
$DB->delete_records('tool_usertours_steps', array('id' => $this->id));
$DB->delete_records('tool_usertours_steps', ['id' => $this->id]);
$this->get_tour()->reset_step_sortorder();
// Notify of a change to the step configuration.
@@ -817,15 +807,19 @@ class step {
return $content;
}
$content = preg_replace_callback('%@@PIXICON::(?P<identifier>([^::]*))::(?P<component>([^@@]*))@@%',
function(array $matches) {
$content = preg_replace_callback(
'%@@PIXICON::(?P<identifier>([^::]*))::(?P<component>([^@@]*))@@%',
function (array $matches) {
global $OUTPUT;
$component = $matches['component'];
if ($component == 'moodle') {
$component = 'core';
}
return \html_writer::img($OUTPUT->image_url($matches['identifier'], $component)->out(false), '',
['class' => 'img-fluid']);
return \html_writer::img(
$OUTPUT->image_url($matches['identifier'], $component)->out(false),
'',
['class' => 'img-fluid']
);
},
$content
);
+2 -12
View File
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours;
/**
* Target class.
*
@@ -21,19 +23,7 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
defined('MOODLE_INTERNAL') || die();
/**
* Target class.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class target {
/**
* @var TARGET_SELECTOR The target is a CSS selector.
*/
+47 -22
View File
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
namespace tool_usertours;
/**
* Tour class.
*
@@ -21,21 +23,7 @@
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
use tool_usertours\local\clientside_filter\clientside_filter;
defined('MOODLE_INTERNAL') || die();
/**
* Tour class.
*
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class tour {
/**
* The tour is currently disabled
*
@@ -64,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.
*/
@@ -157,7 +151,7 @@ class tour {
global $DB;
return $this->reload_from_record(
$DB->get_record('tool_usertours_tours', array('id' => $id), '*', MUST_EXIST)
$DB->get_record('tool_usertours_tours', ['id' => $id], '*', MUST_EXIST)
);
}
@@ -424,7 +418,7 @@ class tour {
* @return object
*/
public function to_record() {
return (object) array(
return (object) [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
@@ -434,7 +428,7 @@ class tour {
'endtourlabel' => $this->endtourlabel,
'configdata' => json_encode($this->config),
'displaystepnumbers' => $this->displaystepnumbers,
);
];
}
/**
@@ -519,7 +513,7 @@ class tour {
*/
public function get_config($key = null, $default = null) {
if ($this->config === null) {
$this->config = (object) array();
$this->config = (object) [];
}
if ($key === null) {
return $this->config;
@@ -545,7 +539,7 @@ class tour {
*/
public function set_config($key, $value) {
if ($this->config === null) {
$this->config = (object) array();
$this->config = (object) [];
}
$this->config->$key = $value;
$this->dirty = true;
@@ -602,7 +596,7 @@ class tour {
}
// Remove the configuration for the tour.
$DB->delete_records('tool_usertours_tours', array('id' => $this->id));
$DB->delete_records('tool_usertours_tours', ['id' => $this->id]);
helper::reset_tour_sortorder();
$this->remove_user_preferences();
@@ -617,11 +611,11 @@ class tour {
*/
public function reset_step_sortorder() {
global $DB;
$steps = $DB->get_records('tool_usertours_steps', array('tourid' => $this->id), 'sortorder ASC', 'id');
$steps = $DB->get_records('tool_usertours_steps', ['tourid' => $this->id], 'sortorder ASC', 'id');
$index = 0;
foreach ($steps as $step) {
$DB->set_field('tool_usertours_steps', 'sortorder', $index, array('id' => $step->id));
$DB->set_field('tool_usertours_steps', 'sortorder', $index, ['id' => $step->id]);
$index++;
}
@@ -653,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) {
@@ -775,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));
}
@@ -872,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);
}
}
+2 -2
View File
@@ -31,5 +31,5 @@ $pluginmanager = new \tool_usertours\manager();
$PAGE->set_context(context_system::instance());
$pluginmanager->execute(
$action
);
$action
);
+3 -3
View File
@@ -24,13 +24,13 @@
defined('MOODLE_INTERNAL') || die();
$capabilities = array(
$capabilities = [
'tool/usertours:managetours' => [
'captype' => 'write',
'riskbitmask' => RISK_XSS,
'contextlevel' => CONTEXT_SYSTEM,
'archetypes' => [
'manager' => CAP_ALLOW,
]
],
],
);
];
+6 -6
View File
@@ -24,19 +24,19 @@
defined('MOODLE_INTERNAL') || die();
$definitions = array(
'tourdata' => array(
$definitions = [
'tourdata' => [
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'simpledata' => true,
'staticacceleration' => true,
'staticaccelerationsize' => 1,
),
'stepdata' => array(
],
'stepdata' => [
'mode' => cache_store::MODE_APPLICATION,
'simplekeys' => true,
'simpledata' => true,
'staticacceleration' => true,
'staticaccelerationsize' => 1,
),
);
],
];
+10 -10
View File
@@ -24,40 +24,40 @@
defined('MOODLE_INTERNAL') || die();
$functions = array(
'tool_usertours_fetch_and_start_tour' => array(
$functions = [
'tool_usertours_fetch_and_start_tour' => [
'classname' => 'tool_usertours\external\tour',
'methodname' => 'fetch_and_start_tour',
'description' => 'Fetch the specified tour',
'type' => 'read',
'capabilities' => '',
'ajax' => true,
),
],
'tool_usertours_step_shown' => array(
'tool_usertours_step_shown' => [
'classname' => 'tool_usertours\external\tour',
'methodname' => 'step_shown',
'description' => 'Mark the specified step as completed for the current user',
'type' => 'write',
'capabilities' => '',
'ajax' => true,
),
],
'tool_usertours_complete_tour' => array(
'tool_usertours_complete_tour' => [
'classname' => 'tool_usertours\external\tour',
'methodname' => 'complete_tour',
'description' => 'Mark the specified tour as completed for the current user',
'type' => 'write',
'capabilities' => '',
'ajax' => true,
),
],
'tool_usertours_reset_tour' => array(
'tool_usertours_reset_tour' => [
'classname' => 'tool_usertours\external\tour',
'methodname' => 'reset_tour',
'description' => 'Remove the specified tour',
'type' => 'write',
'capabilities' => '',
'ajax' => true,
),
);
],
];
@@ -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?';
@@ -24,9 +24,9 @@ use tool_usertours\local\filter\accessdate;
* @package tool_usertours
* @copyright 2019 Tom Dickman <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\local\filter\accessdate
*/
class accessdate_filter_test extends \advanced_testcase {
public function setUp(): void {
$this->resetAfterTest(true);
}
@@ -36,7 +36,7 @@ class accessdate_filter_test extends \advanced_testcase {
*
* @return array
*/
public function filter_matches_provider() {
public static function filter_matches_provider(): array {
return [
'No config set; Matches' => [
[],
@@ -45,61 +45,61 @@ class accessdate_filter_test extends \advanced_testcase {
],
'Filter is not enabled; Match' => [
['filter_accessdate' => accessdate::FILTER_ACCOUNT_CREATION, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 0],
'filter_accessdate_enabled' => 0, ],
['timecreated' => time() - (89 * DAYSECS)],
true,
],
'Filter is not enabled (tour would not be displayed if it was); Match' => [
['filter_accessdate' => accessdate::FILTER_ACCOUNT_CREATION, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 0],
'filter_accessdate_enabled' => 0, ],
['timecreated' => time() - (91 * DAYSECS)],
true,
],
'Inside range of account creation date; Match' => [
['filter_accessdate' => accessdate::FILTER_ACCOUNT_CREATION, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['timecreated' => time() - (89 * DAYSECS)],
true,
],
'Outside range of account creation date; No match' => [
['filter_accessdate' => accessdate::FILTER_ACCOUNT_CREATION, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['timecreated' => time() - (91 * DAYSECS)],
false,
],
'Inside range of first login date; Match' => [
['filter_accessdate' => accessdate::FILTER_FIRST_LOGIN, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['firstaccess' => time() - (89 * DAYSECS)],
true,
],
'Outside range of first login date; No match' => [
['filter_accessdate' => accessdate::FILTER_FIRST_LOGIN, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['firstaccess' => time() - (91 * DAYSECS)],
false,
],
'Inside range of last login date; Match' => [
['filter_accessdate' => accessdate::FILTER_LAST_LOGIN, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['lastlogin' => time() - (89 * DAYSECS)],
true,
],
'Outside range of last login date; No match' => [
['filter_accessdate' => accessdate::FILTER_LAST_LOGIN, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['lastlogin' => time() - (91 * DAYSECS)],
false,
],
'User has never logged in, but tour should be visible; Match' => [
['filter_accessdate' => accessdate::FILTER_LAST_LOGIN, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['lastlogin' => 0, 'timecreated' => time() - (89 * DAYSECS)],
true,
],
'User has never logged in, and tour should not be visible; No match' => [
['filter_accessdate' => accessdate::FILTER_LAST_LOGIN, 'filter_accessdate_range' => 90 * DAYSECS,
'filter_accessdate_enabled' => 1],
'filter_accessdate_enabled' => 1, ],
['lastlogin' => 0, 'timecreated' => time() - (91 * DAYSECS)],
false,
],
@@ -115,7 +115,7 @@ class accessdate_filter_test extends \advanced_testcase {
* @param array $userstate any user state required for test.
* @param bool $expected result expected.
*/
public function test_filter_matches($filtervalues, $userstate, $expected) {
public function test_filter_matches($filtervalues, $userstate, $expected): void {
$course = $this->getDataGenerator()->create_course();
$context = \context_course::instance($course->id);
@@ -127,5 +127,4 @@ class accessdate_filter_test extends \advanced_testcase {
$this->assertEquals($expected, accessdate::filter_matches($tour, $context));
}
}
@@ -25,7 +25,7 @@
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
use Behat\Gherkin\Node\TableNode as TableNode;
use Behat\Gherkin\Node\TableNode;
/**
* User tour related steps definitions.
*
@@ -35,7 +35,6 @@ use Behat\Gherkin\Node\TableNode as TableNode;
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_tool_usertours extends behat_base {
/**
* Add a new user tour.
*
@@ -90,8 +89,9 @@ class behat_tool_usertours extends behat_base {
* @Given /^I open the User tour settings page$/
*/
public function i_open_the_user_tour_settings_page() {
$this->execute('behat_navigation::i_navigate_to_in_site_administration',
get_string('appearance', 'admin') . ' > ' .
$this->execute(
'behat_navigation::i_navigate_to_in_site_administration',
get_string('appearance', 'admin') . ' > ' .
get_string('usertours', 'tool_usertours')
);
}
@@ -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"
+21 -21
View File
@@ -27,6 +27,7 @@ require_once(__DIR__ . '/helper_trait.php');
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\cache
*/
class cache_test extends \advanced_testcase {
// There are shared helpers for these tests in the helper trait.
@@ -35,7 +36,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that get_enabled_tourdata does not return disabled tours.
*/
public function test_get_enabled_tourdata_disabled() {
public function test_get_enabled_tourdata_disabled(): void {
$this->resetAfterTest();
$tour = $this->helper_create_tour((object)['enabled' => false]);
@@ -48,7 +49,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that get_enabled_tourdata does not return an enabled but empty tour.
*/
public function test_get_enabled_tourdata_enabled_no_steps() {
public function test_get_enabled_tourdata_enabled_no_steps(): void {
$this->resetAfterTest();
$this->helper_create_tour();
@@ -60,7 +61,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that get_enabled_tourdata returns a tour with steps.
*/
public function test_get_enabled_tourdata_enabled() {
public function test_get_enabled_tourdata_enabled(): void {
$this->resetAfterTest();
// Create two tours. Only the second has steps.
@@ -79,7 +80,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that get_enabled_tourdata returns tours in the correct sortorder
*/
public function test_get_enabled_tourdata_enabled_sortorder() {
public function test_get_enabled_tourdata_enabled_sortorder(): void {
$this->resetAfterTest();
$tour1 = $this->helper_create_tour();
@@ -100,7 +101,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that caching prevents additional DB reads.
*/
public function test_get_enabled_tourdata_single_fetch() {
public function test_get_enabled_tourdata_single_fetch(): void {
global $DB;
$this->resetAfterTest();
@@ -118,7 +119,6 @@ class cache_test extends \advanced_testcase {
// No subsequent reads for any further calls.
$matches = \tool_usertours\cache::get_enabled_tourdata();
$this->assertEquals(1, $DB->perf_get_reads() - $startreads);
}
/**
@@ -126,31 +126,31 @@ class cache_test extends \advanced_testcase {
*
* @return array
*/
public function get_matching_tourdata_provider() {
public static function get_matching_tourdata_provider(): array {
$tourconfigs = [
(object) [
'name' => 'my_exact_1',
'pathmatch' => '/my/view.php'
'pathmatch' => '/my/view.php',
],
(object) [
'name' => 'my_failed_regex',
'pathmatch' => '/my/*.php'
'pathmatch' => '/my/*.php',
],
(object) [
'name' => 'my_glob_1',
'pathmatch' => '/my/%'
'pathmatch' => '/my/%',
],
(object) [
'name' => 'my_glob_2',
'pathmatch' => '/my/%'
'pathmatch' => '/my/%',
],
(object) [
'name' => 'frontpage_only',
'pathmatch' => 'FRONTPAGE'
'pathmatch' => 'FRONTPAGE',
],
(object) [
'name' => 'frontpage_match',
'pathmatch' => '/?%'
'pathmatch' => '/?%',
],
];
@@ -186,7 +186,7 @@ class cache_test extends \advanced_testcase {
* @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) {
public function test_get_matching_tourdata($tourconfigs, $targetmatch, $expected): void {
$this->resetAfterTest();
foreach ($tourconfigs as $tourconfig) {
$tour = $this->helper_create_tour($tourconfig);
@@ -205,7 +205,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that notify_tour_change clears the cache.
*/
public function test_notify_tour_change() {
public function test_notify_tour_change(): void {
global $DB;
$this->resetAfterTest();
@@ -236,7 +236,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that get_stepdata returns an empty array when no steps were found.
*/
public function test_get_stepdata_no_steps() {
public function test_get_stepdata_no_steps(): void {
$this->resetAfterTest();
$tour = $this->helper_create_tour((object)['enabled' => false]);
@@ -249,7 +249,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that get_stepdata returns an empty array when no steps were found.
*/
public function test_get_stepdata_correct_tour() {
public function test_get_stepdata_correct_tour(): void {
$this->resetAfterTest();
$tour1 = $this->helper_create_tour((object)['enabled' => false]);
@@ -274,7 +274,7 @@ class cache_test extends \advanced_testcase {
* 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() {
public function test_get_stepdata_ordered_steps(): void {
$this->resetAfterTest();
$tour = $this->helper_create_tour((object)['enabled' => false]);
@@ -290,7 +290,7 @@ class cache_test extends \advanced_testcase {
$this->assertCount(4, $data);
// Re-order the steps.
usort($steps, function($a, $b) {
usort($steps, function ($a, $b) {
return ($a->get_sortorder() < $b->get_sortorder()) ? -1 : 1;
});
@@ -303,7 +303,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that caching prevents additional DB reads.
*/
public function test_get_stepdata_single_fetch() {
public function test_get_stepdata_single_fetch(): void {
global $DB;
$this->resetAfterTest();
@@ -324,7 +324,7 @@ class cache_test extends \advanced_testcase {
/**
* Test that notify_step_change clears the cache.
*/
public function test_notify_step_change() {
public function test_notify_step_change(): void {
global $DB;
$this->resetAfterTest();
+3 -13
View File
@@ -14,35 +14,25 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Tests for helper.
*
* @package tool_usertours
* @copyright 2022 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours;
use advanced_testcase;
defined('MOODLE_INTERNAL') || die();
/**
* Tests for helper.
*
* @package tool_usertours
* @copyright 2022 Huong Nguyen <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\helper
*/
class helper_test extends advanced_testcase {
/**
* Data Provider for get_string_from_input.
*
* @return array
*/
public function get_string_from_input_provider(): array {
public static function get_string_from_input_provider(): array {
return [
'Text' => [
'example',
@@ -78,7 +68,7 @@ class helper_test extends advanced_testcase {
* @param string $string The string to test
* @param string $expected The expected result
*/
public function test_get_string_from_input($string, $expected) {
public function test_get_string_from_input($string, $expected): void {
$this->assertEquals($expected, helper::get_string_from_input($string));
}
}
+1 -11
View File
@@ -14,16 +14,6 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Helpers for unit tests.
*
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Helpers for unit tests.
*
@@ -47,7 +37,7 @@ trait tool_usertours_helper_trait {
'name' => '',
'description' => '',
'configdata' => '',
'displaystepnumbers' => true
'displaystepnumbers' => true,
];
if ($tourconfig === null) {
+118 -118
View File
@@ -28,6 +28,7 @@ require_once(__DIR__ . '/helper_trait.php');
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\manager
*/
class manager_test extends \advanced_testcase {
// There are shared helpers for these tests in the helper trait.
@@ -74,28 +75,28 @@ class manager_test extends \advanced_testcase {
*
* @return array
*/
public function sesskey_required_provider() {
public static function sesskey_required_provider(): array {
$tourid = rand(1, 100);
$stepid = rand(1, 100);
return [
'Tour removal' => [
'delete_tour',
[$tourid],
],
'Step removal' => [
'delete_step',
[$stepid],
],
'Tour visibility' => [
'show_hide_tour',
[$tourid, true],
],
'Move step' => [
'move_step',
[$stepid],
],
];
'Tour removal' => [
'delete_tour',
[$tourid],
],
'Step removal' => [
'delete_step',
[$stepid],
],
'Tour visibility' => [
'show_hide_tour',
[$tourid, true],
],
'Move step' => [
'move_step',
[$stepid],
],
];
}
/**
@@ -105,12 +106,11 @@ class manager_test extends \advanced_testcase {
* @param string $function The function to test
* @param array $arguments The arguments to pass with it
*/
public function test_sesskey_required($function, $arguments) {
public function test_sesskey_required($function, $arguments): void {
$manager = new \tool_usertours\manager();
$rc = new \ReflectionClass('\tool_usertours\manager');
$rcm = $rc->getMethod($function);
$rcm->setAccessible(true);
$this->expectException('moodle_exception');
$rcm->invokeArgs($manager, $arguments);
@@ -121,7 +121,7 @@ class manager_test extends \advanced_testcase {
*
* @return array
*/
public function move_tour_provider() {
public static function move_tour_provider(): array {
$alltours = [
['name' => 'Tour 1'],
['name' => 'Tour 2'],
@@ -167,7 +167,7 @@ class manager_test extends \advanced_testcase {
* @param int $expectedsortorder
* @return void
*/
public function test_move_tour($alltours, $movetourname, $direction, $expectedsortorder) {
public function test_move_tour($alltours, $movetourname, $direction, $expectedsortorder): void {
global $DB;
$this->resetAfterTest();
@@ -186,7 +186,6 @@ class manager_test extends \advanced_testcase {
// 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.
@@ -198,114 +197,115 @@ class manager_test extends \advanced_testcase {
*
* @return array
*/
public function get_matching_tours_provider() {
public static function get_matching_tours_provider(): array {
global $CFG;
$alltours = [
[
'pathmatch' => '/my/%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/my/%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/my/%',
'enabled' => true,
'name' => 'My tour enabled',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/my/%',
'enabled' => true,
'name' => 'My tour enabled',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/my/%',
'enabled' => true,
'name' => 'My tour enabled 2',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/my/%',
'enabled' => true,
'name' => 'My tour enabled 2',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/my/%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/my/%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/course/?id=%foo=bar',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/course/?id=%foo=bar',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/course/?id=%foo=bar',
'enabled' => true,
'name' => 'course tour with additional params enabled',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/course/?id=%foo=bar',
'enabled' => true,
'name' => 'course tour with additional params enabled',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/course/?id=%foo=bar',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/course/?id=%foo=bar',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/course/?id=%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/course/?id=%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/course/?id=%',
'enabled' => true,
'name' => 'course tour enabled',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/course/?id=%',
'enabled' => true,
'name' => 'course tour enabled',
'description' => '',
'configdata' => '',
],
[
'pathmatch' => '/course/?id=%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
'pathmatch' => '/course/?id=%',
'enabled' => false,
'name' => 'Failure',
'description' => '',
'configdata' => '',
],
];
return [
'No matches found' => [
$alltours,
$CFG->wwwroot . '/some/invalid/value',
[],
],
'Never return a disabled tour' => [
$alltours,
$CFG->wwwroot . '/my/index.php',
['My tour enabled', 'My tour enabled 2'],
],
'My not course' => [
$alltours,
$CFG->wwwroot . '/my/index.php',
['My tour enabled', 'My tour enabled 2'],
],
'My with params' => [
$alltours,
$CFG->wwwroot . '/my/index.php?id=42',
['My tour enabled', 'My tour enabled 2'],
],
'Course with params' => [
$alltours,
$CFG->wwwroot . '/course/?id=42',
['course tour enabled'],
],
'Course with params and trailing content' => [
$alltours,
$CFG->wwwroot . '/course/?id=42&foo=bar',
['course tour with additional params enabled', 'course tour enabled'],
],
];
return
[
'No matches found' => [
$alltours,
$CFG->wwwroot . '/some/invalid/value',
[],
],
'Never return a disabled tour' => [
$alltours,
$CFG->wwwroot . '/my/index.php',
['My tour enabled', 'My tour enabled 2'],
],
'My not course' => [
$alltours,
$CFG->wwwroot . '/my/index.php',
['My tour enabled', 'My tour enabled 2'],
],
'My with params' => [
$alltours,
$CFG->wwwroot . '/my/index.php?id=42',
['My tour enabled', 'My tour enabled 2'],
],
'Course with params' => [
$alltours,
$CFG->wwwroot . '/course/?id=42',
['course tour enabled'],
],
'Course with params and trailing content' => [
$alltours,
$CFG->wwwroot . '/course/?id=42&foo=bar',
['course tour with additional params enabled', 'course tour enabled'],
],
];
}
/**
@@ -316,7 +316,7 @@ class manager_test extends \advanced_testcase {
* @param string $url The URL to test.
* @param array $expected List of names of the expected matching tours.
*/
public function test_get_matching_tours(array $alltours, string $url, array $expected) {
public function test_get_matching_tours(array $alltours, string $url, array $expected): void {
$this->resetAfterTest();
$this->setGuestUser();
@@ -336,7 +336,7 @@ class manager_test extends \advanced_testcase {
/**
* Test that no matching tours are returned if there is pending site policy agreement.
*/
public function test_get_matching_tours_for_user_without_site_policy_agreed() {
public function test_get_matching_tours_for_user_without_site_policy_agreed(): void {
global $CFG;
$this->resetAfterTest();
@@ -14,18 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Unit tests for the tool_usertours implementation of the privacy API.
*
* @package tool_usertours
* @category test
* @copyright 2018 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace tool_usertours\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\metadata\collection;
use core_privacy\local\request\writer;
use tool_usertours\tour;
@@ -34,11 +24,13 @@ use tool_usertours\privacy\provider;
/**
* Unit tests for the tool_usertours implementation of the privacy API.
*
* @package tool_usertours
* @category test
* @copyright 2018 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\privacy\provider
*/
class provider_test extends \core_privacy\tests\provider_testcase {
/**
* Helper method for creating a tour
*
@@ -56,7 +48,7 @@ class provider_test extends \core_privacy\tests\provider_testcase {
/**
* Ensure that get_metadata exports valid content.
*/
public function test_get_metadata() {
public function test_get_metadata(): void {
$items = new collection('tool_usertours');
$result = provider::get_metadata($items);
$this->assertSame($items, $result);
@@ -66,7 +58,7 @@ class provider_test extends \core_privacy\tests\provider_testcase {
/**
* Ensure that export_user_preferences returns no data if the user has completed no tours.
*/
public function test_export_user_preferences_no_pref() {
public function test_export_user_preferences_no_pref(): void {
$user = \core_user::get_user_by_username('admin');
provider::export_user_preferences($user->id);
@@ -78,7 +70,7 @@ class provider_test extends \core_privacy\tests\provider_testcase {
/**
* Ensure that export_user_preferences returns request completion data.
*/
public function test_export_user_preferences_completed() {
public function test_export_user_preferences_completed(): void {
global $DB;
$this->resetAfterTest();
@@ -101,7 +93,7 @@ class provider_test extends \core_privacy\tests\provider_testcase {
/**
* Ensure that export_user_preferences returns request completion data.
*/
public function test_export_user_preferences_requested() {
public function test_export_user_preferences_requested(): void {
global $DB;
$this->resetAfterTest();
@@ -149,14 +141,16 @@ class provider_test extends \core_privacy\tests\provider_testcase {
$this->assertCount(1, $prefs);
// We should have received back the "completed tour" preference of the test user.
$this->assertStringStartsWith('You last marked the "' . $tour->get_name() . '" user tour as completed on',
reset($prefs)->description);
$this->assertStringStartsWith(
'You last marked the "' . $tour->get_name() . '" user tour as completed on',
reset($prefs)->description
);
}
/**
* Ensure that export_user_preferences excludes deleted tours.
*/
public function test_export_user_preferences_deleted_tour() {
public function test_export_user_preferences_deleted_tour(): void {
global $DB;
$this->resetAfterTest();
@@ -22,9 +22,9 @@ namespace tool_usertours;
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\local\filter\role
*/
class role_filter_test extends \advanced_testcase {
/**
* @var $course Test course
*/
@@ -72,7 +72,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when any is set.
*/
public function test_filter_matches_any() {
public function test_filter_matches_any(): void {
$context = \context_course::instance($this->course->id);
// Note: No need to persist this tour.
@@ -93,7 +93,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when one role is set.
*/
public function test_filter_matches_single_role() {
public function test_filter_matches_single_role(): void {
$context = \context_course::instance($this->course->id);
$roles = [
@@ -122,7 +122,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when multiple roles are set.
*/
public function test_filter_matches_multiple_role() {
public function test_filter_matches_multiple_role(): void {
$context = \context_course::instance($this->course->id);
$roles = [
@@ -152,7 +152,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when one user has multiple roles.
*/
public function test_filter_matches_multiple_role_one_user() {
public function test_filter_matches_multiple_role_one_user(): void {
$context = \context_course::instance($this->course->id);
$roles = [
@@ -184,7 +184,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when it is targetted at an admin.
*/
public function test_filter_matches_multiple_role_only_admin() {
public function test_filter_matches_multiple_role_only_admin(): void {
$context = \context_course::instance($this->course->id);
$roles = [
@@ -212,7 +212,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when multiple roles are set, including an admin user.
*/
public function test_filter_matches_multiple_role_including_admin() {
public function test_filter_matches_multiple_role_including_admin(): void {
$context = \context_course::instance($this->course->id);
$roles = [
@@ -243,7 +243,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test the filter_matches function when an admin user has multiple roles.
*/
public function test_filter_matches_multiple_role_admin_user() {
public function test_filter_matches_multiple_role_admin_user(): void {
global $USER;
$context = \context_course::instance($this->course->id);
@@ -266,7 +266,7 @@ class role_filter_test extends \advanced_testcase {
/**
* Test that the get_filter_options function does not include the guest roles.
*/
public function test_get_filter_options_no_guest_roles() {
public function test_get_filter_options_no_guest_roles(): void {
create_role('Test Role', 'testrole', 'This is a test role', 'guest');
$allroles = role_get_names(null, ROLENAME_ALIAS);
+254 -315
View File
@@ -27,9 +27,9 @@ require_once($CFG->libdir . '/formslib.php');
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\step
*/
class step_test extends \advanced_testcase {
/**
* @var moodle_database
*/
@@ -62,8 +62,7 @@ class step_test extends \advanced_testcase {
global $DB;
$DB = $this->getMockBuilder('moodle_database')
->getMock()
;
->getMock();
return $DB;
}
@@ -73,64 +72,61 @@ class step_test extends \advanced_testcase {
*
* @return array
*/
public function dirty_value_provider() {
return [
public static function dirty_value_provider(): array {
return
[
'tourid' => [
'tourid',
[1],
],
'tourid',
[1],
],
'title' => [
'title',
['Lorem'],
],
'title',
['Lorem'],
],
'content' => [
'content',
['Lorem'],
],
'content',
['Lorem'],
],
'targettype' => [
'targettype',
['Lorem'],
],
'targettype',
['Lorem'],
],
'targetvalue' => [
'targetvalue',
['Lorem'],
],
'targetvalue',
['Lorem'],
],
'sortorder' => [
'sortorder',
[1],
],
'sortorder',
[1],
],
'config' => [
'config',
['key', 'value'],
],
'config',
['key', 'value'],
],
];
}
/**
* Test the fetch function.
*/
public function test_fetch() {
public function test_fetch(): void {
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods(['reload_from_record'])
->getMock()
;
->getMock();
$idretval = rand(1, 100);
$DB = $this->mock_database();
$DB->method('get_record')
->willReturn($idretval)
;
->willReturn($idretval);
$retval = rand(1, 100);
$step->expects($this->once())
->method('reload_from_record')
->with($this->equalTo($idretval))
->wilLReturn($retval)
;
->wilLReturn($retval);
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcm = $rc->getMethod('fetch');
$rcm->setAccessible(true);
$id = rand(1, 100);
$this->assertEquals($retval, $rcm->invoke($step, 'fetch', $id));
@@ -143,14 +139,13 @@ class step_test extends \advanced_testcase {
* @param string $name The key to update
* @param string $value The value to set
*/
public function test_dirty_values($name, $value) {
public function test_dirty_values($name, $value): void {
$step = new \tool_usertours\step();
$method = 'set_' . $name;
call_user_func_array([$step, $method], $value);
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('dirty');
$rcp->setAccessible(true);
$this->assertTrue($rcp->getValue($step));
}
@@ -160,12 +155,12 @@ class step_test extends \advanced_testcase {
*
* @return array
*/
public function step_sortorder_provider() {
public static function step_sortorder_provider(): array {
return [
[0, 5, true, false],
[1, 5, false, false],
[4, 5, false, true],
];
[0, 5, true, false],
[1, 5, false, false],
[4, 5, false, true],
];
}
/**
@@ -177,15 +172,14 @@ class step_test extends \advanced_testcase {
* @param bool $isfirst Whether this is the first step
* @param bool $islast Whether this is the last step
*/
public function test_is_first_step($sortorder, $count, $isfirst, $islast) {
public function test_is_first_step($sortorder, $count, $isfirst, $islast): void {
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods(['get_sortorder'])
->getMock();
$step->expects($this->once())
->method('get_sortorder')
->willReturn($sortorder)
;
->willReturn($sortorder);
$this->assertEquals($isfirst, $step->is_first_step());
}
@@ -199,7 +193,7 @@ class step_test extends \advanced_testcase {
* @param bool $isfirst Whether this is the first step
* @param bool $islast Whether this is the last step
*/
public function test_is_last_step($sortorder, $count, $isfirst, $islast) {
public function test_is_last_step($sortorder, $count, $isfirst, $islast): void {
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods(['get_sortorder', 'get_tour'])
->getMock();
@@ -210,18 +204,15 @@ class step_test extends \advanced_testcase {
$step->expects($this->once())
->method('get_tour')
->willReturn($tour)
;
->willReturn($tour);
$tour->expects($this->once())
->method('count_steps')
->willReturn($count)
;
->willReturn($count);
$step->expects($this->once())
->method('get_sortorder')
->willReturn($sortorder)
;
->willReturn($sortorder);
$this->assertEquals($islast, $step->is_last_step());
}
@@ -229,20 +220,19 @@ class step_test extends \advanced_testcase {
/**
* Test get_config with no keys provided.
*/
public function test_get_config_no_keys() {
public function test_get_config_no_keys(): void {
$step = new \tool_usertours\step();
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('config');
$rcp->setAccessible(true);
$allvalues = (object) [
'some' => 'value',
'another' => 42,
'key' => [
'somethingelse',
],
];
'some' => 'value',
'another' => 42,
'key' => [
'somethingelse',
],
];
$rcp->setValue($step, $allvalues);
@@ -254,92 +244,92 @@ class step_test extends \advanced_testcase {
*
* @return array
*/
public function get_config_provider() {
public static function get_config_provider(): array {
$allvalues = (object) [
'some' => 'value',
'another' => 42,
'key' => [
'somethingelse',
],
];
'some' => 'value',
'another' => 42,
'key' => [
'somethingelse',
],
];
$tourconfig = rand(1, 100);
$forcedconfig = rand(1, 100);
return [
'No initial config' => [
null,
null,
null,
$tourconfig,
false,
$forcedconfig,
(object) [],
],
'All values' => [
$allvalues,
null,
null,
$tourconfig,
false,
$forcedconfig,
$allvalues,
],
'Valid string value' => [
$allvalues,
'some',
null,
$tourconfig,
false,
$forcedconfig,
'value',
],
'Valid array value' => [
$allvalues,
'key',
null,
$tourconfig,
false,
$forcedconfig,
['somethingelse'],
],
'Invalid value' => [
$allvalues,
'notavalue',
null,
$tourconfig,
false,
$forcedconfig,
$tourconfig,
],
'Configuration value' => [
$allvalues,
'placement',
null,
$tourconfig,
false,
$forcedconfig,
$tourconfig,
],
'Invalid value with default' => [
$allvalues,
'notavalue',
'somedefault',
$tourconfig,
false,
$forcedconfig,
'somedefault',
],
'Value forced at target' => [
$allvalues,
'somevalue',
'somedefault',
$tourconfig,
true,
$forcedconfig,
$forcedconfig,
],
];
'No initial config' => [
null,
null,
null,
$tourconfig,
false,
$forcedconfig,
(object) [],
],
'All values' => [
$allvalues,
null,
null,
$tourconfig,
false,
$forcedconfig,
$allvalues,
],
'Valid string value' => [
$allvalues,
'some',
null,
$tourconfig,
false,
$forcedconfig,
'value',
],
'Valid array value' => [
$allvalues,
'key',
null,
$tourconfig,
false,
$forcedconfig,
['somethingelse'],
],
'Invalid value' => [
$allvalues,
'notavalue',
null,
$tourconfig,
false,
$forcedconfig,
$tourconfig,
],
'Configuration value' => [
$allvalues,
'placement',
null,
$tourconfig,
false,
$forcedconfig,
$tourconfig,
],
'Invalid value with default' => [
$allvalues,
'notavalue',
'somedefault',
$tourconfig,
false,
$forcedconfig,
'somedefault',
],
'Value forced at target' => [
$allvalues,
'somevalue',
'somedefault',
$tourconfig,
true,
$forcedconfig,
$forcedconfig,
],
];
}
/**
@@ -354,55 +344,46 @@ class step_test extends \advanced_testcase {
* @param mixed $forcedvalue The example value
* @param mixed $expected The expected value
*/
public function test_get_config_valid_keys($values, $key, $default, $tourconfig, $isforced, $forcedvalue, $expected) {
public function test_get_config_valid_keys($values, $key, $default, $tourconfig, $isforced, $forcedvalue, $expected): void {
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods(['get_target', 'get_targettype', 'get_tour'])
->getMock();
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('config');
$rcp->setAccessible(true);
$rcp->setValue($step, $values);
$target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
->disableOriginalConstructor()
->getMock()
;
->getMock();
$target->expects($this->any())
->method('is_setting_forced')
->willReturn($isforced)
;
->willReturn($isforced);
$target->expects($this->any())
->method('get_forced_setting_value')
->with($this->equalTo($key))
->willReturn($forcedvalue)
;
->willReturn($forcedvalue);
$step->expects($this->any())
->method('get_targettype')
->willReturn('type')
;
->willReturn('type');
$step->expects($this->any())
->method('get_target')
->willReturn($target)
;
->willReturn($target);
$tour = $this->getMockBuilder(\tool_usertours\tour::class)
->getMock()
;
->getMock();
$tour->expects($this->any())
->method('get_config')
->willReturn($tourconfig)
;
->willReturn($tourconfig);
$step->expects($this->any())
->method('get_tour')
->willReturn($tour)
;
->willReturn($tour);
$this->assertEquals($expected, $step->get_config($key, $default));
}
@@ -410,14 +391,14 @@ class step_test extends \advanced_testcase {
/**
* Data provider for set_config.
*/
public function set_config_provider() {
public static function set_config_provider(): array {
$allvalues = (object) [
'some' => 'value',
'another' => 42,
'key' => [
'somethingelse',
],
];
'some' => 'value',
'another' => 42,
'key' => [
'somethingelse',
],
];
$randvalue = rand(1, 100);
@@ -426,27 +407,27 @@ class step_test extends \advanced_testcase {
$newvalues = $allvalues;
$newvalues->some = 'unset';
$provider['Unset an existing value'] = [
$allvalues,
'some',
null,
$newvalues,
];
$allvalues,
'some',
null,
$newvalues,
];
$newvalues = $allvalues;
$newvalues->some = $randvalue;
$provider['Set an existing value'] = [
$allvalues,
'some',
$randvalue,
$newvalues,
];
$allvalues,
'some',
$randvalue,
$newvalues,
];
$provider['Set a new value'] = [
$allvalues,
'newkey',
$randvalue,
(object) array_merge((array) $allvalues, ['newkey' => $randvalue]),
];
$allvalues,
'newkey',
$randvalue,
(object) array_merge((array) $allvalues, ['newkey' => $randvalue]),
];
return $provider;
}
@@ -460,23 +441,20 @@ class step_test extends \advanced_testcase {
* @param mixed $newvalue The new value to set
* @param mixed $expected The expected value
*/
public function test_set_config($initialvalues, $key, $newvalue, $expected) {
public function test_set_config($initialvalues, $key, $newvalue, $expected): void {
$step = new \tool_usertours\step();
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('config');
$rcp->setAccessible(true);
$rcp->setValue($step, $initialvalues);
$target = $this->getMockBuilder(\tool_usertours\local\target\base::class)
->disableOriginalConstructor()
->getMock()
;
->getMock();
$target->expects($this->any())
->method('is_setting_forced')
->willReturn(false)
;
->willReturn(false);
$step->set_config($key, $newvalue);
@@ -486,22 +464,19 @@ class step_test extends \advanced_testcase {
/**
* Ensure that non-dirty tours are not persisted.
*/
public function test_persist_non_dirty() {
public function test_persist_non_dirty(): void {
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([
'to_record',
'reload',
])
->getMock()
;
'to_record',
'reload',
])
->getMock();
$step->expects($this->never())
->method('to_record')
;
->method('to_record');
$step->expects($this->never())
->method('reload')
;
->method('reload');
$this->assertSame($step, $step->persist());
}
@@ -509,45 +484,38 @@ class step_test extends \advanced_testcase {
/**
* Ensure that new dirty steps are persisted.
*/
public function test_persist_dirty_new() {
public function test_persist_dirty_new(): void {
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->once())
->method('insert_record')
->willReturn(42)
;
->willReturn(42);
// Mock the tour.
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([
'to_record',
'calculate_sortorder',
'reload',
])
->getMock()
;
'to_record',
'calculate_sortorder',
'reload',
])
->getMock();
$step->expects($this->once())
->method('to_record')
->willReturn((object)['id' => 42]);
;
$step->expects($this->once())
->method('calculate_sortorder')
;
->method('calculate_sortorder');
$step->expects($this->once())
->method('reload')
;
->method('reload');
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('dirty');
$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());
@@ -556,43 +524,37 @@ class step_test extends \advanced_testcase {
/**
* Ensure that new non-dirty, forced steps are persisted.
*/
public function test_persist_force_new() {
public function test_persist_force_new(): void {
global $DB;
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->once())
->method('insert_record')
->willReturn(42)
;
->willReturn(42);
// Mock the tour.
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([
'to_record',
'calculate_sortorder',
'reload',
])
->getMock()
;
'to_record',
'calculate_sortorder',
'reload',
])
->getMock();
$step->expects($this->once())
->method('to_record')
->willReturn((object)['id' => 42]);
;
$step->expects($this->once())
->method('calculate_sortorder')
;
->method('calculate_sortorder');
$step->expects($this->once())
->method('reload')
;
->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));
@@ -601,48 +563,40 @@ class step_test extends \advanced_testcase {
/**
* Ensure that existing dirty steps are persisted.
*/
public function test_persist_dirty_existing() {
public function test_persist_dirty_existing(): void {
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->once())
->method('update_record')
;
->method('update_record');
// Mock the tour.
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([
'to_record',
'calculate_sortorder',
'reload',
])
->getMock()
;
'to_record',
'calculate_sortorder',
'reload',
])
->getMock();
$step->expects($this->once())
->method('to_record')
->willReturn((object)['id' => 42]);
;
$step->expects($this->never())
->method('calculate_sortorder')
;
->method('calculate_sortorder');
$step->expects($this->once())
->method('reload')
;
->method('reload');
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('id');
$rcp->setAccessible(true);
$rcp->setValue($step, 42);
$rcp = $rc->getProperty('dirty');
$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());
@@ -651,46 +605,39 @@ class step_test extends \advanced_testcase {
/**
* Ensure that existing non-dirty, forced steps are persisted.
*/
public function test_persist_force_existing() {
public function test_persist_force_existing(): void {
global $DB;
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->once())
->method('update_record')
;
->method('update_record');
// Mock the tour.
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([
'to_record',
'calculate_sortorder',
'reload',
])
->getMock()
;
'to_record',
'calculate_sortorder',
'reload',
])
->getMock();
$step->expects($this->once())
->method('to_record')
->willReturn((object)['id' => 42]);
;
->willReturn((object) ['id' => 42]);
$step->expects($this->never())
->method('calculate_sortorder')
;
->method('calculate_sortorder');
$step->expects($this->once())
->method('reload')
;
->method('reload');
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('id');
$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));
@@ -699,17 +646,15 @@ class step_test extends \advanced_testcase {
/**
* Check that a tour which has never been persisted is removed correctly.
*/
public function test_remove_non_persisted() {
public function test_remove_non_persisted(): void {
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([])
->getMock()
;
->getMock();
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->never())
->method('delete_records')
;
->method('delete_records');
$this->assertNull($step->remove());
}
@@ -717,42 +662,36 @@ class step_test extends \advanced_testcase {
/**
* Check that a tour which has been persisted is removed correctly.
*/
public function test_remove_persisted() {
public function test_remove_persisted(): void {
$id = rand(1, 100);
$tour = $this->getMockBuilder(\tool_usertours\tour::class)
->onlyMethods([
'reset_step_sortorder',
])
->getMock()
;
'reset_step_sortorder',
])
->getMock();
$tour->expects($this->once())
->method('reset_step_sortorder')
;
->method('reset_step_sortorder');
$step = $this->getMockBuilder(\tool_usertours\step::class)
->onlyMethods([
'get_tour',
])
->getMock()
;
'get_tour',
])
->getMock();
$step->expects($this->once())
->method('get_tour')
->willReturn($tour)
;
->willReturn($tour);
// Mock the database.
$DB = $this->mock_database();
$DB->expects($this->once())
->method('delete_records')
->with($this->equalTo('tool_usertours_steps'), $this->equalTo(['id' => $id]))
;
->with($this->equalTo('tool_usertours_steps'), $this->equalTo(['id' => $id]));
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty('id');
$rcp->setAccessible(true);
$rcp->setValue($step, $id);
$this->assertEquals($id, $step->get_id());
@@ -764,37 +703,37 @@ class step_test extends \advanced_testcase {
*
* @return array
*/
public function getter_provider() {
public static function getter_provider(): array {
return [
'id' => [
'id',
rand(1, 100),
],
'tourid' => [
'tourid',
rand(1, 100),
],
'title' => [
'title',
'Lorem',
],
'content' => [
'content',
'Lorem',
],
'targettype' => [
'targettype',
'Lorem',
],
'targetvalue' => [
'targetvalue',
'Lorem',
],
'sortorder' => [
'sortorder',
rand(1, 100),
],
];
'id' => [
'id',
rand(1, 100),
],
'tourid' => [
'tourid',
rand(1, 100),
],
'title' => [
'title',
'Lorem',
],
'content' => [
'content',
'Lorem',
],
'targettype' => [
'targettype',
'Lorem',
],
'targetvalue' => [
'targetvalue',
'Lorem',
],
'sortorder' => [
'sortorder',
rand(1, 100),
],
];
}
/**
@@ -804,13 +743,12 @@ class step_test extends \advanced_testcase {
* @param string $key The key to test
* @param mixed $value The expected value
*/
public function test_getters($key, $value) {
public function test_getters($key, $value): void {
$step = new \tool_usertours\step();
$rc = new \ReflectionClass(\tool_usertours\step::class);
$rcp = $rc->getProperty($key);
$rcp->setAccessible(true);
$rcp->setValue($step, $value);
$getter = 'get_' . $key;
@@ -821,7 +759,7 @@ class step_test extends \advanced_testcase {
/**
* Ensure that the get_step_image_from_input function replace PIXICON placeholder with the correct images correctly.
*/
public function test_get_step_image_from_input() {
public function test_get_step_image_from_input(): void {
// Test step content with single image.
$stepcontent = '@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Test';
$stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
@@ -832,7 +770,8 @@ class step_test extends \advanced_testcase {
$this->assertStringNotContainsString('PIXICON', $stepcontent);
// Test step content with multiple images.
$stepcontent = '@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Test<br>@@PIXICON::tour/tour_myhomepage::tool_usertours@@';
$stepcontent =
'@@PIXICON::tour/tour_mycourses::tool_usertours@@<br>Test<br>@@PIXICON::tour/tour_myhomepage::tool_usertours@@';
$stepcontent = \tool_usertours\step::get_step_image_from_input($stepcontent);
// If the format is correct, PIXICON placeholder will be replaced with the img tag.
$this->assertStringStartsWith('<img', $stepcontent);
@@ -22,15 +22,15 @@ namespace tool_usertours;
* @package tool_usertours
* @copyright 2016 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \tool_usertours\local\filter\theme
*/
class theme_filter_test extends \advanced_testcase {
/**
* Data Provider for filter_matches function.
*
* @return array
*/
public function filter_matches_provider() {
public static function filter_matches_provider(): array {
return [
'No config set; Matches' => [
null,
@@ -73,7 +73,7 @@ class theme_filter_test extends \advanced_testcase {
* @param string $currenttheme The name of the current theme
* @param boolean $expected Whether the tour is expected to match
*/
public function test_filter_matches($filtervalues, $currenttheme, $expected) {
public function test_filter_matches($filtervalues, $currenttheme, $expected): void {
global $PAGE;
$filtername = \tool_usertours\local\filter\theme::class;
File diff suppressed because it is too large Load Diff
@@ -78,7 +78,6 @@ class community_of_inquiry_activities_completed_by_testcase extends advanced_tes
));
$method = new ReflectionMethod($availabilityinfo, 'set_in_database');
$method->setAccessible(true);
$method->invoke($availabilityinfo, json_encode($structure));
$this->setUser($stu1);
@@ -339,11 +338,9 @@ class community_of_inquiry_activities_completed_by_testcase extends advanced_tes
$class = new ReflectionClass($indicator);
$property = $class->getProperty('course');
$property->setAccessible(true);
$property->setValue($indicator, $course);
$method = new ReflectionMethod($indicator, 'get_activities');
$method->setAccessible(true);
return array($indicator, $method);
}
-1
View File
@@ -427,7 +427,6 @@ class model_test extends \advanced_testcase {
$modelconfig = new \core_analytics\model_config($this->model);
$method = new \ReflectionMethod('\\core_analytics\\model_config', 'export_model_data');
$method->setAccessible(true);
$modeldata = $method->invoke($modelconfig);
+11
View File
@@ -75,6 +75,10 @@ class login implements renderable, templatable {
public $maintenance;
/** @var string ReCaptcha element HTML. */
public $recaptcha;
/** @var bool Toggle the password visibility icon. */
public $togglepassword;
/** @var bool Toggle the password visibility icon for small screens only. */
public $smallscreensonly;
/**
* Constructor.
@@ -130,6 +134,11 @@ class login implements renderable, templatable {
require_once($CFG->libdir . '/recaptchalib_v2.php');
$this->recaptcha = recaptcha_get_challenge_html(RECAPTCHA_API_URL, $CFG->recaptchapublickey);
}
// Toggle password visibility icon.
$this->togglepassword = get_config('core', 'loginpasswordtoggle') == TOGGLE_SENSITIVE_ENABLED ||
get_config('core', 'loginpasswordtoggle') == TOGGLE_SENSITIVE_SMALL_SCREENS_ONLY;
$this->smallscreensonly = get_config('core', 'loginpasswordtoggle') == TOGGLE_SENSITIVE_SMALL_SCREENS_ONLY;
}
/**
@@ -175,6 +184,8 @@ class login implements renderable, templatable {
$data->maintenance = format_text($this->maintenance, FORMAT_MOODLE);
$data->languagemenu = $this->languagemenu;
$data->recaptcha = $this->recaptcha;
$data->togglepassword = $this->togglepassword;
$data->smallscreensonly = $this->smallscreensonly;
return $data;
}
+18
View File
@@ -101,3 +101,21 @@ Feature: Test if the login form provides the correct feedback
And I press "Log in"
And I press the tab key
Then the focused element is "Username" "field"
Scenario: Display the password visibility toggle icon
Given the following config values are set as admin:
| loginpasswordtoggle | 1 |
When I follow "Log in"
Then "Toggle sensitive" "button" should be visible
And the following config values are set as admin:
| loginpasswordtoggle | 0 |
And I reload the page
And "Toggle sensitive" "button" should not be visible
Scenario: Display the password visibility toggle icon for small screens only
Given the following config values are set as admin:
| loginpasswordtoggle | 2 |
When I follow "Log in"
Then "Toggle sensitive" "button" should not be visible
And I change the viewport size to "mobile"
And "Toggle sensitive" "button" should be visible
@@ -74,7 +74,6 @@ class backup_stepslib_test extends \advanced_testcase {
$reflection = new \ReflectionClass($step);
$method = $reflection->getMethod('define_structure');
$method->setAccessible(true);
$structure = $method->invoke($step);
$elements = $structure->get_final_elements();
@@ -77,7 +77,6 @@ class restore_gradebook_structure_step_test extends \advanced_testcase {
$rc = new \ReflectionClass('\restore_gradebook_structure_step');
$rcm = $rc->getMethod('rewrite_step_backup_file_for_legacy_freeze');
$rcm->setAccessible(true);
$rcm->invoke($restore, $filepath);
// Check the result.
-9
View File
@@ -116,11 +116,9 @@ class automated_backup_test extends \advanced_testcase {
$classobject = $this->backupcronautomatedhelper->return_this();
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'get_courses');
$method->setAccessible(true); // Allow accessing of private method.
$courses = $method->invoke($classobject);
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'check_and_push_automated_backups');
$method->setAccessible(true); // Allow accessing of private method.
$emailpending = $method->invokeArgs($classobject, [$courses, $admin]);
$this->expectOutputRegex('/Skipping course id ' . $this->course->id . ': Not scheduled for backup until/');
@@ -145,7 +143,6 @@ class automated_backup_test extends \advanced_testcase {
$classobject = $this->backupcronautomatedhelper->return_this();
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'get_courses');
$method->setAccessible(true); // Allow accessing of private method.
$courses = $method->invoke($classobject);
// Create this backup course.
@@ -161,7 +158,6 @@ class automated_backup_test extends \advanced_testcase {
$DB->update_record('backup_courses', $backupcourse);
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'check_and_push_automated_backups');
$method->setAccessible(true); // Allow accessing of private method.
$emailpending = $method->invokeArgs($classobject, [$courses, $admin]);
$this->assertTrue($emailpending);
@@ -204,7 +200,6 @@ class automated_backup_test extends \advanced_testcase {
$nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup(null, time());
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'should_skip_course_backup');
$method->setAccessible(true); // Allow accessing of private method.
$skipped = $method->invokeArgs($classobject, [$backupcourse, $course, $nextstarttime]);
$this->assertTrue($skipped);
@@ -239,7 +234,6 @@ class automated_backup_test extends \advanced_testcase {
$nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup(null, time());
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'should_skip_course_backup');
$method->setAccessible(true); // Allow accessing of private method.
$skipped = $method->invokeArgs($classobject, [$backupcourse, $course, $nextstarttime]);
$this->assertTrue($skipped);
@@ -274,7 +268,6 @@ class automated_backup_test extends \advanced_testcase {
$nextstarttime = backup_cron_automated_helper::calculate_next_automated_backup(null, time());
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'should_skip_course_backup');
$method->setAccessible(true); // Allow accessing of private method.
$skipped = $method->invokeArgs($classobject, [$backupcourse, $course, $nextstarttime]);
$this->assertTrue($skipped);
@@ -298,7 +291,6 @@ class automated_backup_test extends \advanced_testcase {
// Create a backup task.
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'push_course_backup_adhoc_task');
$method->setAccessible(true); // Allow accessing of private method.
$method->invokeArgs($classobject, [$backupcourse, $admin]);
// Delete course for this test.
@@ -331,7 +323,6 @@ class automated_backup_test extends \advanced_testcase {
// Create a backup task.
$method = new \ReflectionMethod('\backup_cron_automated_helper', 'push_course_backup_adhoc_task');
$method->setAccessible(true); // Allow accessing of private method.
$method->invokeArgs($classobject, [$backupcourse, $admin]);
// Delete backup course for this test.
@@ -351,7 +351,6 @@ class restore_dbops_test extends \advanced_testcase {
$dbuser = $DB->get_record('user', ['id' => $dbuser->id]);
$method = (new \ReflectionClass('restore_dbops'))->getMethod('precheck_user');
$method->setAccessible(true);
$result = $method->invoke(null, $backupuser, $samesite, $siteid);
if (is_bool($result)) {
@@ -62,11 +62,9 @@ class restore_log_rule_test extends \basic_testcase {
$class = new \ReflectionClass('restore_log_rule');
$method = $class->getMethod('extract_tokens');
$method->setAccessible(true);
$tokens = $method->invoke($lr, $original);
$method = $class->getMethod('build_regexp');
$method->setAccessible(true);
$this->assertSame($expectation, $method->invoke($lr, $original, $tokens));
}
}
-3
View File
@@ -912,7 +912,6 @@ class badgeslib_test extends advanced_testcase {
core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $course);
$reflector = new ReflectionObject($tree);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
$this->assertArrayHasKey('localbadges', $nodes->getValue($tree));
}
@@ -935,7 +934,6 @@ class badgeslib_test extends advanced_testcase {
core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $course);
$reflector = new ReflectionObject($tree);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
$this->assertArrayNotHasKey('localbadges', $nodes->getValue($tree));
}
@@ -954,7 +952,6 @@ class badgeslib_test extends advanced_testcase {
core_badges_myprofile_navigation($tree, $this->user, $iscurrentuser, $this->course);
$reflector = new ReflectionObject($tree);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
$this->assertArrayHasKey('localbadges', $nodes->getValue($tree));
}
@@ -34,8 +34,7 @@ Feature: Delete course badge already awarded
# Navigate to Manage Badges page in order to delete the badge
And I navigate to "Badges > Manage badges" in current page administration
# Delete the badge
And I open the action menu in "<badgename>" "table_row"
And I choose "Delete" in the open action menu
And I press "Delete" action in the "<badgename>" report row
And I press "<deleteoption>"
And I am on the "Course 1" "enrolled users" page
And I click on "Student 1" "link"
+5 -9
View File
@@ -54,16 +54,14 @@ Feature: Manage badges
And I set the field "Manager" to "1"
And I press "Save"
And I navigate to "Badges > Manage badges" in site administration
And I open the action menu in "Badge #1" "table_row"
And I choose "Enable access" in the open action menu
And I press "Enable access" action in the "Badge #1" report row
And I should see "Changes in badge access"
And I press "Continue"
And I should see "Access to the badges was successfully enabled"
Then the following should exist in the "reportbuilder-table" table:
| Name | Badge status |
| Badge #1 | Available |
And I open the action menu in "Badge #1" "table_row"
And I choose "Disable access" in the open action menu
And I press "Disable access" action in the "Badge #1" report row
And I should see "Access to the badges was successfully disabled"
And the following should exist in the "reportbuilder-table" table:
| Name | Badge status |
@@ -78,14 +76,12 @@ Feature: Manage badges
And I set the field "Manager" to "1"
And I press "Save"
And I navigate to "Badges > Manage badges" in site administration
And I open the action menu in "Badge #1" "table_row"
And I choose "Enable access" in the open action menu
And I press "Enable access" action in the "Badge #1" report row
And I press "Continue"
And I open the action menu in "Badge #1" "table_row"
And I choose "Award badge" in the open action menu
And I press "Award badge" action in the "Badge #1" report row
And I set the field "potentialrecipients[]" to "Admin User (moodle@example.com)"
And I press "Award badge"
And I navigate to "Badges > Manage badges" in site administration
And the following should exist in the "reportbuilder-table" table:
Then the following should exist in the "reportbuilder-table" table:
| Name | Badge status | Recipients |
| Badge #1 | Available | 1 |
+5 -10
View File
@@ -38,8 +38,7 @@ Feature: Display badges
And I navigate to "Badges > Manage badges" in site administration
And I follow "Testing system badge"
And I select "Recipients (1)" from the "jump" singleselect
And I open the action menu in "Student 1" "table_row"
And I choose "View issued badge" in the open action menu
And I press "View issued badge" action in the "Student 1" report row
Then I should see "Awarded to Student 1"
And I should see "This badge has to be awarded by a user with the following role:"
And I should not see "Expired"
@@ -64,8 +63,7 @@ Feature: Display badges
And I navigate to "Badges > Manage badges" in site administration
And I follow "Testing system badge"
And I select "Recipients (1)" from the "jump" singleselect
And I open the action menu in "Student 1" "table_row"
And I choose "View issued badge" in the open action menu
And I press "View issued badge" action in the "Student 1" report row
Then I should see "Awarded to Student 1"
And I should see "Complete ALL of the listed requirements."
And I should see "This badge has to be awarded by a user with the following role:"
@@ -86,8 +84,7 @@ Feature: Display badges
And I press "Continue"
# Check badge details are displayed.
And I select "Recipients (2)" from the "jump" singleselect
And I open the action menu in "Student 1" "table_row"
And I choose "View issued badge" in the open action menu
And I press "View issued badge" action in the "Student 1" report row
Then I should see "Awarded to Student 1"
And I should see "Complete ANY of the listed requirements."
And I should see "This badge has to be awarded by a user with the following role:"
@@ -115,8 +112,7 @@ Feature: Display badges
And I navigate to "Badges > Manage badges" in site administration
And I follow "Testing system badge"
And I select "Recipients (1)" from the "jump" singleselect
And I open the action menu in "Student 1" "table_row"
And I choose "View issued badge" in the open action menu
And I press "View issued badge" action in the "Student 1" report row
Then I should see "Expires"
And I should not see "Expired"
@@ -140,7 +136,6 @@ Feature: Display badges
And I navigate to "Badges > Manage badges" in site administration
And I follow "Testing system badge"
And I select "Recipients (1)" from the "jump" singleselect
And I open the action menu in "Student 1" "table_row"
And I choose "View issued badge" in the open action menu
And I press "View issued badge" action in the "Student 1" report row
Then I should see "Expired"
And I should not see "Expires"
@@ -134,7 +134,6 @@ class manage_badge_action_bar_test extends \advanced_testcase {
$rc = new \ReflectionClass(manage_badge_action_bar::class);
$rcm = $rc->getMethod('generate_badge_navigation');
$rcm->setAccessible(true);
$content = $rcm->invoke($actionbar);
$this->assertEquals($expected, array_values($content));
}
@@ -39,7 +39,6 @@ class accessibility_review_test extends advanced_testcase {
public function test_get_toggle_link() {
$rc = new ReflectionClass(block_accessreview::class);
$rm = $rc->getMethod('get_toggle_link');
$rm->setAccessible(true);
$block = new block_accessreview();
$output = $rm->invoke($block);
@@ -60,7 +59,6 @@ class accessibility_review_test extends advanced_testcase {
$rc = new ReflectionClass(block_accessreview::class);
$rm = $rc->getMethod('get_download_link');
$rm->setAccessible(true);
$block = new block_accessreview();
$this->setUser($user1);
@@ -86,7 +84,6 @@ class accessibility_review_test extends advanced_testcase {
$rc = new ReflectionClass(block_accessreview::class);
$rm = $rc->getMethod('get_report_link');
$rm->setAccessible(true);
$block = new block_accessreview();
$this->setUser($user1);
+8 -1
View File
@@ -363,7 +363,14 @@ class main implements renderable, templatable {
if (!$this->displaygroupingcustomfield) {
return [];
}
$fieldid = $DB->get_field('customfield_field', 'id', ['shortname' => $this->customfiltergrouping]);
// Get the relevant customfield ID within the core_course/course component/area.
$fieldid = $DB->get_field_sql("
SELECT f.id
FROM {customfield_field} f
JOIN {customfield_category} c ON c.id = f.categoryid
WHERE f.shortname = :shortname AND c.component = 'core_course' AND c.area = 'course'
", ['shortname' => $this->customfiltergrouping]);
if (!$fieldid) {
return [];
}
-3
View File
@@ -175,7 +175,6 @@ class lib_test extends \advanced_testcase {
core_blog_myprofile_navigation($tree, $USER, $iscurrentuser, $course);
$reflector = new \ReflectionObject($tree);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
$this->assertArrayHasKey('blogs', $nodes->getValue($tree));
}
@@ -197,7 +196,6 @@ class lib_test extends \advanced_testcase {
core_blog_myprofile_navigation($tree, $USER, $iscurrentuser, $course);
$reflector = new \ReflectionObject($tree);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
$this->assertArrayNotHasKey('blogs', $nodes->getValue($tree));
}
@@ -220,7 +218,6 @@ class lib_test extends \advanced_testcase {
core_blog_myprofile_navigation($tree, $USER, $iscurrentuser, $course);
$reflector = new \ReflectionObject($tree);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
$this->assertArrayNotHasKey('blogs', $nodes->getValue($tree));
}
-1
View File
@@ -851,7 +851,6 @@ class cachestore_redis extends cache_store implements cache_is_key_aware, cache_
if (!empty($config->test_ttl)) {
$definition = clone $definition;
$property = (new ReflectionClass($definition))->getProperty('ttl');
$property->setAccessible(true);
$property->setValue($definition, 999);
}
$cache = new cachestore_redis('Redis test', $configuration);
-4
View File
@@ -2332,11 +2332,8 @@ class cache_test extends \advanced_testcase {
// We need to get the individual stores so as to set up the right behaviour here.
$ref = new \ReflectionClass('\cache');
$definitionprop = $ref->getProperty('definition');
$definitionprop->setAccessible(true);
$storeprop = $ref->getProperty('store');
$storeprop->setAccessible(true);
$loaderprop = $ref->getProperty('loader');
$loaderprop->setAccessible(true);
$definition = $definitionprop->getValue($cache);
$localstore = $storeprop->getValue($cache);
@@ -2346,7 +2343,6 @@ class cache_test extends \advanced_testcase {
// Set the lock waiting time to 1 second so it doesn't take forever to run the test.
$ref = new \ReflectionClass('\cachestore_file');
$lockwaitprop = $ref->getProperty('lockwait');
$lockwaitprop->setAccessible(true);
$lockwaitprop->setValue($localstore, 1);
$lockwaitprop->setValue($sharedstore, 1);
-13
View File
@@ -1,13 +0,0 @@
/**
* This module handles display of multiple mini calendars in a view, and
* movement through them.
*
* @deprecated since 4.0 MDL-72810.
* @todo MDL-73117 This will be deleted in Moodle 4.4.
* @module core_calendar/calendar_threemonth
* @copyright 2017 Andrew Nicols <andrew@nicols.co.uk>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define("core_calendar/calendar_threemonth",["jquery","core/notification","core_calendar/selectors","core_calendar/events","core/templates","core_calendar/view_manager"],(function($,Notification,CalendarSelectors,CalendarEvents,Templates,CalendarViewManager){return{init:function(root){!function(root){$("body").on([CalendarEvents.monthChanged,CalendarEvents.dayChanged].join(" "),(function(e,year,month,courseId,categoryId){root.queue((function(next){return processRequest(e,year,month,courseId,categoryId).then((function(){return next()})).fail(Notification.exception)}))}));var processRequest=function(e,year,month,courseId,categoryId){var newParent=root.find('[data-year="'+year+'"][data-month="'+month+'"]').closest(CalendarSelectors.calendarPeriods.month),allMonths=root.find(CalendarSelectors.calendarPeriods.month),previousMonth=$(allMonths[0]),nextMonth=$(allMonths[2]),placeHolder=$("<span>");placeHolder.attr("data-template","core_calendar/threemonth_month"),placeHolder.attr("data-includenavigation",!1),placeHolder.attr("data-mini",!0);var requestYear,requestMonth,oldMonth,placeHolderContainer=$("<div>");if(placeHolderContainer.hide(),placeHolderContainer.append(placeHolder),newParent.is(previousMonth))placeHolderContainer.insertBefore(previousMonth),requestYear=previousMonth.data("previousYear"),requestMonth=previousMonth.data("previousMonth"),oldMonth=nextMonth;else{if(!newParent.is(nextMonth))return $.Deferred().resolve();placeHolderContainer.insertAfter(nextMonth),requestYear=nextMonth.data("nextYear"),requestMonth=nextMonth.data("nextMonth"),oldMonth=previousMonth}return CalendarViewManager.refreshMonthContent(placeHolder,requestYear,requestMonth,courseId,categoryId,placeHolder).then((function(){var slideUpPromise=$.Deferred(),slideDownPromise=$.Deferred();return oldMonth.slideUp("fast",(function(){$(this).remove(),slideUpPromise.resolve()})),placeHolderContainer.slideDown("fast",(function(){slideDownPromise.resolve()})),$.when(slideUpPromise,slideDownPromise)}))};root.on("click",CalendarSelectors.links.miniDayLink,(function(e){var miniDayLink=$(e.target),year=miniDayLink.data("year"),month=miniDayLink.data("month"),day=miniDayLink.text(),courseId=miniDayLink.data("courseid"),categoryId=miniDayLink.data("categoryid"),calendarRoot=$("body").find(CalendarSelectors.calendarMain);CalendarViewManager.refreshDayContent(calendarRoot,year,month,day,courseId,categoryId,calendarRoot.find('[id^="calendar-"][data-template^="core_calendar/"]'),"core_calendar/calendar_day"),e.preventDefault(),CalendarViewManager.updateUrl("?view=day")}))}(root=$(root))}}}));
//# sourceMappingURL=calendar_threemonth.min.js.map
File diff suppressed because one or more lines are too long
-148
View File
@@ -1,148 +0,0 @@
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* This module handles display of multiple mini calendars in a view, and
* movement through them.
*
* @deprecated since 4.0 MDL-72810.
* @todo MDL-73117 This will be deleted in Moodle 4.4.
* @module core_calendar/calendar_threemonth
* @copyright 2017 Andrew Nicols <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define([
'jquery',
'core/notification',
'core_calendar/selectors',
'core_calendar/events',
'core/templates',
'core_calendar/view_manager',
],
function(
$,
Notification,
CalendarSelectors,
CalendarEvents,
Templates,
CalendarViewManager
) {
/**
* Listen to and handle any calendar events fired by the calendar UI.
*
* @method registerCalendarEventListeners
* @param {object} root The calendar root element
*/
var registerCalendarEventListeners = function(root) {
var body = $('body');
body.on([CalendarEvents.monthChanged, CalendarEvents.dayChanged].join(' '), function(e, year, month, courseId, categoryId) {
// We have to use a queue here because the calling code is decoupled from these listeners.
// It's possible for the event to be called multiple times before one call is fully resolved.
root.queue(function(next) {
return processRequest(e, year, month, courseId, categoryId)
.then(function() {
return next();
})
.fail(Notification.exception)
;
});
});
var processRequest = function(e, year, month, courseId, categoryId) {
var newCurrentMonth = root.find('[data-year="' + year + '"][data-month="' + month + '"]');
var newParent = newCurrentMonth.closest(CalendarSelectors.calendarPeriods.month);
var allMonths = root.find(CalendarSelectors.calendarPeriods.month);
var previousMonth = $(allMonths[0]);
var nextMonth = $(allMonths[2]);
var placeHolder = $('<span>');
placeHolder.attr('data-template', 'core_calendar/threemonth_month');
placeHolder.attr('data-includenavigation', false);
placeHolder.attr('data-mini', true);
var placeHolderContainer = $('<div>');
placeHolderContainer.hide();
placeHolderContainer.append(placeHolder);
var requestYear;
var requestMonth;
var oldMonth;
if (newParent.is(previousMonth)) {
// Fetch the new previous month.
placeHolderContainer.insertBefore(previousMonth);
requestYear = previousMonth.data('previousYear');
requestMonth = previousMonth.data('previousMonth');
oldMonth = nextMonth;
} else if (newParent.is(nextMonth)) {
// Fetch the new next month.
placeHolderContainer.insertAfter(nextMonth);
requestYear = nextMonth.data('nextYear');
requestMonth = nextMonth.data('nextMonth');
oldMonth = previousMonth;
} else {
return $.Deferred().resolve();
}
return CalendarViewManager.refreshMonthContent(
placeHolder,
requestYear,
requestMonth,
courseId,
categoryId,
placeHolder
)
.then(function() {
var slideUpPromise = $.Deferred();
var slideDownPromise = $.Deferred();
oldMonth.slideUp('fast', function() {
$(this).remove();
slideUpPromise.resolve();
});
placeHolderContainer.slideDown('fast', function() {
slideDownPromise.resolve();
});
return $.when(slideUpPromise, slideDownPromise);
});
};
// Listen for a click on the day link in the three month block to load the day view.
root.on('click', CalendarSelectors.links.miniDayLink, function(e) {
var miniDayLink = $(e.target);
var year = miniDayLink.data('year'),
month = miniDayLink.data('month'),
day = miniDayLink.text(),
courseId = miniDayLink.data('courseid'),
categoryId = miniDayLink.data('categoryid'),
calendarRoot = $('body').find(CalendarSelectors.calendarMain);
CalendarViewManager.refreshDayContent(calendarRoot, year, month, day, courseId, categoryId,
calendarRoot.find('[id^="calendar-"][data-template^="core_calendar/"]'), 'core_calendar/calendar_day');
e.preventDefault();
CalendarViewManager.updateUrl('?view=day');
});
};
return {
init: function(root) {
root = $(root);
registerCalendarEventListeners(root);
}
};
});
+2 -55
View File
@@ -51,63 +51,10 @@ class core_calendar_renderer extends plugin_renderer_base {
}
/**
* Produces the content for the three months block (pretend block)
*
* This includes the previous month, the current month, and the next month
*
* @deprecated since 4.0 MDL-72810.
* @todo MDL-73117 This will be deleted in Moodle 4.4.
*
* @param calendar_information $calendar
* @return string
*/
public function fake_block_threemonths(calendar_information $calendar) {
debugging('This method is no longer used as the three month calendar block has been removed', DEBUG_DEVELOPER);
// Get the calendar type we are using.
$calendartype = \core_calendar\type_factory::get_calendar_instance();
$time = $calendartype->timestamp_to_date_array($calendar->time);
$current = $calendar->time;
$prevmonthyear = $calendartype->get_prev_month($time['year'], $time['mon']);
$prev = $calendartype->convert_to_timestamp(
$prevmonthyear[1],
$prevmonthyear[0],
1
);
$nextmonthyear = $calendartype->get_next_month($time['year'], $time['mon']);
$next = $calendartype->convert_to_timestamp(
$nextmonthyear[1],
$nextmonthyear[0],
1
);
$content = '';
// Previous.
$calendar->set_time($prev);
list($previousmonth, ) = calendar_get_view($calendar, 'minithree', false, true);
// Current month.
$calendar->set_time($current);
list($currentmonth, ) = calendar_get_view($calendar, 'minithree', false, true);
// Next month.
$calendar->set_time($next);
list($nextmonth, ) = calendar_get_view($calendar, 'minithree', false, true);
// Reset the time back.
$calendar->set_time($current);
$data = (object) [
'previousmonth' => $previousmonth,
'currentmonth' => $currentmonth,
'nextmonth' => $nextmonth,
];
$template = 'core_calendar/calendar_threemonth';
$content .= $this->render_from_template($template, $data);
return $content;
public function fake_block_threemonths() {
throw new coding_exception(__FUNCTION__ . '() has been removed.');
}
/**
@@ -1,52 +0,0 @@
{{!
This file is part of Moodle - http://moodle.org/
Moodle is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Moodle is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
@template core_calendar/calendar_threemonth
@deprecated since 4.0 MDL-72810.
@todo MDL-73117 This will be deleted in Moodle 4.4.
Calendar view to show three months as a block.
The purpose of this template is to render a set of three months of calendar_mini in a block.
Classes required for JS:
* none
Data attributes required for JS:
* none
Example context (json):
{
}
}}
<div id="calendar-multi-{{uniqid}}">
{{#previousmonth}}
{{> core_calendar/threemonth_month}}
{{/previousmonth}}
{{#currentmonth}}
{{> core_calendar/threemonth_month}}
{{/currentmonth}}
{{#nextmonth}}
{{> core_calendar/threemonth_month}}
{{/nextmonth}}
</div>
{{#js}}
require(['jquery', 'core_calendar/calendar_threemonth'], function($, CalendarThreeMonth) {
CalendarThreeMonth.init($("#calendar-multi-{{uniqid}}"));
});
{{/js}}
-10
View File
@@ -122,16 +122,6 @@ class behat_calendar extends behat_base {
$this->i_hover_over_day_of_this_month_in_mini_calendar_block($todaysday);
}
/**
* Hover over today in the calendar.
*
* @Given /^I hover over today in the calendar$/
*/
public function i_hover_over_today_in_the_calendar() {
$todaysday = date('j');
return $this->i_hover_over_day_of_this_month_in_calendar($todaysday);
}
/**
* Navigate to a specific month in the calendar.
*
@@ -0,0 +1,59 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
require_once(__DIR__ . '/../../../lib/behat/behat_deprecated_base.php');
/**
* Steps definitions that are now deprecated and will be removed in the next releases.
*
* This file only contains the steps that previously were in the behat_*.php files in the SAME DIRECTORY.
* When deprecating steps from other components or plugins, create a behat_COMPONENT_deprecated.php
* file in the same directory where the steps were defined.
*
* @package core_calendar
* @category test
* @copyright 2024 Mathew May <mathew.solutions>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class behat_calendar_deprecated extends behat_deprecated_base {
/**
* Hover over today in the calendar.
*
* @Given /^I hover over today in the calendar$/
*
* @deprecated since 4.4 MDL-73117.
* @TODO MDL-79721: This will be deleted in Moodle 4.8.
*/
public function i_hover_over_today_in_the_calendar() {
$this->deprecated_message('behat_calendar::i_hover_over_today_in_the_calendar');
$todaysday = date('j');
$summarytitle = userdate(time(), get_string('strftimemonthyear'));
// The current month table.
$currentmonth = "table[descendant::*[self::caption[contains(concat(' ', normalize-space(.), ' '), ' {$summarytitle} ')]]]";
// Strings for the class cell match.
$cellclasses = "contains(concat(' ', normalize-space(@class), ' '), ' day ')";
$daycontains = "text()[contains(concat(' ', normalize-space(.), ' '), ' {$todaysday} ')]";
$daycell = "td[{$cellclasses}]";
$dayofmonth = "a[{$daycontains}]";
$xpath = '//' . $currentmonth . '/descendant::' . $daycell . '/' . $dayofmonth;
$this->execute("behat_general::i_hover", [$xpath, "xpath_element"]);
}
}
@@ -80,7 +80,6 @@ class calendar_event_exporter_test extends \advanced_testcase {
->getMock();
$reflector = new \ReflectionClass($class);
$method = $reflector->getMethod('get_timestamp_min_limit');
$method->setAccessible(true);
$result = $method->invoke($mock, $starttime, $min);
$this->assertEquals($expected, $result['mindaytimestamp']);
@@ -137,7 +136,6 @@ class calendar_event_exporter_test extends \advanced_testcase {
->getMock();
$reflector = new \ReflectionClass($class);
$method = $reflector->getMethod('get_timestamp_max_limit');
$method->setAccessible(true);
$result = $method->invoke($mock, $starttime, $max);
$this->assertEquals($expected, $result['maxdaytimestamp']);
-1
View File
@@ -124,7 +124,6 @@ class rrule_manager_test extends \advanced_testcase {
$reflectionclass = new \ReflectionClass($mang);
foreach ($props as $prop => $expectedval) {
$rcprop = $reflectionclass->getProperty($prop);
$rcprop->setAccessible(true);
$this->assertEquals($expectedval, $rcprop->getValue($mang));
}
}
+9
View File
@@ -5,6 +5,15 @@ information provided here is intended especially for developers.
* The following previously deprecated methods have been removed and can no longer be used:
- `calendar_process_subscription_row`
- `calendar_import_icalendar_events`
- `fake_block_threemonths`
- `i_click_day_of_this_month_in_calendar`
- `i_hover_over_today_in_the_calendar`
* The following previously deprecated files have been removed and can no longer be used:
- `calendar_threemonth.js`
- `calendar_threemonth.mustache`
- `threemonth_month.mustache`
* The following have been deprecated:
- Behat step definition `i_hover_over_today_in_the_calendar`
* The event_exporter_base class now returns a field called "branded" indicating whether the module is branded or not.
All the external functions using the exporter will now return the new field:
- core_calendar_get_action_events_by_course
@@ -281,7 +281,6 @@ class command_test extends \advanced_testcase {
);
$execute = new ReflectionMethod($instance, 'execute');
$execute->setAccessible(true);
$execute->invoke($instance, $command);
}
@@ -447,7 +447,6 @@ class matrix_client_test extends \advanced_testcase {
$rc = new \ReflectionClass($instance);
$rcm = $rc->getMethod('execute');
$rcm->setAccessible(true);
$result = $rcm->invoke($instance, $command);
$this->assertEquals(200, $result->getStatusCode());
+3 -1
View File
@@ -179,8 +179,10 @@ class completion_completion extends data_object {
// Notify user.
$course = get_course($data->course);
$messagesubject = get_string('coursecompleted', 'completion');
$options = new stdClass();
$options->context = context_course::instance($course->id);
$a = [
'coursename' => get_course_display_name_for_list($course),
'coursename' => format_string(get_course_display_name_for_list($course), true, $options),
'courselink' => (string) new moodle_url('/course/view.php', array('id' => $course->id)),
];
$messagebody = get_string('coursecompletedmessage', 'completion', $a);
-2
View File
@@ -568,7 +568,6 @@ class contentbank_test extends advanced_testcase {
// Replace protected singletoninstance reference (core_plugin_manager property) with mock object.
$ref = new \ReflectionProperty(\core_plugin_manager::class, 'singletoninstance');
$ref->setAccessible(true);
$ref->setValue(null, $pluginmanager);
// Return values of get_plugins_of_type method.
@@ -592,7 +591,6 @@ class contentbank_test extends advanced_testcase {
// Get access to private property enabledcontenttypes.
$rc = new \ReflectionClass(\core_contentbank\contentbank::class);
$rcp = $rc->getProperty('enabledcontenttypes');
$rcp->setAccessible(true);
foreach ($contenttypesenabled as $contenttypename) {
$plugins["\\contenttype_$contenttypename\\contenttype"] = $contenttypename;
@@ -45,7 +45,6 @@ class baseactions_test extends \advanced_testcase {
private function get_base_reflection_method(baseactions $baseinstance, string $methodname): ReflectionMethod {
$reflectionclass = new \reflectionclass($baseinstance);
$method = $reflectionclass->getMethod($methodname);
$method->setAccessible(true);
return $method;
}
-1
View File
@@ -72,7 +72,6 @@ class category_hooks_test extends \advanced_testcase {
// This is used to overcome private constructor.
$reflected = new \ReflectionClass(\core_course_category::class);
$constructor = $reflected->getConstructor();
$constructor->setAccessible(true);
$constructor->invoke($mockcategory, $category->get_db_record());
return $mockcategory;
-5
View File
@@ -98,7 +98,6 @@ class course_image_cache_test extends \advanced_testcase {
public function test_get_image_url_from_overview_files_return_null_if_no_summary_files_in_the_course() {
$method = new ReflectionMethod(course_image::class, 'get_image_url_from_overview_files');
$cache = course_image::get_instance_for_cache(new cache_definition());
$method->setAccessible(true);
// Create course without files.
$course = $this->getDataGenerator()->create_course();
@@ -111,7 +110,6 @@ class course_image_cache_test extends \advanced_testcase {
public function test_get_image_url_from_overview_files_returns_null_if_no_summary_images_in_the_course() {
$method = new ReflectionMethod(course_image::class, 'get_image_url_from_overview_files');
$cache = course_image::get_instance_for_cache(new cache_definition());
$method->setAccessible(true);
// Create course without image files.
$draftid2 = $this->fill_draft_area(['filename2.zip' => 'Test file contents2']);
@@ -125,7 +123,6 @@ class course_image_cache_test extends \advanced_testcase {
public function test_get_image_url_from_overview_files_returns_url_if_there_is_a_summary_image() {
$method = new ReflectionMethod(course_image::class, 'get_image_url_from_overview_files');
$cache = course_image::get_instance_for_cache(new cache_definition());
$method->setAccessible(true);
// Create course without one image.
$draftid1 = $this->fill_draft_area(['filename1.jpg' => file_get_contents(__DIR__ . '/fixtures/image.jpg')]);
@@ -140,7 +137,6 @@ class course_image_cache_test extends \advanced_testcase {
public function test_get_image_url_from_overview_files_returns_url_of_the_first_image_if_there_are_many_summary_images() {
$method = new ReflectionMethod(course_image::class, 'get_image_url_from_overview_files');
$cache = course_image::get_instance_for_cache(new cache_definition());
$method->setAccessible(true);
// Create course with two image files.
$draftid1 = $this->fill_draft_area([
@@ -159,7 +155,6 @@ class course_image_cache_test extends \advanced_testcase {
public function test_get_image_url_from_overview_files_returns_url_of_the_first_image_if_there_are_many_summary_files() {
$method = new ReflectionMethod(course_image::class, 'get_image_url_from_overview_files');
$cache = course_image::get_instance_for_cache(new cache_definition());
$method->setAccessible(true);
// Create course with two image files and one zip file.
$draftid1 = $this->fill_draft_area([
-7
View File
@@ -413,7 +413,6 @@ class targets_test extends \advanced_testcase {
$class = new \ReflectionClass('\core\analytics\analyser\student_enrolments');
$method = $class->getMethod('get_all_samples');
$method->setAccessible(true);
list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable);
$target->add_sample_data($samplesdata);
@@ -448,7 +447,6 @@ class targets_test extends \advanced_testcase {
$class = new \ReflectionClass('\core\analytics\analyser\student_enrolments');
$method = $class->getMethod('get_all_samples');
$method->setAccessible(true);
list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable);
$target->add_sample_data($samplesdata);
@@ -456,7 +454,6 @@ class targets_test extends \advanced_testcase {
$reftarget = new \ReflectionObject($target);
$refmethod = $reftarget->getMethod('calculate_sample');
$refmethod->setAccessible(true);
if ($nullcalculation) {
$this->assertNull($refmethod->invoke($target, $sampleid, $analysable, $starttime, $endtime));
@@ -532,7 +529,6 @@ class targets_test extends \advanced_testcase {
$class = new \ReflectionClass('\core\analytics\analyser\student_enrolments');
$method = $class->getMethod('get_all_samples');
$method->setAccessible(true);
list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable);
$target->add_sample_data($samplesdata);
@@ -540,7 +536,6 @@ class targets_test extends \advanced_testcase {
$class = new \ReflectionClass('\core_course\analytics\target\course_competencies');
$method = $class->getMethod('calculate_sample');
$method->setAccessible(true);
// Method calculate_sample() returns 1 when the user has not achieved all the competencies assigned to the course.
$this->assertEquals(1, $method->invoke($target, $sampleid, $analysable));
@@ -630,14 +625,12 @@ class targets_test extends \advanced_testcase {
$class = new \ReflectionClass('\core\analytics\analyser\student_enrolments');
$method = $class->getMethod('get_all_samples');
$method->setAccessible(true);
list($sampleids, $samplesdata) = $method->invoke($analyser, $analysable);
$target->add_sample_data($samplesdata);
$class = new \ReflectionClass('\core_course\analytics\target\course_gradetopass');
$method = $class->getMethod('calculate_sample');
$method->setAccessible(true);
// Verify all the expectations are fulfilled.
foreach ($sampleids as $sampleid => $key) {

Some files were not shown because too many files have changed in this diff Show More