From d96092fcfedd89d2ea8a51e427e1e9f96357d1d8 Mon Sep 17 00:00:00 2001 From: djarrancotleanu Date: Thu, 17 Oct 2024 14:58:14 +1000 Subject: [PATCH] #71 WIP: Use new 'after_config' hook for Moodle 4.5 --- classes/hook_callbacks.php | 119 +++++++++++++++++++++++++++++++++++++ db/hooks.php | 5 ++ lib.php | 4 ++ version.php | 6 +- 4 files changed, 131 insertions(+), 3 deletions(-) diff --git a/classes/hook_callbacks.php b/classes/hook_callbacks.php index 467bc7a..2450386 100644 --- a/classes/hook_callbacks.php +++ b/classes/hook_callbacks.php @@ -43,4 +43,123 @@ public static function before_http_headers(\core\hook\output\before_http_headers public static function before_footer_html_generation(\core\hook\output\before_footer_html_generation $hook): void { tool_abconfig_execute_js('footer'); } + + /** + * Runs after config has been set. + * + * @param \core\hook\before_http_headers $hook + * @return void|null + */ + public static function after_config(\core\hook\after_config $hook) { + try { + global $SESSION, $USER; + + // Setup experiment manager. + $manager = new \tool_abconfig_experiment_manager(); + + // Check if the param to disable ABconfig is present, if so, exit. + if (!optional_param('abconfig', true, PARAM_BOOL)) { + if (is_siteadmin()) { + return null; + } + } + + // Get all experiments. + $experiments = $manager->get_experiments(); + foreach ($experiments as $experiment => $contents) { + + if (defined('CLI_SCRIPT') && CLI_SCRIPT) { + // Check ENV vars set on the cli. + $condition = getenv('ABCONFIG_' . strtoupper($experiment)); + } else { + + // Check URL params, and fire any experiments in the params. + $condition = optional_param($experiment, null, PARAM_TEXT); + + // Only admins can fire additional experiments. + if (!is_siteadmin()) { + break; + } + } + + if (empty($condition)) { + continue; + } + + // Ensure condition set exists before executing. + if (array_key_exists($condition, $contents['conditions'])) { + tool_abconfig_execute_command_array($contents['conditions'][$condition]['commands'], + $contents['shortname']); + } + } + + $commandarray = array(); + + // First, Build a list of all commands that need to be executed. + + // Start with request scope. + $requestexperiments = $manager->get_active_request(); + if (!empty($requestexperiments)) { + foreach ($requestexperiments as $record) { + + // Make admin immune unless enabled for admin. + if (is_siteadmin()) { + if ($record['adminenabled'] == 0) { + continue; + } + } + + $conditionrecords = $record['conditions']; + + // Remove all conditions that contain the user ip in the whitelist. + $crecords = array(); + + foreach ($conditionrecords as $conditionrecord) { + $iplist = $conditionrecord['ipwhitelist']; + $users = !empty($conditionrecord['users']) ? json_decode($conditionrecord['users']) : []; + if (empty($users) || in_array($USER->id, $users)) { + if (!remoteip_in_list($iplist)) { + array_push($crecords, $conditionrecord); + } + } + } + + // Increment through conditions until one is selected. + $condition = ''; + $num = rand(1, 100); + $prevtotal = 0; + foreach ($crecords as $crecord) { + // If random number is within this range, set condition and break, else increment total. + if ($num > $prevtotal && $num <= ($prevtotal + $crecord['value'])) { + $commandarray[$record['shortname']] = $crecord['commands']; + // Do not select any more conditions. + break; + } else { + // Not this record, increment lower bound, and move on. + $prevtotal += $crecord['value']; + } + } + } + } + + // Now session scope. + $sessionexperiments = $manager->get_active_session(); + if (!empty($sessionexperiments)) { + foreach ($sessionexperiments as $record) { + // Check if a session var has been set for this experiment, only care if has been set. + $unique = 'abconfig_'.$record['shortname']; + if (property_exists($SESSION, $unique) && $SESSION->$unique != '') { + $commandarray[$record['shortname']] = $record['conditions'][$SESSION->$unique]['commands']; + } + } + } + + // Now, execute all commands in the arrays. + foreach ($commandarray as $shortname => $command) { + tool_abconfig_execute_command_array($command, $shortname); + } + } catch (\Exception $e) { // @codingStandardsIgnoreStart + // Catch exceptions from stuff not existing during installation process, fail silently + } // @codingStandardsIgnoreEnd + } } diff --git a/db/hooks.php b/db/hooks.php index 18c531a..463215d 100644 --- a/db/hooks.php +++ b/db/hooks.php @@ -36,4 +36,9 @@ 'callback' => '\tool_abconfig\hook_callbacks::before_footer_html_generation', 'priority' => 0, ], + [ + 'hook' => \core\hook\after_config::class, + 'callback' => '\tool_abconfig\hook_callbacks::after_config', + 'priority' => 0, + ], ]; diff --git a/lib.php b/lib.php index 8b596ec..84dfc77 100644 --- a/lib.php +++ b/lib.php @@ -26,6 +26,10 @@ /** * After config + * + * This is a legacy callback that is used for compatibility with older Moodle versions. + * Moodle 4.4+ will use tool_abconfig\hook_callbacks::after_config instead. + * * @return void|null */ function tool_abconfig_after_config() { diff --git a/version.php b/version.php index b6ffb2c..0c92d4d 100644 --- a/version.php +++ b/version.php @@ -25,9 +25,9 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024060400; // The current plugin version (Date: YYYYMMDDXX). -$plugin->release = 2024060400; // Same as version. +$plugin->version = 2024060401; // The current plugin version (Date: YYYYMMDDXX). +$plugin->release = 2024060401; // Same as version. $plugin->requires = 2014051217; -$plugin->supported = [38, 404]; // Available as of Moodle 3.8.0 or later. +$plugin->supported = [38, 405]; // Available as of Moodle 3.8.0 or later. $plugin->component = "tool_abconfig"; $plugin->maturity = MATURITY_STABLE;