From 409f8c22bb27e19c4f0838009165ae29e85b8d91 Mon Sep 17 00:00:00 2001 From: djarrancotleanu Date: Thu, 17 Oct 2024 14:58:14 +1000 Subject: [PATCH 1/4] Issue #71: Use new 'after_config' hook for Moodle 4.5 --- classes/hook_callbacks.php | 124 +++++++++++++++++++++++++++++++++++++ db/hooks.php | 5 ++ lib.php | 4 ++ version.php | 6 +- 4 files changed, 136 insertions(+), 3 deletions(-) diff --git a/classes/hook_callbacks.php b/classes/hook_callbacks.php index e20000d..4ca925a 100644 --- a/classes/hook_callbacks.php +++ b/classes/hook_callbacks.php @@ -53,4 +53,128 @@ public static function before_footer_html_generation(\core\hook\output\before_fo 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) { + if (!get_config('tool_abconfig', 'version')) { + // Do nothing if plugin install not completed. + return; + } + + 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; From e0caccff9ec9c6adf5594e537678eac075c5d6a7 Mon Sep 17 00:00:00 2001 From: djarrancotleanu Date: Thu, 21 Nov 2024 17:06:07 +1000 Subject: [PATCH 2/4] Issue #71: Add during_initial_install check --- classes/hook_callbacks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/hook_callbacks.php b/classes/hook_callbacks.php index 4ca925a..a55ebba 100644 --- a/classes/hook_callbacks.php +++ b/classes/hook_callbacks.php @@ -61,7 +61,7 @@ public static function before_footer_html_generation(\core\hook\output\before_fo * @return void|null */ public static function after_config(\core\hook\after_config $hook) { - if (!get_config('tool_abconfig', 'version')) { + if (during_initial_install() || !get_config('tool_abconfig', 'version')) { // Do nothing if plugin install not completed. return; } From 3719cd0b853a01c8a5c7ee8cabd78ddd41732738 Mon Sep 17 00:00:00 2001 From: djarrancotleanu Date: Mon, 2 Dec 2024 11:27:16 +1000 Subject: [PATCH 3/4] Issue #71: Call existing after_config callback in hook --- classes/hook_callbacks.php | 111 +------------------------------------ 1 file changed, 1 insertion(+), 110 deletions(-) diff --git a/classes/hook_callbacks.php b/classes/hook_callbacks.php index a55ebba..2d7e215 100644 --- a/classes/hook_callbacks.php +++ b/classes/hook_callbacks.php @@ -66,115 +66,6 @@ public static function after_config(\core\hook\after_config $hook) { return; } - 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 + tool_abconfig_after_config(); } } From 401a413e482df277c6d2d99594a3fb4a36d16e59 Mon Sep 17 00:00:00 2001 From: djarrancotleanu Date: Mon, 2 Dec 2024 12:20:22 +1000 Subject: [PATCH 4/4] Issue #71: Update param in after_config hook --- classes/hook_callbacks.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes/hook_callbacks.php b/classes/hook_callbacks.php index 2d7e215..b336981 100644 --- a/classes/hook_callbacks.php +++ b/classes/hook_callbacks.php @@ -57,7 +57,7 @@ public static function before_footer_html_generation(\core\hook\output\before_fo /** * Runs after config has been set. * - * @param \core\hook\before_http_headers $hook + * @param \core\hook\after_config $hook * @return void|null */ public static function after_config(\core\hook\after_config $hook) {