From f94e1ef3c99c66e8b68290a377c39b44d40136c3 Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Wed, 19 Apr 2023 15:00:50 +0200 Subject: [PATCH] MDL-56020 search: Adapt code to new style and add tests --- lib/db/services.php | 9 +- search/classes/document.php | 37 +--- search/classes/external.php | 164 ---------------- search/classes/external/get_results.php | 189 +++++++++++++++++++ search/engine/simpledb/classes/engine.php | 2 +- search/tests/external/get_results_test.php | 115 +++++++++++ search/tests/external_test.php | 115 ----------- search/tests/fixtures/mock_search_engine.php | 2 +- version.php | 2 +- 9 files changed, 321 insertions(+), 314 deletions(-) create mode 100644 search/classes/external/get_results.php create mode 100644 search/tests/external/get_results_test.php diff --git a/lib/db/services.php b/lib/db/services.php index 2dc27ec0265..3971faca7ee 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1707,12 +1707,11 @@ $functions = array( 'ajax' => true ), 'core_search_get_results' => array( - 'classname' => 'core_search_external', - 'methodname' => 'get_results', - 'classpath' => 'search/classes/external.php', - 'description' => 'Search contents.', + 'classname' => '\core_search\external\get_results', + 'description' => 'Get search results.', 'type' => 'read', - 'capabilities' => 'moodle/search:query' + 'capabilities' => 'moodle/search:query', + 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], ), 'core_tag_get_tagindex' => array( 'classname' => 'core_tag_external', diff --git a/search/classes/document.php b/search/classes/document.php index 8a4723fa5f6..85e116f6872 100644 --- a/search/classes/document.php +++ b/search/classes/document.php @@ -392,18 +392,6 @@ class document implements \renderable, \templatable { return static::$requiredfields + static::$optionalfields + static::$enginefields; } - /** - * Returns whether a field is required or not. - * - * Considers engine fields to be optional. - * - * @param string $fieldname - * @return bool - */ - public static function field_is_required(string $fieldname): bool { - return (!empty(static::$requiredfields[$fieldname])); - } - /** * Formats the timestamp preparing the time fields to be inserted into the search engine. * @@ -618,10 +606,10 @@ class document implements \renderable, \templatable { * Just delegates all the processing to export_doc_info, also used by external functions. * Adding more info than the required one as people might be interested in extending the template. * - * @param renderer_base $output The renderer. + * @param \renderer_base $output The renderer. * @return array */ - public function export_for_template(\renderer_base $output) { + public function export_for_template(\renderer_base $output): array { $docdata = $this->export_doc($output); return $docdata; } @@ -637,10 +625,12 @@ class document implements \renderable, \templatable { * SECURITY NOTE: It is the responsibility of the document to properly escape any text to be displayed. * The renderer will output the content without any further cleaning. * + * @param \renderer_base $output The renderer. * @return array */ - public function export_doc(\renderer_base $output) { - global $USER; + public function export_doc(\renderer_base $output): array { + global $USER, $CFG; + require_once($CFG->dirroot . '/course/lib.php'); list($componentname, $areaname) = \core_search\manager::extract_areaid_parts($this->get('areaid')); $context = context::instance_by_id($this->get('contextid')); @@ -684,10 +674,10 @@ class document implements \renderable, \templatable { if ($this->get('userid') == $USER->id || (has_capability('moodle/user:viewdetails', $context) && has_capability('moodle/course:viewparticipants', $context))) { - $data['userurl'] = new \moodle_url( + $data['userurl'] = (new \moodle_url( '/user/view.php', ['id' => $this->get('userid'), 'course' => $this->get('courseid')] - ); + ))->out(false); $data['userfullname'] = format_string($this->get('userfullname'), true, ['context' => $context->id]); $data['userid'] = $this->get('userid'); } @@ -695,17 +685,10 @@ class document implements \renderable, \templatable { if ($docicon = $this->get_doc_icon()) { $data['icon'] = $output->image_url($docicon->get_name(), $docicon->get_component()); + $data['iconurl'] = $data['icon']->out(false); } + $data['textformat'] = $this->get_text_format(); - // We need to return the text formatting used for ws stuff. - $settings = \core_external\external_settings::get_instance(); - if ($settings->get_raw()) { - // If this is called by a ws client and requests raw text we return the format specified by the search engine. - $data['textformat'] = $this->get_text_format(); - } else { - // We convert texts to HTML by default. - $data['textformat'] = FORMAT_HTML; - } return $data; } diff --git a/search/classes/external.php b/search/classes/external.php index 5311c5ea831..6629f6069ca 100644 --- a/search/classes/external.php +++ b/search/classes/external.php @@ -120,168 +120,4 @@ class external extends \core_external\external_api { } return $result; } - - /** - * get_results parameters. - * - * @since Moodle 3.2 - * @return external_function_parameters - */ - public static function get_results_parameters() { - return new external_function_parameters( - array( - 'q' => new external_value(PARAM_NOTAGS, 'the search query'), - 'filters' => new external_single_structure( - array( - 'title' => new external_value(PARAM_NOTAGS, 'result title', VALUE_OPTIONAL), - 'areaids' => new external_multiple_structure( - new external_value(PARAM_RAW, 'areaid'), 'restrict results to these areas', VALUE_DEFAULT, [] - ), - 'courseids' => new external_multiple_structure( - new external_value(PARAM_INT, 'courseid'), 'restrict results to these courses', VALUE_DEFAULT, [] - ), - 'contextids' => new external_multiple_structure( - new external_value(PARAM_INT, 'contextid'), 'restrict results to these context', VALUE_DEFAULT, [] - ), - 'userids' => new external_multiple_structure( - new external_value(PARAM_INT, 'userid'), 'restrict results to these users', VALUE_DEFAULT, [] - ), - 'groupids' => new external_multiple_structure( - new external_value(PARAM_INT, 'groupid'), 'restrict results to these groups', VALUE_DEFAULT, [] - ), - 'mycoursesonly' => new external_value(PARAM_BOOL, 'result title', VALUE_OPTIONAL), - 'order' => new external_value(PARAM_ALPHA, 'result title', VALUE_OPTIONAL), - 'timestart' => new external_value(PARAM_INT, 'result title', VALUE_DEFAULT, 0), - 'timeend' => new external_value(PARAM_INT, 'result title', VALUE_DEFAULT, 0) - ), 'filters to apply', VALUE_OPTIONAL - ), - 'page' => new external_value(PARAM_INT, 'results page number starting from 0, defaults to the first page', - VALUE_DEFAULT) - ) - ); - } - - - /* - * Gets global search results based on the provided query and filters. - * - * @param string $q - * @param array $filters - * @param int $page - * @return array - */ - public static function get_results($q, $filters = [], $page = 0) { - global $PAGE; - - $params = self::validate_parameters(self::get_results_parameters(), array( - 'q' => $q, - 'filters' => $filters, - 'page' => $page) - ); - - $system = \context_system::instance(); - \external_api::validate_context($system); - - require_capability('moodle/search:query', $system); - - if (\core_search\manager::is_global_search_enabled() === false) { - throw new \moodle_exception('globalsearchdisabled', 'search'); - } - - $search = \core_search\manager::instance(); - - $data = new \stdClass(); - $data->q = $params['q']; - - if (!empty($params['filters']['title'])) { - $data->title = $params['filters']['title']; - } - - if (!empty($params['filters']['areaids'])) { - $data->areaids = $params['filters']['areaids']; - } - - if (!empty($params['filters']['courseids'])) { - $data->courseids = $params['filters']['courseids']; - } - - if (!empty($params['filters']['contextids'])) { - $data->contextids = $params['filters']['contextids']; - } - - if (!empty($params['filters']['userids'])) { - $data->userids = $params['filters']['userids']; - } - - if (!empty($params['filters']['groupids'])) { - $data->groupids = $params['filters']['groupids']; - } - - if (!empty($params['filters']['timestart'])) { - $data->timestart = $params['filters']['timestart']; - } - if (!empty($params['filters']['timeend'])) { - $data->timeend = $params['filters']['timeend']; - } - - $docs = $search->paged_search($data, $page); - - $return = [ - 'totalcount' => $docs->totalcount, - 'warnings' => [], - 'results' => [] - ]; - - // Convert results to simple data structures. - if ($docs) { - foreach ($docs->results as $doc) { - $return['results'][] = $doc->export_doc($PAGE->get_renderer('core')); - } - } - return $return; - } - - /** - * Returns description of method get_results. - * - * @return external_single_structure - */ - public static function get_results_returns() { - - return new external_single_structure( - array( - 'totalcount' => new external_value(PARAM_INT, 'Total number of results'), - 'results' => new external_multiple_structure( - new external_single_structure( - array( - 'itemid' => new external_value(PARAM_INT, 'unique id in the search area scope'), - 'componentname' => new external_value(PARAM_ALPHANUMEXT, 'component name'), - 'areaname' => new external_value(PARAM_ALPHANUMEXT, 'search area name'), - 'courseurl' => new external_value(PARAM_URL, 'result course url'), - 'coursefullname' => new external_value(PARAM_RAW, 'result course fullname'), - 'timemodified' => new external_value(PARAM_INT, 'result modified time'), - 'title' => new external_value(PARAM_RAW, 'result title'), - 'docurl' => new external_value(PARAM_URL, 'result url'), - 'content' => new external_value(PARAM_RAW, 'result contents', VALUE_OPTIONAL), - 'contextid' => new external_value(PARAM_INT, 'result context id'), - 'contexturl' => new external_value(PARAM_URL, 'result context url'), - 'description1' => new external_value(PARAM_RAW, 'extra result contents, depends on the search area', VALUE_OPTIONAL), - 'description2' => new external_value(PARAM_RAW, 'extra result contents, depends on the search area', VALUE_OPTIONAL), - 'multiplefiles' => new external_value(PARAM_INT, 'whether multiple files are returned or not', VALUE_OPTIONAL), - 'filenames' => new external_multiple_structure( - new external_value(PARAM_RAW, 'result file name', VALUE_OPTIONAL) - , 'result file names if present', - VALUE_OPTIONAL - ), - 'filename' => new external_value(PARAM_RAW, 'result file name if present', VALUE_OPTIONAL), - 'userid' => new external_value(PARAM_INT, 'user id', VALUE_OPTIONAL), - 'userurl' => new external_value(PARAM_URL, 'user url', VALUE_OPTIONAL), - 'userfullname' => new external_value(PARAM_RAW, 'user fullname', VALUE_OPTIONAL), - 'textformat' => new external_value(PARAM_INT, 'text fields format, it is the same for all of them') - ), 'Search result' - ), 'Search results', VALUE_OPTIONAL - ) - ) - ); - } } diff --git a/search/classes/external/get_results.php b/search/classes/external/get_results.php new file mode 100644 index 00000000000..215a85d7209 --- /dev/null +++ b/search/classes/external/get_results.php @@ -0,0 +1,189 @@ +. + +namespace core_search\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 moodle_exception; + +/** + * External function for retrieving search results. + * + * @package core_search + * @copyright 2023 David Monllao & Juan Leyva + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @since Moodle 4.3 + */ +class get_results extends external_api { + + /** + * Webservice parameters. + * + * @return external_function_parameters + */ + public static function execute_parameters(): external_function_parameters { + return new external_function_parameters( + [ + 'query' => new external_value(PARAM_NOTAGS, 'the search query'), + 'filters' => new external_single_structure( + [ + 'title' => new external_value(PARAM_NOTAGS, 'result title', VALUE_OPTIONAL), + 'areaids' => new external_multiple_structure( + new external_value(PARAM_ALPHANUMEXT, 'areaid'), 'restrict results to these areas', VALUE_DEFAULT, [] + ), + 'courseids' => new external_multiple_structure( + new external_value(PARAM_INT, 'courseid'), 'restrict results to these courses', VALUE_DEFAULT, [] + ), + 'contextids' => new external_multiple_structure( + new external_value(PARAM_INT, 'contextid'), 'restrict results to these contexts', VALUE_DEFAULT, [] + ), + 'cat' => new external_value(PARAM_NOTAGS, 'category to filter areas', VALUE_DEFAULT, ''), + 'userids' => new external_multiple_structure( + new external_value(PARAM_INT, 'userid'), 'restrict results to these users', VALUE_DEFAULT, [] + ), + 'groupids' => new external_multiple_structure( + new external_value(PARAM_INT, 'groupid'), 'restrict results to these groups', VALUE_DEFAULT, [] + ), + 'mycoursesonly' => new external_value(PARAM_BOOL, 'only results from my courses', VALUE_DEFAULT, false), + 'order' => new external_value(PARAM_ALPHA, 'how to order', VALUE_DEFAULT, ''), + 'timestart' => new external_value(PARAM_INT, 'docs modified after this date', VALUE_DEFAULT, 0), + 'timeend' => new external_value(PARAM_INT, 'docs modified before this date', VALUE_DEFAULT, 0) + ], 'filters to apply', VALUE_DEFAULT, [] + ), + 'page' => new external_value(PARAM_INT, 'results page number starting from 0, defaults to the first page', + VALUE_DEFAULT, 0) + ] + ); + } + + /** + * Gets global search results based on the provided query and filters. + * + * @param string $query the search query + * @param array $filters filters to apply + * @param int $page results page + * @return array search results + */ + public static function execute(string $query, array $filters = [], int $page = 0): array { + global $PAGE; + + $params = self::validate_parameters(self::execute_parameters(), + [ + 'query' => $query, + 'filters' => $filters, + 'page' => $page, + ] + ); + + $system = \context_system::instance(); + external_api::validate_context($system); + + require_capability('moodle/search:query', $system); + + if (\core_search\manager::is_global_search_enabled() === false) { + throw new moodle_exception('globalsearchdisabled', 'search'); + } + + $search = \core_search\manager::instance(); + + $data = new \stdClass(); + // First, mandatory parameters for consistency with web. + $data->q = $params['query']; + $data->title = $params['filters']['title'] ?? ''; + $data->timestart = $params['filters']['timestart'] ?? 0; + $data->timeend = $params['filters']['timeend'] ?? 0; + $data->areaids = $params['filters']['areaids'] ?? []; + $data->courseids = $params['filters']['courseids'] ?? []; + $data->contextids = $params['filters']['contextids'] ?? []; + $data->userids = $params['filters']['userids'] ?? []; + $data->groupids = $params['filters']['groupids'] ?? []; + + $cat = $params['filters']['cat'] ?? ''; + if (\core_search\manager::is_search_area_categories_enabled()) { + $cat = \core_search\manager::get_search_area_category_by_name($cat); + } + if ($cat instanceof \core_search\area_category) { + $data->cat = $cat->get_name(); + } + + $docs = $search->paged_search($data, $page); + + $return = [ + 'totalcount' => $docs->totalcount, + 'warnings' => [], + 'results' => [] + ]; + + // Convert results to simple data structures. + if ($docs) { + foreach ($docs->results as $doc) { + $return['results'][] = $doc->export_doc($PAGE->get_renderer('core')); + } + } + return $return; + } + + /** + * Webservice returns. + * + * @return external_single_structure + */ + public static function execute_returns(): external_single_structure { + return new external_single_structure( + [ + 'totalcount' => new external_value(PARAM_INT, 'Total number of results'), + 'results' => new external_multiple_structure( + new external_single_structure( + [ + 'itemid' => new external_value(PARAM_INT, 'unique id in the search area scope'), + 'componentname' => new external_value(PARAM_ALPHANUMEXT, 'component name'), + 'areaname' => new external_value(PARAM_ALPHANUMEXT, 'search area name'), + 'courseurl' => new external_value(PARAM_URL, 'result course url'), + 'coursefullname' => new external_value(PARAM_RAW, 'result course fullname'), + 'timemodified' => new external_value(PARAM_INT, 'result modified time'), + 'title' => new external_value(PARAM_RAW, 'result title'), + 'docurl' => new external_value(PARAM_URL, 'result url'), + 'iconurl' => new external_value(PARAM_URL, 'icon url', VALUE_OPTIONAL), + 'content' => new external_value(PARAM_RAW, 'result contents', VALUE_OPTIONAL), + 'contextid' => new external_value(PARAM_INT, 'result context id'), + 'contexturl' => new external_value(PARAM_URL, 'result context url'), + 'description1' => new external_value(PARAM_RAW, 'extra result contents, depends on the search area', + VALUE_OPTIONAL), + 'description2' => new external_value(PARAM_RAW, 'extra result contents, depends on the search area', + VALUE_OPTIONAL), + 'multiplefiles' => new external_value(PARAM_INT, 'whether multiple files are returned or not', + VALUE_OPTIONAL), + 'filenames' => new external_multiple_structure( + new external_value(PARAM_RAW, 'result file name', VALUE_OPTIONAL) + , 'result file names if present', + VALUE_OPTIONAL + ), + 'filename' => new external_value(PARAM_RAW, 'result file name if present', VALUE_OPTIONAL), + 'userid' => new external_value(PARAM_INT, 'user id', VALUE_OPTIONAL), + 'userurl' => new external_value(PARAM_URL, 'user url', VALUE_OPTIONAL), + 'userfullname' => new external_value(PARAM_RAW, 'user fullname', VALUE_OPTIONAL), + 'textformat' => new external_value(PARAM_INT, 'text fields format, it is the same for all of them') + ], 'Search result' + ), 'Search results', VALUE_OPTIONAL + ) + ] + ); + } +} diff --git a/search/engine/simpledb/classes/engine.php b/search/engine/simpledb/classes/engine.php index 2531c613581..ff39920ad63 100644 --- a/search/engine/simpledb/classes/engine.php +++ b/search/engine/simpledb/classes/engine.php @@ -323,7 +323,7 @@ class engine extends \core_search\engine { * @return int */ public function get_query_total_count() { - if (!is_null($this->totalresults)) { + if (is_null($this->totalresults)) { // This is a just in case as we count total results in execute_query. return \core_search\manager::MAX_RESULTS; } diff --git a/search/tests/external/get_results_test.php b/search/tests/external/get_results_test.php new file mode 100644 index 00000000000..414c212e359 --- /dev/null +++ b/search/tests/external/get_results_test.php @@ -0,0 +1,115 @@ +. + +namespace core_search\external; + +use core_external\external_api; + +defined('MOODLE_INTERNAL') || die(); + +global $CFG; +require_once($CFG->dirroot . '/webservice/tests/helpers.php'); + +/** + * Tests for the get_results external function. + * + * @package core_search + * @category test + * @copyright 2023 Juan Leyva (juan@moodle.com) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @coversDefaultClass \core_search\external\get_results + */ +class get_results_test extends \externallib_advanced_testcase { + + public function setUp(): void { + $this->resetAfterTest(); + } + + /** + * test external api + * @covers ::execute + * @return void + */ + public function test_external_get_results(): void { + + set_config('enableglobalsearch', true); + set_config('searchengine', 'simpledb'); + + $this->setAdminUser(); + + // Test search not returning anything (nothing in the index yet). + $return = external_api::clean_returnvalue(get_results::execute_returns(), get_results::execute('one')); + $this->assertEquals(0, $return['totalcount']); + + // Create an index of searchable things. + $generator = $this->getDataGenerator(); + $course = $generator->create_course(['fullname' => 'SearchTest course']); + $anothercourse = $generator->create_course(['fullname' => 'Another']); + $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); + $studentothercourse = $this->getDataGenerator()->create_and_enrol($anothercourse, 'student'); + $page = $generator->create_module('page', ['course' => $course->id, 'name' => 'SearchTest page']); + $forum = $generator->create_module('forum', ['course' => $course->id]); + + $fgenerator = $generator->get_plugin_generator('mod_forum'); + + for ($i = 0; $i < 15; $i++) { + $fgenerator->create_discussion( + [ + 'course' => $course->id, + 'forum' => $forum->id, + 'userid' => $student->id, + ] + ); + } + + $search = \core_search\manager::instance(); + $search->index(); + + // Basic search, by text. + $return = external_api::clean_returnvalue(get_results::execute_returns(), get_results::execute('page')); + $this->assertEquals(1, $return['totalcount']); + $this->assertEquals('activity', $return['results'][0]['areaname']); + $this->assertEquals($page->name, $return['results'][0]['title']); + + // Basic search, by name containing text. + $return = external_api::clean_returnvalue(get_results::execute_returns(), get_results::execute('SearchTest')); + $this->assertEquals(2, $return['totalcount']); + + // Test pagination. + $return = external_api::clean_returnvalue(get_results::execute_returns(), get_results::execute('discussion', [], 0)); + $this->assertCount(10, $return['results']); // The first 10 posts of a total of 15 for the second page. + $this->assertEquals(15, $return['totalcount']); + + $return = external_api::clean_returnvalue(get_results::execute_returns(), get_results::execute('discussion', [], 1)); + $this->assertCount(5, $return['results']); // The last 5 posts of a total of 15 for the second page. + $this->assertEquals(15, $return['totalcount']); + + // Test some filters. + $return = external_api::clean_returnvalue(get_results::execute_returns(), + get_results::execute('discussion', ['title' => 'Discussion 11'])); + $this->assertEquals(1, $return['totalcount']); + + // No discussions created in the future. + $return = external_api::clean_returnvalue(get_results::execute_returns(), + get_results::execute('discussion', ['timestart' => time() + DAYSECS])); + $this->assertEquals(0, $return['totalcount']); + + // Basic permissions check. + $this->setUser($studentothercourse); + $return = external_api::clean_returnvalue(get_results::execute_returns(), get_results::execute('discussion', [], 1)); + $this->assertCount(0, $return['results']); // I should not see other courses discussions. + } +} diff --git a/search/tests/external_test.php b/search/tests/external_test.php index 4cad01d78ad..10ab44c9ec6 100644 --- a/search/tests/external_test.php +++ b/search/tests/external_test.php @@ -75,119 +75,4 @@ class external_test extends \advanced_testcase { // Note: We are not checking search permissions, search by different fields, etc. as these // are covered by the core_user::search unit test. } - - /** - * test external api - * - * @return void - */ - public function test_external_get_results() { - global $USER, $DB, $CFG; - - require_once($CFG->dirroot . '/lib/externallib.php'); - - set_config('enableglobalsearch', true); - set_config('searchengine', 'simpledb'); - - $course = $this->getDataGenerator()->create_course(); - - $this->setAdminUser(); - - // Filters with defaults. - $filters = array( - 'title' => null, - 'areaids' => array(), - 'courseids' => array(), - 'timestart' => 0, - 'timeend' => 0 - ); - - // We need to execute the return values cleaning process to simulate the web service server. - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('one', $filters)); - $this->assertEquals(0, $return['totalcount']); - - $search = \core_search\manager::instance(); - $search->index(); - - - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results($course->shortname)); - - print_r($return); - - $this->assertEquals(0, $return['totalcount']); - - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(2, $return['totalcount']); - $this->assertEquals($USER->id, $return['results'][0]['userid']); - $this->assertEquals(\context_system::instance()->id, $return['results'][0]['contextid']); - - sleep(1); - $beforeadding = time(); - sleep(1); - $this->generator->create_record(); - $this->search->index(); - - // Timestart. - $filters['timestart'] = $beforeadding; - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(1, $return['totalcount']); - - // Timeend. - $filters['timestart'] = 0; - $filters['timeend'] = $beforeadding; - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(2, $return['totalcount']); - - // Title. - $filters['timeend'] = 0; - $filters['title'] = 'Special title'; - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(1, $return['totalcount']); - - // Course IDs. - $filters['title'] = null; - $filters['courseids'] = array(SITEID + 1); - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(0, $return['totalcount']); - - $filters['courseids'] = array(SITEID); - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(3, $return['totalcount']); - - // Reset filters once again. - $filters['courseids'] = array(); - - // Now try some area-id combinations. - $forumpostareaid = \core_search\manager::generate_areaid('mod_forum', 'post'); - $mockareaid = \core_search\manager::generate_areaid('core_mocksearch', 'mock_search_area'); - - $filters['areaids'] = array($forumpostareaid); - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(0, $return['totalcount']); - - $filters['areaids'] = array($forumpostareaid, $mockareaid); - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(3, $return['totalcount']); - - $filters['areaids'] = array($mockareaid); - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(3, $return['totalcount']); - - // All records now. - $filters['areaids'] = array(); - $return = \external_api::clean_returnvalue(\core_search\external::get_results_returns(), - \core_search\external::get_results('message', $filters)); - $this->assertEquals(3, $return['totalcount']); - } } diff --git a/search/tests/fixtures/mock_search_engine.php b/search/tests/fixtures/mock_search_engine.php index f19d2447548..0b8b3e12ffc 100644 --- a/search/tests/fixtures/mock_search_engine.php +++ b/search/tests/fixtures/mock_search_engine.php @@ -61,7 +61,7 @@ class engine extends \core_search\engine { public function execute_query($data, $usercontexts, $limit = 0) { // No need to implement. - return array(); + return []; } public function delete($areaid = null) { diff --git a/version.php b/version.php index 23257d6c911..0ca461b88e7 100644 --- a/version.php +++ b/version.php @@ -29,7 +29,7 @@ defined('MOODLE_INTERNAL') || die(); -$version = 2023082600.00; // YYYYMMDD = weekly release date of this DEV branch. +$version = 2023082600.01; // YYYYMMDD = weekly release date of this DEV branch. // RR = release increments - 00 in DEV branches. // .XX = incremental changes. $release = '4.3dev+ (Build: 20230826)'; // Human-friendly version name