From e9abb3a5de3b7088d18ef2878ea111e4b8b897bc Mon Sep 17 00:00:00 2001 From: Marina Glancy Date: Mon, 4 Dec 2023 15:09:01 +0000 Subject: [PATCH] MDL-79076 output: convert callback before_standard_html_head --- .../output/standard_head_html_prepend.php | 53 +++++++++++ admin/tool/mobile/db/hooks.php | 33 +++++++ admin/tool/mobile/lib.php | 27 ------ .../output/standard_head_html_prepend.php | 50 ++++++++++ admin/tool/policy/db/hooks.php | 33 +++++++ admin/tool/policy/lib.php | 26 ----- .../output/standard_head_html_prepend.php | 94 +++++++++++++++++++ lib/outputrenderers.php | 11 +-- lib/tests/component_test.php | 2 +- lib/upgrade.txt | 2 + 10 files changed, 271 insertions(+), 60 deletions(-) create mode 100644 admin/tool/mobile/classes/local/hooks/output/standard_head_html_prepend.php create mode 100644 admin/tool/mobile/db/hooks.php create mode 100644 admin/tool/policy/classes/local/hooks/output/standard_head_html_prepend.php create mode 100644 admin/tool/policy/db/hooks.php create mode 100644 lib/classes/hook/output/standard_head_html_prepend.php diff --git a/admin/tool/mobile/classes/local/hooks/output/standard_head_html_prepend.php b/admin/tool/mobile/classes/local/hooks/output/standard_head_html_prepend.php new file mode 100644 index 00000000000..f349ea39260 --- /dev/null +++ b/admin/tool/mobile/classes/local/hooks/output/standard_head_html_prepend.php @@ -0,0 +1,53 @@ +. + +namespace tool_mobile\local\hooks\output; + +/** + * Allows plugins to add any elements to the page html tag + * + * @package tool_mobile + * @copyright 2023 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class standard_head_html_prepend { + + /** + * Callback to add head elements. + * + * @param \core\hook\output\standard_head_html_prepend $hook + */ + public static function callback(\core\hook\output\standard_head_html_prepend $hook): void { + global $CFG, $PAGE; + // Smart App Banners meta tag is only displayed if mobile services are enabled and configured. + if (!empty($CFG->enablemobilewebservice)) { + $mobilesettings = get_config('tool_mobile'); + if (!empty($mobilesettings->enablesmartappbanners)) { + if (!empty($mobilesettings->iosappid)) { + $hook->add_html( + '' + ); + } + + if (!empty($mobilesettings->androidappid)) { + $mobilemanifesturl = "$CFG->wwwroot/$CFG->admin/tool/mobile/mobile.webmanifest.php"; + $hook->add_html(''); + } + } + } + } +} diff --git a/admin/tool/mobile/db/hooks.php b/admin/tool/mobile/db/hooks.php new file mode 100644 index 00000000000..60e2d927e8c --- /dev/null +++ b/admin/tool/mobile/db/hooks.php @@ -0,0 +1,33 @@ +. + +/** + * Hook callbacks for Moodle app tools + * + * @package tool_mobile + * @copyright 2023 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +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', + 'priority' => 0, + ], +]; diff --git a/admin/tool/mobile/lib.php b/admin/tool/mobile/lib.php index 3ecf96402c1..a7c5125048f 100644 --- a/admin/tool/mobile/lib.php +++ b/admin/tool/mobile/lib.php @@ -24,33 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -/** - * Callback to add head elements. - * - * @return str valid html head content - * @since Moodle 3.3 - */ -function tool_mobile_before_standard_html_head() { - global $CFG, $PAGE; - $output = ''; - // Smart App Banners meta tag is only displayed if mobile services are enabled and configured. - if (!empty($CFG->enablemobilewebservice)) { - $mobilesettings = get_config('tool_mobile'); - if (!empty($mobilesettings->enablesmartappbanners)) { - if (!empty($mobilesettings->iosappid)) { - $output .= ''; - } - - if (!empty($mobilesettings->androidappid)) { - $mobilemanifesturl = "$CFG->wwwroot/$CFG->admin/tool/mobile/mobile.webmanifest.php"; - $output .= ''; - } - } - } - return $output; -} - /** * Generate the app download url to promote moodle mobile. * diff --git a/admin/tool/policy/classes/local/hooks/output/standard_head_html_prepend.php b/admin/tool/policy/classes/local/hooks/output/standard_head_html_prepend.php new file mode 100644 index 00000000000..7f137b9693e --- /dev/null +++ b/admin/tool/policy/classes/local/hooks/output/standard_head_html_prepend.php @@ -0,0 +1,50 @@ +. + +namespace tool_policy\local\hooks\output; + +/** + * Allows plugins to add any elements to the page html tag + * + * @package tool_policy + * @copyright 2023 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class standard_head_html_prepend { + + /** + * Load policy message for guests. + * + * @param \core\hook\output\standard_head_html_prepend $hook + */ + public static function callback(\core\hook\output\standard_head_html_prepend $hook): void { + global $CFG, $PAGE, $USER; + + if (!empty($CFG->sitepolicyhandler) + && $CFG->sitepolicyhandler == 'tool_policy' + && empty($USER->policyagreed) + && (isguestuser() || !isloggedin())) { + $output = $PAGE->get_renderer('tool_policy'); + try { + $page = new \tool_policy\output\guestconsent(); + $hook->add_html($output->render($page)); + // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch + } catch (\dml_read_exception $e) { + // During upgrades, the new plugin code with new SQL could be in place but the DB not upgraded yet. + } + } + } +} diff --git a/admin/tool/policy/db/hooks.php b/admin/tool/policy/db/hooks.php new file mode 100644 index 00000000000..28e3d695512 --- /dev/null +++ b/admin/tool/policy/db/hooks.php @@ -0,0 +1,33 @@ +. + +/** + * Hook callbacks for Policies + * + * @package tool_policy + * @copyright 2023 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$callbacks = [ + [ + 'hook' => core\hook\output\standard_head_html_prepend::class, + 'callback' => 'tool_policy\local\hooks\output\standard_head_html_prepend::callback', + 'priority' => 0, + ], +]; diff --git a/admin/tool/policy/lib.php b/admin/tool/policy/lib.php index 07504daed5e..196cc140fc4 100644 --- a/admin/tool/policy/lib.php +++ b/admin/tool/policy/lib.php @@ -71,32 +71,6 @@ function tool_policy_myprofile_navigation(tree $tree, $user, $iscurrentuser, $co return true; } -/** - * Load policy message for guests. - * - * @return string The HTML code to insert before the head. - */ -function tool_policy_before_standard_html_head() { - global $CFG, $PAGE, $USER; - - $message = null; - if (!empty($CFG->sitepolicyhandler) - && $CFG->sitepolicyhandler == 'tool_policy' - && empty($USER->policyagreed) - && (isguestuser() || !isloggedin())) { - $output = $PAGE->get_renderer('tool_policy'); - try { - $page = new \tool_policy\output\guestconsent(); - $message = $output->render($page); - } catch (dml_read_exception $e) { - // During upgrades, the new plugin code with new SQL could be in place but the DB not upgraded yet. - $message = null; - } - } - - return $message; -} - /** * Callback to add footer elements. * diff --git a/lib/classes/hook/output/standard_head_html_prepend.php b/lib/classes/hook/output/standard_head_html_prepend.php new file mode 100644 index 00000000000..52b7b9553d6 --- /dev/null +++ b/lib/classes/hook/output/standard_head_html_prepend.php @@ -0,0 +1,94 @@ +. + +namespace core\hook\output; + +use core\hook\described_hook; +use core\hook\deprecated_callback_replacement; + +/** + * Allows plugins to add any elements to the page html tag + * + * @package core + * @copyright 2023 Marina Glancy + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class standard_head_html_prepend implements described_hook, deprecated_callback_replacement { + /** @var string $output Stores results from callbacks */ + private $output = ''; + + /** + * Describes the hook purpose. + * + * @return string + */ + public static function get_hook_description(): string { + return 'Allows plugins to add any elements to the page <head> html tag.'; + } + + /** + * List of tags that describe this hook. + * + * @return string[] + */ + public static function get_hook_tags(): array { + return ['output']; + } + + /** + * Returns list of lib.php plugin callbacks that were deprecated by the hook. + * + * @return array + */ + public static function get_deprecated_plugin_callbacks(): array { + return ['before_standard_html_head']; + } + + /** + * Plugins implementing callback can add any HTML to the page. + * + * Must be a string containing valid html head content + * + * @param string $output + */ + public function add_html(string $output): void { + $this->output .= $output; + } + + /** + * Returns all HTML added by the plugins + * + * @return string + */ + public function get_output(): string { + return $this->output; + } + + /** + * Process legacy callbacks. + * + * Legacy callback 'before_standard_html_head' is deprecated since Moodle 4.4 + */ + public function process_legacy_callbacks(): void { + $pluginswithfunction = get_plugins_with_function('before_standard_html_head', 'lib.php', true, true); + foreach ($pluginswithfunction as $plugins) { + foreach ($plugins as $function) { + $output = $function(); + $this->add_html((string)$output); + } + } + } +} diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 3cef72177a2..d28430b929c 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -702,12 +702,11 @@ class core_renderer extends renderer_base { // Give plugins an opportunity to add any head elements. The callback // must always return a string containing valid html head content. - $pluginswithfunction = get_plugins_with_function('before_standard_html_head', 'lib.php'); - foreach ($pluginswithfunction as $plugins) { - foreach ($plugins as $function) { - $output .= $function(); - } - } + + $hook = new \core\hook\output\standard_head_html_prepend(); + \core\hook\manager::get_instance()->dispatch($hook); + $hook->process_legacy_callbacks(); + $output .= $hook->get_output(); // Allow a url_rewrite plugin to setup any dynamic head content. if (isset($CFG->urlrewriteclass) && !isset($CFG->upgraderunning)) { diff --git a/lib/tests/component_test.php b/lib/tests/component_test.php index 59f558f5237..5df2a1c34d8 100644 --- a/lib/tests/component_test.php +++ b/lib/tests/component_test.php @@ -540,7 +540,7 @@ class component_test extends advanced_testcase { $this->assertCount(5, core_component::get_component_classes_in_namespace('core_user', 'output\\myprofile')); // Without namespace it returns classes/ classes. - $this->assertCount(5, core_component::get_component_classes_in_namespace('tool_mobile', '')); + $this->assertCount(6, core_component::get_component_classes_in_namespace('tool_mobile', '')); $this->assertCount(2, core_component::get_component_classes_in_namespace('tool_filetypes')); // When no component is specified, classes are returned for the namespace in all components. diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 6f62d0ddae3..4ccb63f4f8f 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -26,6 +26,8 @@ information provided here is intended especially for developers. - set_attempts_available(): Used to set the number of attempts available for the task - get_attempts_available(): Used to get the number of attempts available for the task. * There is a new DML method $DB->get_fieldset. For some reason, this did not exist even though get_fieldset_select etc. did. +* The following callbacks have been migrated to hooks: + - before_standard_html_head() -> core\hook\output\standard_head_html_prepend === 4.3 ===