See Release Notes
Long Term Support Release
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for WS in tags 19 * 20 * @package core_tag 21 * @category test 22 * @copyright 2015 Marina Glancy 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 30 require_once($CFG->libdir . '/externallib.php'); 31 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 32 33 class core_tag_external_testcase extends externallib_advanced_testcase { 34 /** 35 * Test update_categories 36 */ 37 public function test_update_tags() { 38 global $DB; 39 $this->resetAfterTest(); 40 $context = context_system::instance(); 41 42 $originaltag = array( 43 'isstandard' => 0, 44 'flag' => 1, 45 'rawname' => 'test', 46 'description' => 'desc' 47 ); 48 $tag = $this->getDataGenerator()->create_tag($originaltag); 49 50 $updatetag = array( 51 'id' => $tag->id, 52 'description' => 'Trying to change tag description', 53 'rawname' => 'Trying to change tag name', 54 'flag' => 0, 55 'isstandard' => 1, 56 ); 57 $gettag = array( 58 'id' => $tag->id, 59 ); 60 61 // User without any caps can not change anything about a tag but can request [partial] tag data. 62 $this->setUser($this->getDataGenerator()->create_user()); 63 $result = core_tag_external::update_tags(array($updatetag)); 64 $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result); 65 $this->assertEquals($tag->id, $result['warnings'][0]['item']); 66 $this->assertEquals('nothingtoupdate', $result['warnings'][0]['warningcode']); 67 $this->assertEquals($originaltag['rawname'], $DB->get_field('tag', 'rawname', 68 array('id' => $tag->id))); 69 $this->assertEquals($originaltag['description'], $DB->get_field('tag', 'description', 70 array('id' => $tag->id))); 71 72 $result = core_tag_external::get_tags(array($gettag)); 73 $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result); 74 $this->assertEquals($originaltag['rawname'], $result['tags'][0]['rawname']); 75 $this->assertEquals($originaltag['description'], $result['tags'][0]['description']); 76 $this->assertNotEmpty($result['tags'][0]['viewurl']); 77 $this->assertArrayNotHasKey('changetypeurl', $result['tags'][0]); 78 $this->assertArrayNotHasKey('changeflagurl', $result['tags'][0]); 79 $this->assertArrayNotHasKey('flag', $result['tags'][0]); 80 $this->assertArrayNotHasKey('official', $result['tags'][0]); 81 $this->assertArrayNotHasKey('isstandard', $result['tags'][0]); 82 83 // User with editing only capability can change description but not the tag name. 84 $roleid = $this->assignUserCapability('moodle/tag:edit', $context->id); 85 $result = core_tag_external::update_tags(array($updatetag)); 86 $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result); 87 $this->assertEmpty($result['warnings']); 88 89 $result = core_tag_external::get_tags(array($gettag)); 90 $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result); 91 $this->assertEquals($updatetag['id'], $result['tags'][0]['id']); 92 $this->assertEquals($updatetag['description'], $result['tags'][0]['description']); 93 $this->assertEquals($originaltag['rawname'], $result['tags'][0]['rawname']); 94 $this->assertArrayNotHasKey('flag', $result['tags'][0]); // 'Flag' is not available unless 'moodle/tag:manage' cap exists. 95 $this->assertEquals(0, $result['tags'][0]['official']); 96 $this->assertEquals(0, $result['tags'][0]['isstandard']); 97 $this->assertEquals($originaltag['rawname'], $DB->get_field('tag', 'rawname', 98 array('id' => $tag->id))); 99 $this->assertEquals($updatetag['description'], $DB->get_field('tag', 'description', 100 array('id' => $tag->id))); 101 102 // User with editing and manage cap can also change the tag name, 103 // make it standard and reset flag. 104 assign_capability('moodle/tag:manage', CAP_ALLOW, $roleid, $context->id); 105 $this->assertTrue(has_capability('moodle/tag:manage', $context)); 106 $result = core_tag_external::update_tags(array($updatetag)); 107 $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result); 108 $this->assertEmpty($result['warnings']); 109 110 $result = core_tag_external::get_tags(array($gettag)); 111 $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result); 112 $this->assertEquals($updatetag['id'], $result['tags'][0]['id']); 113 $this->assertEquals($updatetag['rawname'], $result['tags'][0]['rawname']); 114 $this->assertEquals(core_text::strtolower($updatetag['rawname']), $result['tags'][0]['name']); 115 $this->assertEquals($updatetag['flag'], $result['tags'][0]['flag']); 116 $this->assertEquals($updatetag['isstandard'], $result['tags'][0]['official']); 117 $this->assertEquals($updatetag['isstandard'], $result['tags'][0]['isstandard']); 118 $this->assertEquals($updatetag['rawname'], $DB->get_field('tag', 'rawname', 119 array('id' => $tag->id))); 120 $this->assertEquals(1, $DB->get_field('tag', 'isstandard', array('id' => $tag->id))); 121 122 // Updating and getting non-existing tag. 123 $nonexistingtag = array( 124 'id' => 123, 125 'description' => 'test' 126 ); 127 $getnonexistingtag = array( 128 'id' => 123, 129 ); 130 $result = core_tag_external::update_tags(array($nonexistingtag)); 131 $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result); 132 $this->assertEquals(123, $result['warnings'][0]['item']); 133 $this->assertEquals('tagnotfound', $result['warnings'][0]['warningcode']); 134 135 $result = core_tag_external::get_tags(array($getnonexistingtag)); 136 $result = external_api::clean_returnvalue(core_tag_external::get_tags_returns(), $result); 137 $this->assertEmpty($result['tags']); 138 $this->assertEquals(123, $result['warnings'][0]['item']); 139 $this->assertEquals('tagnotfound', $result['warnings'][0]['warningcode']); 140 141 // Attempt to update a tag to the name that is reserved. 142 $anothertag = $this->getDataGenerator()->create_tag(array('rawname' => 'Mytag')); 143 $updatetag2 = array('id' => $tag->id, 'rawname' => 'MYTAG'); 144 $result = core_tag_external::update_tags(array($updatetag2)); 145 $result = external_api::clean_returnvalue(core_tag_external::update_tags_returns(), $result); 146 $this->assertEquals($tag->id, $result['warnings'][0]['item']); 147 $this->assertEquals('namesalreadybeeingused', $result['warnings'][0]['warningcode']); 148 } 149 150 /** 151 * Test update_inplace_editable() 152 */ 153 public function test_update_inplace_editable() { 154 global $CFG, $DB, $PAGE; 155 require_once($CFG->dirroot . '/lib/external/externallib.php'); 156 157 $this->resetAfterTest(true); 158 $tag = $this->getDataGenerator()->create_tag(); 159 $this->setUser($this->getDataGenerator()->create_user()); 160 161 // Call service for core_tag component without necessary permissions. 162 try { 163 core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'new tag name'); 164 $this->fail('Exception expected'); 165 } catch (moodle_exception $e) { 166 $this->assertEquals('Sorry, but you do not currently have permissions to do that (Manage all tags).', 167 $e->getMessage()); 168 } 169 170 // Change to admin user and make sure that tag name can be updated using web service update_inplace_editable(). 171 $this->setAdminUser(); 172 $res = core_external::update_inplace_editable('core_tag', 'tagname', $tag->id, 'New tag name'); 173 $res = external_api::clean_returnvalue(core_external::update_inplace_editable_returns(), $res); 174 $this->assertEquals('New tag name', $res['value']); 175 $this->assertEquals('New tag name', $DB->get_field('tag', 'rawname', array('id' => $tag->id))); 176 177 // Call callback core_tag_inplace_editable() directly. 178 $tmpl = component_callback('core_tag', 'inplace_editable', array('tagname', $tag->id, 'Rename me again')); 179 $this->assertInstanceOf('core\output\inplace_editable', $tmpl); 180 $res = $tmpl->export_for_template($PAGE->get_renderer('core')); 181 $this->assertEquals('Rename me again', $res['value']); 182 $this->assertEquals('Rename me again', $DB->get_field('tag', 'rawname', array('id' => $tag->id))); 183 } 184 185 /** 186 * Test get_tagindex_per_area. 187 */ 188 public function test_get_tagindex_per_area() { 189 global $USER; 190 $this->resetAfterTest(true); 191 192 // Create tags for two user profiles and one course. 193 $this->setAdminUser(); 194 $context = context_user::instance($USER->id); 195 core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('test')); 196 197 $this->setUser($this->getDataGenerator()->create_user()); 198 $context = context_user::instance($USER->id); 199 core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('test')); 200 201 $course = $this->getDataGenerator()->create_course(); 202 $context = context_course::instance($course->id); 203 core_tag_tag::set_item_tags('core', 'course', $course->id, $context, array('test')); 204 205 $tag = core_tag_tag::get_by_name(0, 'test'); 206 207 // First, search by id. 208 $result = core_tag_external::get_tagindex_per_area(array('id' => $tag->id)); 209 $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result); 210 $this->assertCount(2, $result); // Two different areas: course and user. 211 $this->assertEquals($tag->id, $result[0]['tagid']); 212 $this->assertEquals('course', $result[0]['itemtype']); 213 $this->assertEquals($tag->id, $result[1]['tagid']); 214 $this->assertEquals('user', $result[1]['itemtype']); 215 216 // Now, search by name. 217 $result = core_tag_external::get_tagindex_per_area(array('tag' => 'test')); 218 $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result); 219 $this->assertCount(2, $result); // Two different areas: course and user. 220 $this->assertEquals($tag->id, $result[0]['tagid']); 221 $this->assertEquals('course', $result[0]['itemtype']); 222 $this->assertEquals($tag->id, $result[1]['tagid']); 223 $this->assertEquals('user', $result[1]['itemtype']); 224 225 // Filter by tag area. 226 $result = core_tag_external::get_tagindex_per_area(array('tag' => 'test', 'ta' => $result[0]['ta'])); 227 $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result); 228 $this->assertCount(1, $result); // Just the given area. 229 $this->assertEquals($tag->id, $result[0]['tagid']); 230 $this->assertEquals('course', $result[0]['itemtype']); 231 232 // Now, search by tag collection (use default). 233 $result = core_tag_external::get_tagindex_per_area(array('id' => $tag->id, 'tc' => 1)); 234 $result = external_api::clean_returnvalue(core_tag_external::get_tagindex_per_area_returns(), $result); 235 $this->assertCount(2, $result); // Two different areas: course and user. 236 } 237 238 /** 239 * Test get_tag_areas. 240 */ 241 public function test_get_tag_areas() { 242 global $DB; 243 $this->resetAfterTest(true); 244 245 $this->setAdminUser(); 246 $result = core_tag_external::get_tag_areas(); 247 $result = external_api::clean_returnvalue(core_tag_external::get_tag_areas_returns(), $result); 248 $areas = $DB->get_records('tag_area'); 249 $this->assertCount(count($areas), $result['areas']); 250 foreach ($result['areas'] as $area) { 251 $this->assertEquals($areas[$area['id']]->component, $area['component']); 252 $this->assertEquals($areas[$area['id']]->itemtype, $area['itemtype']); 253 } 254 } 255 256 /** 257 * Test get_tag_collections. 258 */ 259 public function test_get_tag_collections() { 260 global $DB; 261 $this->resetAfterTest(true); 262 263 // Create new tag collection. 264 $data = (object) array('name' => 'new tag coll'); 265 core_tag_collection::create($data); 266 267 $this->setAdminUser(); 268 $result = core_tag_external::get_tag_collections(); 269 $result = external_api::clean_returnvalue(core_tag_external::get_tag_collections_returns(), $result); 270 271 $collections = $DB->get_records('tag_coll'); 272 $this->assertCount(count($collections), $result['collections']); 273 foreach ($result['collections'] as $collection) { 274 $this->assertEquals($collections[$collection['id']]->component, $collection['component']); 275 $this->assertEquals($collections[$collection['id']]->name, $collection['name']); 276 } 277 } 278 279 /** 280 * Test get_tag_cloud. 281 */ 282 public function test_get_tag_cloud() { 283 global $USER, $DB; 284 $this->resetAfterTest(true); 285 286 // Create tags for two user profiles, a post and one course. 287 $this->setAdminUser(); 288 $context = context_user::instance($USER->id); 289 core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('Cats', 'Dogs')); 290 291 $this->setUser($this->getDataGenerator()->create_user()); 292 $context = context_user::instance($USER->id); 293 core_tag_tag::set_item_tags('core', 'user', $USER->id, $context, array('Mice')); 294 295 $course = $this->getDataGenerator()->create_course(); 296 $coursecontext = context_course::instance($course->id); 297 core_tag_tag::set_item_tags('core', 'course', $course->id, $coursecontext, array('Cats')); 298 299 $post = new stdClass(); 300 $post->userid = $USER->id; 301 $post->content = 'test post content text'; 302 $post->id = $DB->insert_record('post', $post); 303 $context = context_system::instance(); 304 core_tag_tag::set_item_tags('core', 'post', $post->id, $context, array('Horses', 'Cats')); 305 306 // First, retrieve complete cloud. 307 $result = core_tag_external::get_tag_cloud(); 308 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 309 $this->assertCount(4, $result['tags']); // Four different tags: Cats, Dogs, Mice, Horses. 310 $this->assertEquals(4, $result['tagscount']); 311 $this->assertEquals(4, $result['totalcount']); 312 313 foreach ($result['tags'] as $tag) { 314 if ($tag['name'] == 'Cats') { 315 $this->assertEquals(3, $tag['count']); 316 } else { 317 $this->assertEquals(1, $tag['count']); 318 } 319 } 320 321 // Test filter by collection, pagination and sorting. 322 $defaultcoll = core_tag_collection::get_default(); 323 $result = core_tag_external::get_tag_cloud($defaultcoll, false, 2, 'count'); 324 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 325 $this->assertCount(2, $result['tags']); // Only two tags. 326 $this->assertEquals(2, $result['tagscount']); 327 $this->assertEquals(4, $result['totalcount']); 328 $this->assertEquals('Dogs', $result['tags'][0]['name']); // Lower count first. 329 330 // Test search. 331 $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', 'Mice'); 332 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 333 $this->assertCount(1, $result['tags']); // Only the searched tags. 334 $this->assertEquals(1, $result['tagscount']); 335 $this->assertEquals(1, $result['totalcount']); // When searching, the total is always for the search. 336 $this->assertEquals('Mice', $result['tags'][0]['name']); 337 338 $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', 'Conejo'); 339 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 340 $this->assertCount(0, $result['tags']); // Nothing found. 341 $this->assertEquals(0, $result['tagscount']); 342 $this->assertEquals(0, $result['totalcount']); // When searching, the total is always for the search. 343 344 // Test standard filtering. 345 $micetag = core_tag_tag::get_by_name($defaultcoll, 'Mice', '*'); 346 $micetag->update(array('isstandard' => 1)); 347 348 $result = core_tag_external::get_tag_cloud(0, true); 349 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 350 $this->assertCount(1, $result['tags']); 351 $this->assertEquals(1, $result['tagscount']); 352 $this->assertEquals(1, $result['totalcount']); // When searching, the total is always for the search. 353 $this->assertEquals('Mice', $result['tags'][0]['name']); 354 355 // Test course context filtering. 356 $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', '', 0, $coursecontext->id); 357 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 358 $this->assertCount(1, $result['tags']); 359 $this->assertEquals(1, $result['tagscount']); 360 $this->assertEquals(1, $result['totalcount']); // When searching, the total is always for the search. 361 $this->assertEquals('Cats', $result['tags'][0]['name']); 362 363 // Complete system context. 364 $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', '', 0, context_system::instance()->id); 365 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 366 $this->assertCount(4, $result['tags']); 367 $this->assertEquals(4, $result['tagscount']); 368 369 // Just system context - avoid children. 370 $result = core_tag_external::get_tag_cloud(0, false, 150, 'name', '', 0, context_system::instance()->id, 0); 371 $result = external_api::clean_returnvalue(core_tag_external::get_tag_cloud_returns(), $result); 372 $this->assertCount(2, $result['tags']); 373 $this->assertEquals(2, $result['tagscount']); // Horses and Cats. 374 $this->assertEquals('Cats', $result['tags'][0]['name']); 375 $this->assertEquals('Horses', $result['tags'][1]['name']); 376 } 377 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body