From 86fd9277c2b5dbf2bf9cedcc49cd7f772dc72d3a Mon Sep 17 00:00:00 2001 From: Juan Leyva Date: Wed, 27 Feb 2019 16:40:16 +0100 Subject: [PATCH] MDL-64656 core_tag: New WebService core_tag_get_tag_cloud --- lib/db/services.php | 7 +++ tag/classes/external.php | 103 ++++++++++++++++++++++++++++++++++++ tag/tests/external_test.php | 99 ++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) diff --git a/lib/db/services.php b/lib/db/services.php index 4edebbcbf90..7b2b093acf6 100644 --- a/lib/db/services.php +++ b/lib/db/services.php @@ -1535,6 +1535,13 @@ $functions = array( 'type' => 'read', 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), ), + 'core_tag_get_tag_cloud' => array( + 'classname' => 'core_tag_external', + 'methodname' => 'get_tag_cloud', + 'description' => 'Retrieves a tag cloud for the given collection and/or query search.', + 'type' => 'read', + 'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE), + ), 'core_update_inplace_editable' => array( 'classname' => 'core_external', 'methodname' => 'update_inplace_editable', diff --git a/tag/classes/external.php b/tag/classes/external.php index 40022a3eb72..6214f86ac02 100644 --- a/tag/classes/external.php +++ b/tag/classes/external.php @@ -579,4 +579,107 @@ class core_tag_external extends external_api { ) ); } + + /** + * Returns description of get_tag_cloud() parameters. + * + * @return external_function_parameters + * @since Moodle 3.7 + */ + public static function get_tag_cloud_parameters() { + return new external_function_parameters( + array( + 'tagcollid' => new external_value(PARAM_INT, 'Tag collection id.', VALUE_DEFAULT, 0), + 'isstandard' => new external_value(PARAM_BOOL, 'Whether to return only standard tags.', VALUE_DEFAULT, false), + 'limit' => new external_value(PARAM_INT, 'Maximum number of tags to retrieve.', VALUE_DEFAULT, 150), + 'sort' => new external_value(PARAM_ALPHA, 'Sort order for display + (id, name, rawname, count, flag, isstandard, tagcollid).', VALUE_DEFAULT, 'name'), + 'search' => new external_value(PARAM_RAW, 'Search string.', VALUE_DEFAULT, ''), + 'fromctx' => new external_value(PARAM_INT, 'Context id where this tag cloud is displayed.', VALUE_DEFAULT, 0), + 'ctx' => new external_value(PARAM_INT, 'Only retrieve tag instances in this context.', VALUE_DEFAULT, 0), + 'rec' => new external_value(PARAM_INT, 'Retrieve tag instances in the $ctx context and it\'s children.', + VALUE_DEFAULT, 1), + ) + ); + } + + /** + * Retrieves a tag cloud for display. + * + * @param int $tagcollid tag collection id + * @param bool $isstandard return only standard tags + * @param int $limit maximum number of tags to retrieve, tags are sorted by the instance count + * descending here regardless of $sort parameter + * @param string $sort sort order for display, default 'name' - tags will be sorted after they are retrieved + * @param string $search search string + * @param int $fromctx context id where this tag cloud is displayed + * @param int $ctx only retrieve tag instances in this context + * @param int $rec retrieve tag instances in the $ctx context and it's children (default 1) + * @return array an array of warnings and tag cloud information and items + * @throws moodle_exception + * @since Moodle 3.7 + */ + public static function get_tag_cloud($tagcollid = 0, $isstandard = false, $limit = 150, $sort = 'name', + $search = '', $fromctx = 0, $ctx = 0, $rec = 1) { + global $CFG, $PAGE; + + $params = self::validate_parameters(self::get_tag_cloud_parameters(), + array( + 'tagcollid' => $tagcollid, + 'isstandard' => $isstandard, + 'limit' => $limit, + 'sort' => $sort, + 'search' => $search, + 'fromctx' => $fromctx, + 'ctx' => $ctx, + 'rec' => $rec, + ) + ); + + if (empty($CFG->usetags)) { + throw new moodle_exception('tagsaredisabled', 'tag'); + } + + $context = context_system::instance(); + self::validate_context($context); + $PAGE->set_context($context); // Needed by internal APIs. + $output = $PAGE->get_renderer('core'); + + $tagcloud = core_tag_collection::get_tag_cloud($params['tagcollid'], $params['isstandard'], $params['limit'], + $params['sort'], $params['search'], $params['fromctx'], $params['ctx'], $params['rec']); + + $result = $tagcloud->export_for_template($output); + $result->warnings = array(); + + return (array) $result; + } + + /** + * Returns description of get_tag_cloud() result value. + * + * @return external_description + * @since Moodle 3.7 + */ + public static function get_tag_cloud_returns() { + return new external_single_structure( + array( + 'tags' => new external_multiple_structure( + new external_single_structure( + array( + 'name' => new external_value(PARAM_TAG, 'Tag name.'), + 'viewurl' => new external_value(PARAM_RAW, 'URL to view the tag index.'), + 'flag' => new external_value(PARAM_BOOL, 'Whether the tag is flagged as inappropriate.', + VALUE_OPTIONAL), + 'isstandard' => new external_value(PARAM_BOOL, 'Whether is a standard tag or not.', VALUE_OPTIONAL), + 'count' => new external_value(PARAM_INT, 'Number of tag instances.', VALUE_OPTIONAL), + 'size' => new external_value(PARAM_INT, 'Proportional size to display the tag.', VALUE_OPTIONAL), + ), 'Tags.' + ) + ), + 'tagscount' => new external_value(PARAM_INT, 'Number of tags returned.'), + 'totalcount' => new external_value(PARAM_INT, 'Total count of tags.'), + 'warnings' => new external_warnings(), + ) + ); + } } diff --git a/tag/tests/external_test.php b/tag/tests/external_test.php index 8f557597bde..b6813a70125 100644 --- a/tag/tests/external_test.php +++ b/tag/tests/external_test.php @@ -275,4 +275,103 @@ class core_tag_external_testcase extends externallib_advanced_testcase { $this->assertEquals($collections[$collection['id']]->name, $collection['name']); } } + + /** + * Test get_tag_cloud. + */ + public function test_get_tag_cloud() { + global $USER, $DB; + $this->resetAfterTest(true); + + // Create tags for two user profiles, a post and one course. + $this->setAdminUser(); + $context = context_user::instance($USER->id); + core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('Cats', 'Dogs')); + + $this->setUser($this->getDataGenerator()->create_user()); + $context = context_user::instance($USER->id); + core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('Mice')); + + $course = $this->getDataGenerator()->create_course(); + $coursecontext = context_course::instance($course->id); + core_tag_tag::set_item_tags('core', 'course', $course->id, $coursecontext, array('Cats')); + + $post = new stdClass(); + $post->userid = $USER->id; + $post->content = 'test post content text'; + $post->id = $DB->insert_record('post', $post); + $context = context_system::instance(); + core_tag_tag::set_item_tags('core', 'post', $post->id, $context, array('Horses', 'Cats')); + + // First, retrieve complete cloud. + $result = core_tag_external::get_tag_cloud(); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(4, $result['tags']); // Four different tags: Cats, Dogs, Mice, Horses. + $this->assertEquals(4, $result['tagscount']); + $this->assertEquals(4, $result['totalcount']); + + foreach ($result['tags'] as $tag) { + if ($tag['name'] == 'Cats') { + $this->assertEquals(3, $tag['count']); + } else { + $this->assertEquals(1, $tag['count']); + } + } + + // Test filter by collection, pagination and sorting. + $defaultcoll = core_tag_collection::get_default(); + $result = core_tag_external::get_tag_cloud($defaultcoll, false, 2, 'count'); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(2, $result['tags']); // Only two tags. + $this->assertEquals(2, $result['tagscount']); + $this->assertEquals(4, $result['totalcount']); + $this->assertEquals('Dogs', $result['tags'][0]['name']); // Lower count first. + + // Test search. + $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', 'Mice'); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(1, $result['tags']); // Only the searched tags. + $this->assertEquals(1, $result['tagscount']); + $this->assertEquals(1, $result['totalcount']); // When searching, the total is always for the search. + $this->assertEquals('Mice', $result['tags'][0]['name']); + + $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', 'Conejo'); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(0, $result['tags']); // Nothing found. + $this->assertEquals(0, $result['tagscount']); + $this->assertEquals(0, $result['totalcount']); // When searching, the total is always for the search. + + // Test standard filtering. + $micetag = core_tag_tag::get_by_name($defaultcoll, 'Mice', '*'); + $micetag->update(array('isstandard' => 1)); + + $result = core_tag_external::get_tag_cloud(0, true); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(1, $result['tags']); + $this->assertEquals(1, $result['tagscount']); + $this->assertEquals(1, $result['totalcount']); // When searching, the total is always for the search. + $this->assertEquals('Mice', $result['tags'][0]['name']); + + // Test course context filtering. + $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', '', 0, $coursecontext->id); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(1, $result['tags']); + $this->assertEquals(1, $result['tagscount']); + $this->assertEquals(1, $result['totalcount']); // When searching, the total is always for the search. + $this->assertEquals('Cats', $result['tags'][0]['name']); + + // Complete system context. + $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', '', 0, context_system::instance()->id); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(4, $result['tags']); + $this->assertEquals(4, $result['tagscount']); + + // Just system context - avoid children. + $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', '', 0, context_system::instance()->id, 0); + $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); + $this->assertCount(2, $result['tags']); + $this->assertEquals(2, $result['tagscount']); // Horses and Cats. + $this->assertEquals('Cats', $result['tags'][0]['name']); + $this->assertEquals('Horses', $result['tags'][1]['name']); + } } -- 2.43.0