From f693e84ff5da8f96d74295f298a369533d2a8741 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Tue, 27 Feb 2024 12:57:04 +0100 Subject: [PATCH] MDL-81065 core_filters: New WS core_filters_get_all_states --- filter/classes/external/get_all_states.php | 108 +++++++++++++++++++++ filter/tests/external/external_test.php | 53 ++++++++++ lib/db/services.php | 7 ++ lib/filterlib.php | 10 ++ 4 files changed, 178 insertions(+) create mode 100644 filter/classes/external/get_all_states.php diff --git a/filter/classes/external/get_all_states.php b/filter/classes/external/get_all_states.php new file mode 100644 index 00000000000..97116b0910b --- /dev/null +++ b/filter/classes/external/get_all_states.php @@ -0,0 +1,108 @@ +. + +namespace core_filters\external; + +use core_external\external_api; +use core_external\external_function_parameters; +use core_external\external_single_structure; +use core_external\external_multiple_structure; +use core_external\external_value; +use core_external\external_warnings; +use context; + +/** + * External function for getting all filter states. + * + * @package core_filters + * @copyright 2024 Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 4.4 + */ +class get_all_states extends external_api { + + /** + * Webservice parameters. + * + * @return external_function_parameters + */ + public static function execute_parameters(): external_function_parameters { + return new external_function_parameters([]); + } + + + /** + * Main method of the external function. + * + * @return array containing all filter states. + */ + public static function execute(): array { + global $CFG; + require_once($CFG->libdir . '/filterlib.php'); + + $system = \context_system::instance(); + external_api::validate_context($system); + + $filterstates = $warnings = []; + $states = filter_get_all_states(); + + foreach ($states as $state) { + $context = context::instance_by_id($state->contextid); + $classname = \core\context_helper::parse_external_level($context->contextlevel); + + $filterstates[] = [ + 'contextlevel' => $classname::get_short_name(), + 'instanceid' => $context->instanceid, + 'contextid' => $state->contextid, + 'filter' => $state->filter, + 'state' => $state->active, + 'sortorder' => $state->sortorder, + ]; + } + + return [ + 'filters' => $filterstates, + 'warnings' => $warnings, + ]; + } + + /** + * Webservice returns. + * + * @return external_single_structure + */ + public static function execute_returns(): external_single_structure { + return new external_single_structure( + [ + 'filters' => new external_multiple_structure( + new external_single_structure( + [ + 'contextlevel' => new external_value(PARAM_ALPHA, 'The context level where the filters are: + (coursecat, course, module).'), + 'instanceid' => new external_value(PARAM_INT, 'The instance id of item associated with the context.'), + 'contextid' => new external_value(PARAM_INT, 'The context id.'), + 'filter' => new external_value(PARAM_PLUGIN, 'Filter plugin name.'), + 'state' => new external_value(PARAM_INT, 'Filter state: 1 for on, -1 for off, -9999 if disabled.'), + 'sortorder' => new external_value(PARAM_INT, 'Execution order.'), + ] + ), + 'All filters states' + ), + 'warnings' => new external_warnings(), + ] + ); + } +} diff --git a/filter/tests/external/external_test.php b/filter/tests/external/external_test.php index 6ce13059e39..8d68c54acc5 100644 --- a/filter/tests/external/external_test.php +++ b/filter/tests/external/external_test.php @@ -202,4 +202,57 @@ class external_test extends externallib_advanced_testcase { $this->assertEquals('context', $result['warnings'][0]['item']); $this->assertEquals($forum->cmid, $result['warnings'][0]['itemid']); } + + /** + * Test get_all_states + * @covers \core_filters\external\get_all_states::execute + */ + public function test_get_all_states() { + $this->resetAfterTest(true); + $this->setAdminUser(); + + // Get all filters and disable them all globally except for the first. + $allfilters = filter_get_all_installed(); + reset($allfilters); + $firstfilter = key($allfilters); + foreach ($allfilters as $filter => $filterdata) { + if ($filter == $firstfilter) { + filter_set_global_state($filter, TEXTFILTER_ON); + continue; + } + filter_set_global_state($filter, TEXTFILTER_DISABLED); + } + + // Set some filters at particular levels. + $course = self::getDataGenerator()->create_course(); + filter_set_local_state($firstfilter, \context_course::instance($course->id)->id, TEXTFILTER_ON); + $forum = self::getDataGenerator()->create_module('forum', (object) ['course' => $course->id]); + filter_set_local_state($firstfilter, \context_module::instance($forum->cmid)->id, TEXTFILTER_OFF); + + $result = get_all_states::execute(); + $result = external_api::clean_returnvalue(get_all_states::execute_returns(), $result); + + $totalcount = count($allfilters) + 2; // All filters plus two local states. + $this->assertCount($totalcount, $result['filters']); + + $customfound = 0; + foreach ($result['filters'] as $filter) { + if ($filter['contextlevel'] == 'course' && $filter['instanceid'] == $course->id) { + $this->assertEquals($firstfilter, $filter['filter']); + $this->assertEquals(TEXTFILTER_ON, $filter['state']); + $customfound++; + } else if ($filter['contextlevel'] == 'module' && $filter['instanceid'] == $forum->cmid) { + $this->assertEquals($firstfilter, $filter['filter']); + $this->assertEquals(TEXTFILTER_OFF, $filter['state']); + $customfound++; + } else if ($filter['filter'] == $firstfilter) { + $this->assertEquals($firstfilter, $filter['filter']); + $this->assertEquals(TEXTFILTER_ON, $filter['state']); + $this->assertEquals(1, $filter['sortorder']); + } else { + $this->assertEquals(TEXTFILTER_DISABLED, $filter['state']); + } + } + $this->assertEquals(2, $customfound); // Both custom states found. + } } diff --git a/lib/db/services.php b/lib/db/services.php index a86c651d1f7..0d33aeb63e3 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -2787,6 +2787,13 @@ $functions = array( 'type' => 'read', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), ), + 'core_filters_get_all_states' => [ + 'classname' => 'core_filters\external\get_all_states', + 'description' => 'Retrieve all the filters and their states (including overridden ones in any context).', + 'type' => 'read', + 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], + ], + 'core_customfield_delete_field' => array( 'classname' => 'core_customfield_external', 'methodname' => 'delete_field', diff --git a/lib/filterlib.php b/lib/filterlib.php index 66cf3d15972..3277ff836fd 100644 --- a/lib/filterlib.php +++ b/lib/filterlib.php @@ -1316,6 +1316,16 @@ function filter_get_global_states() { return $DB->get_records('filter_active', array('contextid' => $context->id), 'sortorder', 'filter,active,sortorder'); } +/** + * Retrieve all the filters and their states (including overridden ones in any context). + * + * @return array filters objects containing filter name, context, active state and sort order. + */ +function filter_get_all_states(): array { + global $DB; + return $DB->get_records('filter_active'); +} + /** * Delete all the data in the database relating to a filter, prior to deleting it. *