diff --git a/lib/outputcomponents.php b/lib/outputcomponents.php index 2fe139b1124..89087212ae5 100644 --- a/lib/outputcomponents.php +++ b/lib/outputcomponents.php @@ -1012,13 +1012,8 @@ class single_button implements renderable { } // Form parameters. - $params = $this->url->params(); - if ($this->method === 'post') { - $params['sesskey'] = sesskey(); - } - $data->params = array_map(function($key) use ($params) { - return ['name' => $key, 'value' => $params[$key]]; - }, array_keys($params)); + $actionurl = new moodle_url($this->url, ['sesskey' => sesskey()]); + $data->params = $actionurl->export_params_for_template(); // Button actions. $actions = $this->actions; @@ -1220,13 +1215,8 @@ class single_select implements renderable, templatable { }, array_keys($attributes)); // Form parameters. - $params = $this->url->params(); - if ($this->method === 'post') { - $params['sesskey'] = sesskey(); - } - $data->params = array_map(function($key) use ($params) { - return ['name' => $key, 'value' => $params[$key]]; - }, array_keys($params)); + $actionurl = new moodle_url($this->url, ['sesskey' => sesskey()]); + $data->params = $actionurl->export_params_for_template(); // Select options. $hasnothing = false; diff --git a/lib/tests/moodle_url_test.php b/lib/tests/moodle_url_test.php index a2de3e24941..61b39455e64 100644 --- a/lib/tests/moodle_url_test.php +++ b/lib/tests/moodle_url_test.php @@ -19,9 +19,10 @@ namespace core; /** * Tests for moodle_url. * - * @package core - * @copyright 2018 Andrew Nicols - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @package core + * @copyright 2018 Andrew Nicols + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @covers \moodle_url */ class moodle_url_test extends \advanced_testcase { /** @@ -249,6 +250,74 @@ class moodle_url_test extends \advanced_testcase { $this->assertSame('', $url->get_port()); } + /** + * Test exporting params for templates. + * + * @dataProvider moodle_url_export_params_for_template_provider + * @param string $url URL with params to test. + * @param array $expected The expected result. + */ + public function test_moodle_url_export_params_for_template(string $url, array $expected) :void { + // Should return params in the URL. + $moodleurl = new \moodle_url($url); + $this->assertSame($expected, $moodleurl->export_params_for_template()); + } + + /** + * Data provider for moodle_url_export_params_for_template tests. + * + * @return array[] the array of test data. + */ + public function moodle_url_export_params_for_template_provider() :array { + $baseurl = "http://example.com"; + return [ + 'With indexed array params' => [ + 'url' => "@{$baseurl}/?tags[0]=123&tags[1]=456", + 'expected' => [ + 0 => ['name' => 'tags[0]', 'value' => '123'], + 1 => ['name' => 'tags[1]', 'value' => '456'] + ] + ], + 'Without indexed array params' => [ + 'url' => "@{$baseurl}/?tags[]=123&tags[]=456", + 'expected' => [ + 0 => ['name' => 'tags[0]', 'value' => '123'], + 1 => ['name' => 'tags[1]', 'value' => '456'] + ] + ], + 'with no params' => [ + 'url' => "@{$baseurl}/", + 'expected' => [] + ], + 'with no array params' => [ + 'url' => "@{$baseurl}/?param1=1¶m2=2¶m3=3", + 'expected' => [ + 0 => ['name' => 'param1', 'value' => '1'], + 1 => ['name' => 'param2', 'value' => '2'], + 2 => ['name' => 'param3', 'value' => '3'], + ] + ], + 'array embedded with other params' => [ + 'url' => "@{$baseurl}/?param1=1&tags[0]=123&tags[1]=456¶m2=2¶m3=3", + 'expected' => [ + 0 => ['name' => 'param1', 'value' => '1'], + 1 => ['name' => 'tags[0]', 'value' => '123'], + 2 => ['name' => 'tags[1]', 'value' => '456'], + 3 => ['name' => 'param2', 'value' => '2'], + 4 => ['name' => 'param3', 'value' => '3'], + ] + ], + 'params with array at the end' => [ + 'url' => "@{$baseurl}/?param1=1&tags[]=123&tags[]=456", + 'expected' => [ + 0 => ['name' => 'param1', 'value' => '1'], + 1 => ['name' => 'tags[0]', 'value' => '123'], + 2 => ['name' => 'tags[1]', 'value' => '456'], + ] + ], + ]; + } + /** * Test the make_pluginfile_url function. * diff --git a/lib/upgrade.txt b/lib/upgrade.txt index 17689869a4a..466d4ed0551 100644 --- a/lib/upgrade.txt +++ b/lib/upgrade.txt @@ -118,6 +118,8 @@ information provided here is intended especially for developers. parameter. This information can be used by the plugins when enclosing the icons in `.activityiconcontainer .icon` or `.activityiconcontainer .activityicon` containers to determine whether CSS filtering should be applied to the icon. If the icon needs to be rendered as is and not whitened out, the `.nofilter` CSS class needs to be applied to the icon. +* New moodle_url::export_params_for_template() returns the params as an array of key => value pairs. You should use this when + you want to pass URL params to a template. An example can be found in single button. === 4.1 === diff --git a/lib/weblib.php b/lib/weblib.php index bc40502da56..3520813b4e9 100644 --- a/lib/weblib.php +++ b/lib/weblib.php @@ -537,6 +537,27 @@ class moodle_url { } } + /** + * Get the url params as an array of key => value pairs. + * + * This helps in handling cases where url params contain arrays. + * + * @return array params array for templates. + */ + public function export_params_for_template(): array { + $data = []; + foreach ($this->params as $key => $val) { + if (is_array($val)) { + foreach ($val as $index => $value) { + $data[] = ['name' => $key.'['.$index.']', 'value' => $value]; + } + } else { + $data[] = ['name' => $key, 'value' => $val]; + } + } + return $data; + } + /** * Shortcut for printing of encoded URL. * diff --git a/question/bank/deletequestion/tests/behat/delete_question_column.feature b/question/bank/deletequestion/tests/behat/delete_question_column.feature index c20b49baecf..ac6603f1f83 100644 --- a/question/bank/deletequestion/tests/behat/delete_question_column.feature +++ b/question/bank/deletequestion/tests/behat/delete_question_column.feature @@ -54,3 +54,20 @@ Feature: Use the qbank plugin manager page for deletequestion And I click on "Delete" "button" in the "Confirm" "dialogue" Then I should not see "First question" And I should not see "First question second" + + @javascript + Scenario: I should be able to delete a question when filtered using tags + Given I am on the "First question" "core_question > edit" page logged in as "admin" + And I set the following fields to these values: + | Tags | foo | + And I click on "Save changes" "button" + And I am on the "Test quiz" "mod_quiz > question bank" page + And I open the autocomplete suggestions list + And I click on "foo" item in the autocomplete list + And "foo" "autocomplete_selection" should exist + And I click on "First question" "checkbox" + And I click on "With selected" "button" + And I click on question bulk action "deleteselected" + When I click on "Delete" "button" in the "Confirm" "dialogue" + Then I should not see "Third question" + And "foo" "autocomplete_selection" should exist