From fcee9eaafa31c3f652be2357ede5940e737b1bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mudr=C3=A1k?= Date: Fri, 16 Nov 2018 14:00:55 +0100 Subject: [PATCH] MDL-64061 javascript: Allow js_call_amd() be called without a function Not all AMD modules need an explicit function call to start working. The patch makes the function name optional, in which case the js_call_amd() simply loads the module. --- lib/outputrequirementslib.php | 50 ++++++++++++++---------- lib/tests/outputrequirementslib_test.php | 27 +++++++++++++ 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/lib/outputrequirementslib.php b/lib/outputrequirementslib.php index 28d3c709faa..9cf473503e6 100644 --- a/lib/outputrequirementslib.php +++ b/lib/outputrequirementslib.php @@ -999,37 +999,47 @@ class page_requirements_manager { } /** - * This function creates a minimal JS script that requires and calls a single function from an AMD module with arguments. - * If it is called multiple times, it will be executed multiple times. + * Load an AMD module and eventually call its method. * - * @param string $fullmodule The format for module names is /. - * @param string $func The function from the module to call - * @param array $params The params to pass to the function. They will be json encoded, so no nasty classes/types please. + * This function creates a minimal inline JS snippet that requires an AMD module and eventually calls a single + * function from the module with given arguments. If it is called multiple times, it will be create multiple + * snippets. + * + * @param string $fullmodule The name of the AMD module to load, formatted as /. + * @param string $func Optional function from the module to call, defaults to just loading the AMD module. + * @param array $params The params to pass to the function (will be serialized into JSON). */ - public function js_call_amd($fullmodule, $func, $params = array()) { + public function js_call_amd($fullmodule, $func = null, $params = array()) { global $CFG; list($component, $module) = explode('/', $fullmodule, 2); $component = clean_param($component, PARAM_COMPONENT); $module = clean_param($module, PARAM_ALPHANUMEXT); - $func = clean_param($func, PARAM_ALPHANUMEXT); - $jsonparams = array(); - foreach ($params as $param) { - $jsonparams[] = json_encode($param); - } - $strparams = implode(', ', $jsonparams); - if ($CFG->debugdeveloper) { - $toomanyparamslimit = 1024; - if (strlen($strparams) > $toomanyparamslimit) { - debugging('Too much data passed as arguments to js_call_amd("' . $fullmodule . '", "' . $func . - '"). Generally there are better ways to pass lots of data from PHP to JavaScript, for example via Ajax, data attributes, ... . ' . - 'This warning is triggered if the argument string becomes longer than ' . $toomanyparamslimit . ' characters.', DEBUG_DEVELOPER); + if ($func !== null) { + $func = clean_param($func, PARAM_ALPHANUMEXT); + + $jsonparams = array(); + foreach ($params as $param) { + $jsonparams[] = json_encode($param); + } + $strparams = implode(', ', $jsonparams); + if ($CFG->debugdeveloper) { + $toomanyparamslimit = 1024; + if (strlen($strparams) > $toomanyparamslimit) { + debugging('Too much data passed as arguments to js_call_amd("' . $fullmodule . '", "' . $func . + '"). Generally there are better ways to pass lots of data from PHP to JavaScript, for example via Ajax, ' . + 'data attributes, ... . This warning is triggered if the argument string becomes longer than ' . + $toomanyparamslimit . ' characters.', DEBUG_DEVELOPER); + } } - } - $js = 'require(["' . $component . '/' . $module . '"], function(amd) { amd.' . $func . '(' . $strparams . '); });'; + $js = 'require(["' . $component . '/' . $module . '"], function(amd) { amd.' . $func . '(' . $strparams . '); });'; + + } else { + $js = 'require(["' . $component . '/' . $module . '"]);'; + } $this->js_amd_inline($js); } diff --git a/lib/tests/outputrequirementslib_test.php b/lib/tests/outputrequirementslib_test.php index 9d98ed70752..58680786d24 100644 --- a/lib/tests/outputrequirementslib_test.php +++ b/lib/tests/outputrequirementslib_test.php @@ -102,4 +102,31 @@ class core_outputrequirementslib_testcase extends advanced_testcase { // Make sure that the generated code does not contain backslashes. $this->assertFalse(strpos($requirecode, '\\'), "Output contains backslashes: " . $requirecode); } + + /** + * Test AMD modules loading. + */ + public function test_js_call_amd() { + + $page = new moodle_page(); + + // Load an AMD module without a function call. + $page->requires->js_call_amd('theme_foobar/lightbox'); + + // Load an AMD module and call its function without parameters. + $page->requires->js_call_amd('theme_foobar/demo_one', 'init'); + + // Load an AMD module and call its function with some parameters. + $page->requires->js_call_amd('theme_foobar/demo_two', 'init', [ + 'foo', + 'keyWillIgnored' => 'baz', + [42, 'xyz'], + ]); + + $html = $page->requires->get_end_code(); + + $this->assertContains('require(["theme_foobar/lightbox"]);', $html); + $this->assertContains('require(["theme_foobar/demo_one"], function(amd) { amd.init(); });', $html); + $this->assertContains('require(["theme_foobar/demo_two"], function(amd) { amd.init("foo", "baz", [42,"xyz"]); });', $html); + } }