From 36e6789b2747a5d2b52f0b0fae0a200665ff8be0 Mon Sep 17 00:00:00 2001 From: Frederic Massart Date: Thu, 1 Dec 2016 12:48:42 +0800 Subject: [PATCH] MDL-57101 filter: Load globally available filters on every page Previous commits were overlooked, they should have passed the system context to filter_manager::setup_page_for_fitlers(), the page context was passed instead. Regardless, the processing of the latter is too excessive for what we need, but, more importantly, it does not return "Off, but available" filters which we also need. --- lib/filterlib.php | 67 ++++++++++++++++++++++++++++++++++++ lib/pagelib.php | 2 +- lib/tests/filterlib_test.php | 33 ++++++++++++++++++ media/classes/player.php | 6 ++++ 4 files changed, 107 insertions(+), 1 deletion(-) diff --git a/lib/filterlib.php b/lib/filterlib.php index 0c2343105a9..230fd3fe728 100644 --- a/lib/filterlib.php +++ b/lib/filterlib.php @@ -272,6 +272,33 @@ class filter_manager { $filter->setup($page, $context); } } + + /** + * Setup the page for globally available filters. + * + * This helps setting up the page for filters which may be applied to + * the page, even if they do not belong to the current context, or are + * not yet visible because the content is lazily added (ajax). This method + * always uses to the system context which determines the globally + * available filters. + * + * This should only ever be called once per request. + * + * @param moodle_page $page The page. + * @since Moodle 3.2 + */ + public function setup_page_for_globally_available_filters($page) { + $context = context_system::instance(); + $filterdata = filter_get_globally_enabled_filters_with_config(); + foreach ($filterdata as $name => $config) { + if (isset($this->textfilters[$context->id][$name])) { + $filter = $this->textfilters[$context->id][$name]; + } else { + $filter = $this->make_filter_object($name, $context, $config); + } + $filter->setup($page, $context); + } + } } @@ -694,6 +721,46 @@ function filter_get_globally_enabled() { return $enabledfilters; } +/** + * Get the globally enabled filters. + * + * This returns the filters which could be used in any context. Essentially + * the filters which are not disabled for the entire site. + * + * @return array Keys are filter names, and values the config. + */ +function filter_get_globally_enabled_filters_with_config() { + global $DB; + + $sql = "SELECT f.filter, fc.name, fc.value + FROM {filter_active} f + LEFT JOIN {filter_config} fc + ON fc.filter = f.filter + AND fc.contextid = f.contextid + WHERE f.contextid = :contextid + AND f.active != :disabled + ORDER BY f.sortorder"; + + $rs = $DB->get_recordset_sql($sql, [ + 'contextid' => context_system::instance()->id, + 'disabled' => TEXTFILTER_DISABLED + ]); + + // Massage the data into the specified format to return. + $filters = array(); + foreach ($rs as $row) { + if (!isset($filters[$row->filter])) { + $filters[$row->filter] = array(); + } + if ($row->name !== null) { + $filters[$row->filter][$row->name] = $row->value; + } + } + $rs->close(); + + return $filters; +} + /** * Return the names of the filters that should also be applied to strings * (when they are enabled). diff --git a/lib/pagelib.php b/lib/pagelib.php index 6d34bccff0f..9e2c5d47824 100644 --- a/lib/pagelib.php +++ b/lib/pagelib.php @@ -1601,7 +1601,7 @@ class moodle_page { if (!during_initial_install()) { $filtermanager = filter_manager::instance(); - $filtermanager->setup_page_for_filters($this, $this->context); + $filtermanager->setup_page_for_globally_available_filters($this); } $this->_wherethemewasinitialised = debug_backtrace(); diff --git a/lib/tests/filterlib_test.php b/lib/tests/filterlib_test.php index e769e087eaf..b8af6ff2966 100644 --- a/lib/tests/filterlib_test.php +++ b/lib/tests/filterlib_test.php @@ -675,4 +675,37 @@ class core_filterlib_testcase extends advanced_testcase { $this->assertInstanceOf('filter_manager', $filterman); $this->assertInstanceOf('performance_measuring_filter_manager', $filterman); } + + public function test_filter_get_globally_enabled_filters_with_config() { + $this->setup_available_in_context_tests(); + + // Set few filters. + filter_set_global_state('one', TEXTFILTER_ON); + filter_set_global_state('three', TEXTFILTER_OFF, -1); + filter_set_global_state('two', TEXTFILTER_DISABLED); + + // Set global config. + filter_set_local_config('one', $this->syscontext->id, 'test1a', 'In root'); + filter_set_local_config('one', $this->syscontext->id, 'test1b', 'In root'); + filter_set_local_config('two', $this->syscontext->id, 'test2a', 'In root'); + filter_set_local_config('two', $this->syscontext->id, 'test2b', 'In root'); + + // Set child config. + filter_set_local_config('one', $this->childcontext->id, 'test1a', 'In child'); + filter_set_local_config('one', $this->childcontext->id, 'test1b', 'In child'); + filter_set_local_config('two', $this->childcontext->id, 'test2a', 'In child'); + filter_set_local_config('two', $this->childcontext->id, 'test2b', 'In child'); + filter_set_local_config('three', $this->childcontext->id, 'test3a', 'In child'); + filter_set_local_config('three', $this->childcontext->id, 'test3b', 'In child'); + + // Check. + $actual = filter_get_globally_enabled_filters_with_config(); + $this->assertCount(2, $actual); + $this->assertEquals(['three', 'one'], array_keys($actual)); // Checks sortorder. + $this->assertArrayHasKey('one', $actual); + $this->assertArrayNotHasKey('two', $actual); + $this->assertArrayHasKey('three', $actual); + $this->assertEquals(['test1a' => 'In root', 'test1b' => 'In root'], $actual['one']); + $this->assertEquals([], $actual['three']); + } } diff --git a/media/classes/player.php b/media/classes/player.php index cb05f1260ed..7171c05762f 100644 --- a/media/classes/player.php +++ b/media/classes/player.php @@ -246,6 +246,12 @@ abstract class core_media_player { /** * Setup page requirements. * + * The typical javascript requirements MUST not take action on the content + * directly. They are meant to load the required libraries and listen + * to events in order to know when to take action. The role of this method + * is not to provide a way for plugins to look for content to embed on the + * page. The {@link self::embed()} method is meant to be used for that. + * * @param moodle_page $page The page we are going to add requirements to. * @since Moodle 3.2 */