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