[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
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 * Tag related unit tests. 19 * 20 * @package core_tag 21 * @category test 22 * @copyright 2014 Mark Nelson <markn@moodle.com> 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 class core_tag_taglib_testcase extends advanced_testcase { 31 32 /** 33 * Test set up. 34 * 35 * This is executed before running any test in this file. 36 */ 37 public function setUp() { 38 $this->resetAfterTest(); 39 } 40 41 /** 42 * Test the tag_set function. 43 * This function was deprecated in 3.1 44 */ 45 public function test_tag_set_get() { 46 global $DB; 47 48 // Create a course to tag. 49 $course = $this->getDataGenerator()->create_course(); 50 51 // Create the tag and tag instance. 52 tag_set('course', $course->id, array('A random tag'), 'core', context_course::instance($course->id)->id); 53 $this->assertDebuggingCalled(); 54 55 // Get the tag instance that should have been created. 56 $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course->id), '*', MUST_EXIST); 57 $this->assertEquals('core', $taginstance->component); 58 $this->assertEquals(context_course::instance($course->id)->id, $taginstance->contextid); 59 60 $tagbyname = tag_get('name', 'A random tag'); 61 $this->assertDebuggingCalled(); 62 $this->assertEquals('A random tag', $tagbyname->rawname); 63 64 $this->assertEmpty(tag_get('name', 'Non existing tag')); 65 $this->assertDebuggingCalled(); 66 67 $tagbyid = tag_get('id', $tagbyname->id); 68 $this->assertDebuggingCalled(); 69 $this->assertEquals('A random tag', $tagbyid->rawname); 70 $tagid = $tagbyname->id; 71 72 $this->assertEmpty(tag_get('id', $tagid + 1)); 73 $this->assertDebuggingCalled(); 74 75 tag_set('tag', $tagid, array('Some related tag')); 76 $this->assertDebuggingCalled(); 77 $relatedtags = tag_get_related_tags($tagid); 78 $this->assertDebuggingCalled(); 79 $this->assertCount(1, $relatedtags); 80 $this->assertEquals('Some related tag', $relatedtags[0]->rawname); 81 82 $tagids = tag_get_id(array('A random tag', 'Some related tag')); 83 $this->assertDebuggingCalled(); 84 $this->assertCount(2, $tagids); 85 $this->assertEquals($tagid, $tagids['a random tag']); 86 $this->assertEquals($relatedtags[0]->id, $tagids['some related tag']); 87 } 88 89 /** 90 * Test the tag_set_add function. 91 * This function was deprecated in 3.1 92 */ 93 public function test_tag_set_add() { 94 global $DB; 95 96 // Create a course to tag. 97 $course = $this->getDataGenerator()->create_course(); 98 99 // Create the tag and tag instance. 100 tag_set_add('course', $course->id, 'A random tag', 'core', context_course::instance($course->id)->id); 101 $this->assertDebuggingCalled(); 102 103 // Get the tag instance that should have been created. 104 $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course->id), '*', MUST_EXIST); 105 $this->assertEquals('core', $taginstance->component); 106 $this->assertEquals(context_course::instance($course->id)->id, $taginstance->contextid); 107 $tagid = $taginstance->tagid; 108 109 tag_set_add('tag', $tagid, 'Some related tag'); 110 $this->assertDebuggingCalled(); 111 $relatedtags = tag_get_related_tags($tagid); 112 $this->assertDebuggingCalled(); 113 $this->assertCount(1, $relatedtags); 114 $this->assertEquals('Some related tag', $relatedtags[0]->rawname); 115 } 116 117 /** 118 * Test the tag_set_delete function. 119 * This function was deprecated in 3.1 120 */ 121 public function test_tag_set_delete() { 122 global $DB; 123 124 // Create a course to tag. 125 $course = $this->getDataGenerator()->create_course(); 126 127 // Create the tag and tag instance we are going to delete. 128 tag_set_add('course', $course->id, 'A random tag', 'core', context_course::instance($course->id)->id); 129 $this->assertDebuggingCalled(); 130 131 // Call the tag_set_delete function. 132 tag_set_delete('course', $course->id, 'a random tag', 'core', context_course::instance($course->id)->id); 133 $this->assertDebuggingCalled(); 134 135 // Now check that there are no tags or tag instances. 136 $this->assertEquals(0, $DB->count_records('tag')); 137 $this->assertEquals(0, $DB->count_records('tag_instance')); 138 139 // Add tag again, add and remove related tag. 140 tag_set_add('course', $course->id, 'A random tag', 'core', context_course::instance($course->id)->id); 141 $this->assertDebuggingCalled(); 142 $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course->id), '*', MUST_EXIST); 143 $tagid = $taginstance->tagid; 144 tag_set_add('tag', $tagid, 'Some related tag'); 145 $this->assertDebuggingCalled(); 146 tag_set_delete('tag', $tagid, 'Some related tag'); 147 $this->assertDebuggingCalled(); 148 $relatedtags = tag_get_related_tags($tagid); 149 $this->assertDebuggingCalled(); 150 $this->assertCount(0, $relatedtags); 151 } 152 153 /** 154 * Test the core_tag_tag::add_item_tag() and core_tag_tag::remove_item_tag() functions. 155 */ 156 public function test_add_remove_item_tag() { 157 global $DB; 158 159 // Create a course to tag. 160 $course = $this->getDataGenerator()->create_course(); 161 162 // Create the tag and tag instance we are going to delete. 163 core_tag_tag::add_item_tag('core', 'course', $course->id, context_course::instance($course->id), 'A random tag'); 164 165 $this->assertEquals(1, $DB->count_records('tag')); 166 $this->assertEquals(1, $DB->count_records('tag_instance')); 167 168 // Call the tag_set_delete function. 169 core_tag_tag::remove_item_tag('core', 'course', $course->id, 'A random tag'); 170 171 // Now check that there are no tags or tag instances. 172 $this->assertEquals(0, $DB->count_records('tag')); 173 $this->assertEquals(0, $DB->count_records('tag_instance')); 174 } 175 176 /** 177 * Test the tag_assign function. 178 * This function was deprecated in 3.1 179 */ 180 public function test_tag_assign() { 181 global $DB; 182 183 // Create a course to tag. 184 $course = $this->getDataGenerator()->create_course(); 185 186 // Create the tag. 187 $tag = $this->getDataGenerator()->create_tag(); 188 $tag2 = $this->getDataGenerator()->create_tag(); 189 190 // Tag the course with the tag we created. 191 tag_assign('course', $course->id, $tag->id, 0, 0, 'core', context_course::instance($course->id)->id); 192 $this->assertDebuggingCalled(); 193 194 // Get the tag instance that should have been created. 195 $taginstance = $DB->get_record('tag_instance', array('itemtype' => 'course', 'itemid' => $course->id), '*', MUST_EXIST); 196 $this->assertEquals('core', $taginstance->component); 197 $this->assertEquals(context_course::instance($course->id)->id, $taginstance->contextid); 198 199 // Now call the tag_assign function without specifying the component or 200 // contextid and ensure the function debugging is called twice. 201 tag_assign('course', $course->id, $tag2->id, 0, 0); 202 $this->assertDebuggingCalled(); 203 } 204 205 /** 206 * Test the tag cleanup function used by the cron. 207 */ 208 public function test_tag_cleanup() { 209 global $DB; 210 211 $task = new \core\task\tag_cron_task(); 212 213 // Create some users. 214 $users = array(); 215 for ($i = 0; $i < 10; $i++) { 216 $users[] = $this->getDataGenerator()->create_user(); 217 } 218 219 // Create a course to tag. 220 $course = $this->getDataGenerator()->create_course(); 221 $context = context_course::instance($course->id); 222 223 // Test clean up instances with tags that no longer exist. 224 $tags = array(); 225 $tagnames = array(); 226 for ($i = 0; $i < 10; $i++) { 227 $tags[] = $tag = $this->getDataGenerator()->create_tag(array('userid' => $users[0]->id)); 228 $tagnames[] = $tag->rawname; 229 } 230 // Create instances with the tags. 231 core_tag_tag::set_item_tags('core', 'course', $course->id, $context, $tagnames); 232 // We should now have ten tag instances. 233 $coursetaginstances = $DB->count_records('tag_instance', array('itemtype' => 'course')); 234 $this->assertEquals(10, $coursetaginstances); 235 236 // Delete four tags 237 // Manual delete of tags is done as the function will remove the instances as well. 238 $DB->delete_records('tag', array('id' => $tags[6]->id)); 239 $DB->delete_records('tag', array('id' => $tags[7]->id)); 240 $DB->delete_records('tag', array('id' => $tags[8]->id)); 241 $DB->delete_records('tag', array('id' => $tags[9]->id)); 242 243 // Clean up the tags. 244 $task->cleanup(); 245 // Check that we now only have six tag_instance records left. 246 $coursetaginstances = $DB->count_records('tag_instance', array('itemtype' => 'course')); 247 $this->assertEquals(6, $coursetaginstances); 248 249 // Test clean up with users that have been deleted. 250 // Create a tag for this course. 251 foreach ($users as $user) { 252 $context = context_user::instance($user->id); 253 core_tag_tag::set_item_tags('core', 'user', $user->id, $context, array($tags[0]->rawname)); 254 } 255 $usertags = $DB->count_records('tag_instance', array('itemtype' => 'user')); 256 $this->assertCount($usertags, $users); 257 // Remove three students. 258 // Using the proper function to delete the user will also remove the tags. 259 $DB->update_record('user', array('id' => $users[4]->id, 'deleted' => 1)); 260 $DB->update_record('user', array('id' => $users[5]->id, 'deleted' => 1)); 261 $DB->update_record('user', array('id' => $users[6]->id, 'deleted' => 1)); 262 263 // Clean up the tags. 264 $task->cleanup(); 265 $usertags = $DB->count_records('tag_instance', array('itemtype' => 'user')); 266 $usercount = $DB->count_records('user', array('deleted' => 0)); 267 // Remove admin and guest from the count. 268 $this->assertEquals($usertags, ($usercount - 2)); 269 270 // Test clean up where a course has been removed. 271 // Delete the course. This also needs to be this way otherwise the tags are removed by using the proper function. 272 $DB->delete_records('course', array('id' => $course->id)); 273 $task->cleanup(); 274 $coursetags = $DB->count_records('tag_instance', array('itemtype' => 'course')); 275 $this->assertEquals(0, $coursetags); 276 277 // Test clean up where a post has been removed. 278 // Create default post. 279 $post = new stdClass(); 280 $post->userid = $users[1]->id; 281 $post->content = 'test post content text'; 282 $post->id = $DB->insert_record('post', $post); 283 $context = context_system::instance(); 284 core_tag_tag::set_item_tags('core', 'post', $post->id, $context, array($tags[0]->rawname)); 285 286 // Add another one with a fake post id to be removed. 287 core_tag_tag::set_item_tags('core', 'post', 15, $context, array($tags[0]->rawname)); 288 // Check that there are two tag instances. 289 $posttags = $DB->count_records('tag_instance', array('itemtype' => 'post')); 290 $this->assertEquals(2, $posttags); 291 // Clean up the tags. 292 $task->cleanup(); 293 // We should only have one entry left now. 294 $posttags = $DB->count_records('tag_instance', array('itemtype' => 'post')); 295 $this->assertEquals(1, $posttags); 296 } 297 298 /** 299 * Test deleting a group of tag instances. 300 */ 301 public function test_tag_bulk_delete_instances() { 302 global $DB; 303 $task = new \core\task\tag_cron_task(); 304 305 // Setup. 306 $user = $this->getDataGenerator()->create_user(); 307 $course = $this->getDataGenerator()->create_course(); 308 $context = context_course::instance($course->id); 309 310 // Create some tag instances. 311 for ($i = 0; $i < 10; $i++) { 312 $tag = $this->getDataGenerator()->create_tag(array('userid' => $user->id)); 313 core_tag_tag::add_item_tag('core', 'course', $course->id, $context, $tag->rawname); 314 } 315 // Get tag instances. tag name and rawname are required for the event fired in this function. 316 $sql = "SELECT ti.*, t.name, t.rawname 317 FROM {tag_instance} ti 318 JOIN {tag} t ON t.id = ti.tagid"; 319 $taginstances = $DB->get_records_sql($sql); 320 $this->assertCount(10, $taginstances); 321 // Run the function. 322 $task->bulk_delete_instances($taginstances); 323 // Make sure they are gone. 324 $instancecount = $DB->count_records('tag_instance'); 325 $this->assertEquals(0, $instancecount); 326 } 327 328 /** 329 * Prepares environment for testing tag correlations 330 * @return core_tag_tag[] list of used tags 331 */ 332 protected function prepare_correlated() { 333 global $DB; 334 335 $user = $this->getDataGenerator()->create_user(); 336 $this->setUser($user); 337 338 $user1 = $this->getDataGenerator()->create_user(); 339 $user2 = $this->getDataGenerator()->create_user(); 340 $user3 = $this->getDataGenerator()->create_user(); 341 $user4 = $this->getDataGenerator()->create_user(); 342 $user5 = $this->getDataGenerator()->create_user(); 343 $user6 = $this->getDataGenerator()->create_user(); 344 345 // Several records have both 'cat' and 'cats' tags attached to them. 346 // This will make those tags automatically correlated. 347 // Same with 'dog', 'dogs' and 'puppy. 348 core_tag_tag::set_item_tags('core', 'user', $user1->id, context_user::instance($user1->id), array('cat', 'cats')); 349 core_tag_tag::set_item_tags('core', 'user', $user2->id, context_user::instance($user2->id), array('cat', 'cats', 'kitten')); 350 core_tag_tag::set_item_tags('core', 'user', $user3->id, context_user::instance($user3->id), array('cat', 'cats')); 351 core_tag_tag::set_item_tags('core', 'user', $user4->id, context_user::instance($user4->id), array('dog', 'dogs', 'puppy')); 352 core_tag_tag::set_item_tags('core', 'user', $user5->id, context_user::instance($user5->id), array('dog', 'dogs', 'puppy')); 353 core_tag_tag::set_item_tags('core', 'user', $user6->id, context_user::instance($user6->id), array('dog', 'dogs', 'puppy')); 354 355 $tags = core_tag_tag::get_by_name_bulk(core_tag_collection::get_default(), 356 array('cat', 'cats', 'dog', 'dogs', 'kitten', 'puppy'), '*'); 357 358 // Add manual relation between tags 'cat' and 'kitten'. 359 core_tag_tag::get($tags['cat']->id)->set_related_tags(array('kitten')); 360 361 return $tags; 362 } 363 364 /** 365 * Test for function tag_compute_correlations() that is part of tag cron 366 */ 367 public function test_correlations() { 368 global $DB; 369 $task = new \core\task\tag_cron_task(); 370 371 $tags = array_map(function ($t) { 372 return $t->id; 373 }, $this->prepare_correlated()); 374 375 $task->compute_correlations(); 376 377 $this->assertEquals($tags['cats'], 378 $DB->get_field_select('tag_correlation', 'correlatedtags', 379 'tagid = ?', array($tags['cat']))); 380 $this->assertEquals($tags['cat'], 381 $DB->get_field_select('tag_correlation', 'correlatedtags', 382 'tagid = ?', array($tags['cats']))); 383 $this->assertEquals($tags['dogs'] . ',' . $tags['puppy'], 384 $DB->get_field_select('tag_correlation', 'correlatedtags', 385 'tagid = ?', array($tags['dog']))); 386 $this->assertEquals($tags['dog'] . ',' . $tags['puppy'], 387 $DB->get_field_select('tag_correlation', 'correlatedtags', 388 'tagid = ?', array($tags['dogs']))); 389 $this->assertEquals($tags['dog'] . ',' . $tags['dogs'], 390 $DB->get_field_select('tag_correlation', 'correlatedtags', 391 'tagid = ?', array($tags['puppy']))); 392 393 // Make sure get_correlated_tags() returns 'cats' as the only correlated tag to the 'cat'. 394 $correlatedtags = array_values(core_tag_tag::get($tags['cat'])->get_correlated_tags(true)); 395 $this->assertCount(3, $correlatedtags); // This will return all existing instances but they all point to the same tag. 396 $this->assertEquals('cats', $correlatedtags[0]->rawname); 397 $this->assertEquals('cats', $correlatedtags[1]->rawname); 398 $this->assertEquals('cats', $correlatedtags[2]->rawname); 399 400 $correlatedtags = array_values(core_tag_tag::get($tags['cat'])->get_correlated_tags()); 401 $this->assertCount(1, $correlatedtags); // Duplicates are filtered out here. 402 $this->assertEquals('cats', $correlatedtags[0]->rawname); 403 404 // Make sure tag_get_correlated() returns 'dogs' and 'puppy' as the correlated tags to the 'dog'. 405 $correlatedtags = core_tag_tag::get($tags['dog'])->get_correlated_tags(true); 406 $this->assertCount(6, $correlatedtags); // 2 tags times 3 instances. 407 408 $correlatedtags = array_values(core_tag_tag::get($tags['dog'])->get_correlated_tags()); 409 $this->assertCount(2, $correlatedtags); 410 $this->assertEquals('dogs', $correlatedtags[0]->rawname); 411 $this->assertEquals('puppy', $correlatedtags[1]->rawname); 412 413 // Function get_related_tags() will return both related and correlated tags. 414 $relatedtags = array_values(core_tag_tag::get($tags['cat'])->get_related_tags()); 415 $this->assertCount(2, $relatedtags); 416 $this->assertEquals('kitten', $relatedtags[0]->rawname); 417 $this->assertEquals('cats', $relatedtags[1]->rawname); 418 419 // Also test deprecated method tag_get_related_tags() and tag_get_correlated(). 420 $correlatedtags = array_values(tag_get_correlated($tags['cat'])); 421 $this->assertDebuggingCalled(); 422 $this->assertCount(3, $correlatedtags); // This will return all existing instances but they all point to the same tag. 423 $this->assertEquals('cats', $correlatedtags[0]->rawname); 424 $this->assertEquals('cats', $correlatedtags[1]->rawname); 425 $this->assertEquals('cats', $correlatedtags[2]->rawname); 426 427 $correlatedtags = array_values(tag_get_related_tags($tags['cat'], TAG_RELATED_CORRELATED)); 428 $this->assertDebuggingCalled(); 429 $this->assertCount(1, $correlatedtags); // Duplicates are filtered out here. 430 $this->assertEquals('cats', $correlatedtags[0]->rawname); 431 432 $correlatedtags = array_values(tag_get_correlated($tags['dog'])); 433 $this->assertDebuggingCalled(); 434 $this->assertCount(6, $correlatedtags); // 2 tags times 3 instances. 435 436 $correlatedtags = array_values(tag_get_related_tags($tags['dog'], TAG_RELATED_CORRELATED)); 437 $this->assertDebuggingCalled(); 438 $this->assertCount(2, $correlatedtags); 439 $this->assertEquals('dogs', $correlatedtags[0]->rawname); 440 $this->assertEquals('puppy', $correlatedtags[1]->rawname); 441 442 $relatedtags = array_values(tag_get_related_tags($tags['cat'])); 443 $this->assertDebuggingCalled(); 444 $this->assertCount(2, $relatedtags); 445 $this->assertEquals('kitten', $relatedtags[0]->rawname); 446 $this->assertEquals('cats', $relatedtags[1]->rawname); 447 // End of testing deprecated methods. 448 449 // If we then manually set 'cat' and 'cats' as related, get_related_tags() will filter out duplicates. 450 core_tag_tag::get($tags['cat'])->set_related_tags(array('kitten', 'cats')); 451 452 $relatedtags = array_values(core_tag_tag::get($tags['cat'])->get_related_tags()); 453 $this->assertCount(2, $relatedtags); 454 $this->assertEquals('kitten', $relatedtags[0]->rawname); 455 $this->assertEquals('cats', $relatedtags[1]->rawname); 456 457 // Make sure core_tag_tag::get_item_tags(), core_tag_tag::get_correlated_tags() return the same set of fields. 458 $relatedtags = core_tag_tag::get_item_tags('core', 'tag', $tags['cat']); 459 $relatedtag = reset($relatedtags); 460 $correlatedtags = core_tag_tag::get($tags['cat'])->get_correlated_tags(); 461 $correlatedtag = reset($correlatedtags); 462 $this->assertEquals(array_keys((array)$relatedtag->to_object()), array_keys((array)$correlatedtag->to_object())); 463 464 // Make sure tag_get_correlated() and tag_get_tags() return the same set of fields. 465 // Both functions were deprecated in 3.1. 466 $relatedtags = tag_get_tags('tag', $tags['cat']); 467 $this->assertDebuggingCalled(); 468 $relatedtag = reset($relatedtags); 469 $correlatedtags = tag_get_correlated($tags['cat']); 470 $this->assertDebuggingCalled(); 471 $correlatedtag = reset($correlatedtags); 472 $this->assertEquals(array_keys((array)$relatedtag), array_keys((array)$correlatedtag)); 473 } 474 475 /** 476 * Test for function tag_cleanup() that is part of tag cron 477 */ 478 public function test_cleanup() { 479 global $DB; 480 $task = new \core\task\tag_cron_task(); 481 482 $user = $this->getDataGenerator()->create_user(); 483 $defaultcoll = core_tag_collection::get_default(); 484 485 // Setting tags will create non-standard tags 'cat', 'dog' and 'fish'. 486 core_tag_tag::set_item_tags('core', 'user', $user->id, context_user::instance($user->id), array('cat', 'dog', 'fish')); 487 488 $this->assertTrue($DB->record_exists('tag', array('name' => 'cat'))); 489 $this->assertTrue($DB->record_exists('tag', array('name' => 'dog'))); 490 $this->assertTrue($DB->record_exists('tag', array('name' => 'fish'))); 491 492 // Make tag 'dog' standard. 493 $dogtag = core_tag_tag::get_by_name($defaultcoll, 'dog', '*'); 494 $fishtag = core_tag_tag::get_by_name($defaultcoll, 'fish'); 495 $dogtag->update(array('isstandard' => 1)); 496 497 // Manually remove the instances pointing on tags 'dog' and 'fish'. 498 $DB->execute('DELETE FROM {tag_instance} WHERE tagid in (?,?)', array($dogtag->id, $fishtag->id)); 499 500 // Call tag_cleanup(). 501 $task->cleanup(); 502 503 // Tag 'cat' is still present because it's used. Tag 'dog' is present because it's standard. 504 // Tag 'fish' was removed because it is not standard and it is no longer used by anybody. 505 $this->assertTrue($DB->record_exists('tag', array('name' => 'cat'))); 506 $this->assertTrue($DB->record_exists('tag', array('name' => 'dog'))); 507 $this->assertFalse($DB->record_exists('tag', array('name' => 'fish'))); 508 509 // Delete user without using API function. 510 $DB->update_record('user', array('id' => $user->id, 'deleted' => 1)); 511 512 // Call tag_cleanup(). 513 $task->cleanup(); 514 515 // Tag 'cat' was now deleted too. 516 $this->assertFalse($DB->record_exists('tag', array('name' => 'cat'))); 517 518 // Assign tag to non-existing record. Make sure tag was created in the DB. 519 core_tag_tag::set_item_tags('core', 'course', 1231231, context_system::instance(), array('bird')); 520 $this->assertTrue($DB->record_exists('tag', array('name' => 'bird'))); 521 522 // Call tag_cleanup(). 523 $task->cleanup(); 524 525 // Tag 'bird' was now deleted because the related record does not exist in the DB. 526 $this->assertFalse($DB->record_exists('tag', array('name' => 'bird'))); 527 528 // Now we have a tag instance pointing on 'sometag' tag. 529 $user = $this->getDataGenerator()->create_user(); 530 core_tag_tag::set_item_tags('core', 'user', $user->id, context_user::instance($user->id), array('sometag')); 531 $sometag = core_tag_tag::get_by_name($defaultcoll, 'sometag'); 532 533 $this->assertTrue($DB->record_exists('tag_instance', array('tagid' => $sometag->id))); 534 535 // Some hacker removes the tag without using API. 536 $DB->delete_records('tag', array('id' => $sometag->id)); 537 538 // Call tag_cleanup(). 539 $task->cleanup(); 540 541 // The tag instances were also removed. 542 $this->assertFalse($DB->record_exists('tag_instance', array('tagid' => $sometag->id))); 543 } 544 545 public function test_guess_tag() { 546 global $DB; 547 $user = $this->getDataGenerator()->create_user(); 548 $this->setUser($user); 549 $tag1 = $this->getDataGenerator()->create_tag(array('name' => 'Cat')); 550 $tc = core_tag_collection::create((object)array('name' => 'tagcoll')); 551 $tag2 = $this->getDataGenerator()->create_tag(array('name' => 'Cat', 'tagcollid' => $tc->id)); 552 $this->assertEquals(2, count($DB->get_records('tag'))); 553 $this->assertEquals(2, count(core_tag_tag::guess_by_name('Cat'))); 554 $this->assertEquals(core_tag_collection::get_default(), core_tag_tag::get_by_name(0, 'Cat')->tagcollid); 555 } 556 557 public function test_instances() { 558 global $DB; 559 $user = $this->getDataGenerator()->create_user(); 560 $this->setUser($user); 561 562 // Create a course to tag. 563 $course = $this->getDataGenerator()->create_course(); 564 $context = context_course::instance($course->id); 565 566 $initialtagscount = $DB->count_records('tag'); 567 568 core_tag_tag::set_item_tags('core', 'course', $course->id, $context, array('Tag 1', 'Tag 2')); 569 $tags = core_tag_tag::get_item_tags('core', 'course', $course->id); 570 $tagssimple = array_values($tags); 571 $this->assertEquals(2, count($tags)); 572 $this->assertEquals('Tag 1', $tagssimple[0]->rawname); 573 $this->assertEquals('Tag 2', $tagssimple[1]->rawname); 574 $this->assertEquals($initialtagscount + 2, $DB->count_records('tag')); 575 576 core_tag_tag::set_item_tags('core', 'course', $course->id, $context, array('Tag 3', 'Tag 2', 'Tag 1')); 577 $tags = core_tag_tag::get_item_tags('core', 'course', $course->id); 578 $tagssimple = array_values($tags); 579 $this->assertEquals(3, count($tags)); 580 $this->assertEquals('Tag 3', $tagssimple[0]->rawname); 581 $this->assertEquals('Tag 2', $tagssimple[1]->rawname); 582 $this->assertEquals('Tag 1', $tagssimple[2]->rawname); 583 $this->assertEquals($initialtagscount + 3, $DB->count_records('tag')); 584 585 core_tag_tag::set_item_tags('core', 'course', $course->id, $context, array('Tag 3')); 586 $tags = core_tag_tag::get_item_tags('core', 'course', $course->id); 587 $tagssimple = array_values($tags); 588 $this->assertEquals(1, count($tags)); 589 $this->assertEquals('Tag 3', $tagssimple[0]->rawname); 590 591 // Make sure the unused tags were removed from tag table. 592 $this->assertEquals($initialtagscount + 1, $DB->count_records('tag')); 593 } 594 595 public function test_related_tags() { 596 global $DB; 597 $user = $this->getDataGenerator()->create_user(); 598 $this->setUser($user); 599 $tagcollid = core_tag_collection::get_default(); 600 $tag = $this->getDataGenerator()->create_tag(array('$tagcollid' => $tagcollid, 'rawname' => 'My tag')); 601 $tag = core_tag_tag::get($tag->id, '*'); 602 603 $tag->set_related_tags(array('Synonym 1', 'Synonym 2')); 604 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $tag->id)); 605 $this->assertEquals(2, count($relatedtags)); 606 $this->assertEquals('Synonym 1', $relatedtags[0]->rawname); 607 $this->assertEquals('Synonym 2', $relatedtags[1]->rawname); 608 609 $t1 = core_tag_tag::get_by_name($tagcollid, 'Synonym 1', '*'); 610 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $t1->id)); 611 $this->assertEquals(1, count($relatedtags)); 612 $this->assertEquals('My tag', $relatedtags[0]->rawname); 613 614 $t2 = core_tag_tag::get_by_name($tagcollid, 'Synonym 2', '*'); 615 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $t2->id)); 616 $this->assertEquals(1, count($relatedtags)); 617 $this->assertEquals('My tag', $relatedtags[0]->rawname); 618 619 $tag->set_related_tags(array('Synonym 3', 'Synonym 2', 'Synonym 1')); 620 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $tag->id)); 621 $this->assertEquals(3, count($relatedtags)); 622 $this->assertEquals('Synonym 1', $relatedtags[0]->rawname); 623 $this->assertEquals('Synonym 2', $relatedtags[1]->rawname); 624 $this->assertEquals('Synonym 3', $relatedtags[2]->rawname); 625 626 $t3 = core_tag_tag::get_by_name($tagcollid, 'Synonym 3', '*'); 627 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $t3->id)); 628 $this->assertEquals(1, count($relatedtags)); 629 $this->assertEquals('My tag', $relatedtags[0]->rawname); 630 631 $tag->set_related_tags(array('Synonym 3', 'Synonym 2')); 632 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $tag->id)); 633 $this->assertEquals(2, count($relatedtags)); 634 $this->assertEquals('Synonym 2', $relatedtags[0]->rawname); 635 $this->assertEquals('Synonym 3', $relatedtags[1]->rawname); 636 637 // Assert "Synonym 1" no longer links but is still present (will be removed by cron). 638 $relatedtags = array_values(core_tag_tag::get_item_tags('core', 'tag', $t1->id)); 639 $this->assertEquals(0, count($relatedtags)); 640 } 641 642 /** 643 * Very basic test for create/move/update/delete actions, without any itemtype movements. 644 */ 645 public function test_tag_coll_basic() { 646 global $DB; 647 648 // Make sure there is one and only one tag coll that is marked as default. 649 $tagcolls = core_tag_collection::get_collections(); 650 $this->assertEquals(1, count($DB->get_records('tag_coll', array('isdefault' => 1)))); 651 $defaulttagcoll = core_tag_collection::get_default(); 652 653 // Create a new tag coll to store user tags and something else. 654 $data = (object)array('name' => 'new tag coll'); 655 $tagcollid1 = core_tag_collection::create($data)->id; 656 $tagcolls = core_tag_collection::get_collections(); 657 $this->assertEquals('new tag coll', $tagcolls[$tagcollid1]->name); 658 659 // Create a new tag coll to store post tags. 660 $data = (object)array('name' => 'posts'); 661 $tagcollid2 = core_tag_collection::create($data)->id; 662 $tagcolls = core_tag_collection::get_collections(); 663 $this->assertEquals('posts', $tagcolls[$tagcollid2]->name); 664 $this->assertEquals($tagcolls[$tagcollid1]->sortorder + 1, 665 $tagcolls[$tagcollid2]->sortorder); 666 667 // Illegal tag colls sortorder changing. 668 $this->assertFalse(core_tag_collection::change_sortorder($tagcolls[$defaulttagcoll], 1)); 669 $this->assertFalse(core_tag_collection::change_sortorder($tagcolls[$defaulttagcoll], -1)); 670 $this->assertFalse(core_tag_collection::change_sortorder($tagcolls[$tagcollid2], 1)); 671 672 // Move the very last tag coll one position up. 673 $this->assertTrue(core_tag_collection::change_sortorder($tagcolls[$tagcollid2], -1)); 674 $tagcolls = core_tag_collection::get_collections(); 675 $this->assertEquals($tagcolls[$tagcollid2]->sortorder + 1, 676 $tagcolls[$tagcollid1]->sortorder); 677 678 // Move the second last tag coll one position down. 679 $this->assertTrue(core_tag_collection::change_sortorder($tagcolls[$tagcollid2], 1)); 680 $tagcolls = core_tag_collection::get_collections(); 681 $this->assertEquals($tagcolls[$tagcollid1]->sortorder + 1, 682 $tagcolls[$tagcollid2]->sortorder); 683 684 // Edit tag coll. 685 $this->assertTrue(core_tag_collection::update($tagcolls[$tagcollid2], 686 (object)array('name' => 'posts2'))); 687 $tagcolls = core_tag_collection::get_collections(); 688 $this->assertEquals('posts2', $tagcolls[$tagcollid2]->name); 689 690 // Delete tag coll. 691 $count = $DB->count_records('tag_coll'); 692 $this->assertFalse(core_tag_collection::delete($tagcolls[$defaulttagcoll])); 693 $this->assertTrue(core_tag_collection::delete($tagcolls[$tagcollid1])); 694 $this->assertEquals($count - 1, $DB->count_records('tag_coll')); 695 } 696 697 /** 698 * Prepares environment for test_move_tags_* tests 699 */ 700 protected function prepare_move_tags() { 701 global $CFG; 702 require_once($CFG->dirroot.'/blog/locallib.php'); 703 $this->setUser($this->getDataGenerator()->create_user()); 704 705 $collid1 = core_tag_collection::get_default(); 706 $collid2 = core_tag_collection::create(array('name' => 'newcoll'))->id; 707 $user1 = $this->getDataGenerator()->create_user(); 708 $user2 = $this->getDataGenerator()->create_user(); 709 $blogpost = new blog_entry(null, array('subject' => 'test'), null); 710 $states = blog_entry::get_applicable_publish_states(); 711 $blogpost->publishstate = reset($states); 712 $blogpost->add(); 713 714 core_tag_tag::set_item_tags('core', 'user', $user1->id, context_user::instance($user1->id), 715 array('Tag1', 'Tag2')); 716 core_tag_tag::set_item_tags('core', 'user', $user2->id, context_user::instance($user2->id), 717 array('Tag2', 'Tag3')); 718 $this->getDataGenerator()->create_tag(array('rawname' => 'Tag4', 719 'tagcollid' => $collid1, 'isstandard' => 1)); 720 $this->getDataGenerator()->create_tag(array('rawname' => 'Tag5', 721 'tagcollid' => $collid2, 'isstandard' => 1)); 722 723 return array($collid1, $collid2, $user1, $user2, $blogpost); 724 } 725 726 public function test_move_tags_simple() { 727 global $DB; 728 list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags(); 729 730 // Move 'user' area from collection 1 to collection 2, make sure tags were moved completely. 731 $tagarea = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core')); 732 core_tag_area::update($tagarea, array('tagcollid' => $collid2)); 733 734 $tagsaftermove = $DB->get_records('tag'); 735 foreach ($tagsaftermove as $tag) { 736 // Confirm that the time modified has not been unset. 737 $this->assertNotEmpty($tag->timemodified); 738 } 739 740 $this->assertEquals(array('Tag4'), 741 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid1))); 742 $this->assertEquals(array('Tag1', 'Tag2', 'Tag3', 'Tag5'), 743 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid2))); 744 $this->assertEquals(array('Tag1', 'Tag2'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user1->id))); 745 $this->assertEquals(array('Tag2', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user2->id))); 746 } 747 748 public function test_move_tags_split_tag() { 749 global $DB; 750 list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags(); 751 752 core_tag_tag::set_item_tags('core', 'post', $blogpost->id, context_system::instance(), 753 array('Tag1', 'Tag3')); 754 755 // Move 'user' area from collection 1 to collection 2, make sure tag Tag2 was moved and tags Tag1 and Tag3 were duplicated. 756 $tagareauser = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core')); 757 core_tag_area::update($tagareauser, array('tagcollid' => $collid2)); 758 759 $tagsaftermove = $DB->get_records('tag'); 760 foreach ($tagsaftermove as $tag) { 761 // Confirm that the time modified has not been unset. 762 $this->assertNotEmpty($tag->timemodified); 763 } 764 765 $this->assertEquals(array('Tag1', 'Tag3', 'Tag4'), 766 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid1))); 767 $this->assertEquals(array('Tag1', 'Tag2', 'Tag3', 'Tag5'), 768 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid2))); 769 $this->assertEquals(array('Tag1', 'Tag2'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user1->id))); 770 $this->assertEquals(array('Tag2', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user2->id))); 771 $this->assertEquals(array('Tag1', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'post', $blogpost->id))); 772 } 773 774 public function test_move_tags_merge_tag() { 775 global $DB; 776 list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags(); 777 778 // Set collection for 'post' tag area to be collection 2 and add some tags there. 779 $tagareablog = $DB->get_record('tag_area', array('itemtype' => 'post', 'component' => 'core')); 780 core_tag_area::update($tagareablog, array('tagcollid' => $collid2)); 781 782 core_tag_tag::set_item_tags('core', 'post', $blogpost->id, context_system::instance(), 783 array('TAG1', 'Tag3')); 784 785 // Move 'user' area from collection 1 to collection 2, 786 // make sure tag Tag2 was moved and tags Tag1 and Tag3 were merged into existing. 787 $tagareauser = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core')); 788 core_tag_area::update($tagareauser, array('tagcollid' => $collid2)); 789 790 $tagsaftermove = $DB->get_records('tag'); 791 foreach ($tagsaftermove as $tag) { 792 // Confirm that the time modified has not been unset. 793 $this->assertNotEmpty($tag->timemodified); 794 } 795 796 $this->assertEquals(array('Tag4'), 797 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid1))); 798 $this->assertEquals(array('TAG1', 'Tag2', 'Tag3', 'Tag5'), 799 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid2))); 800 $this->assertEquals(array('TAG1', 'Tag2'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user1->id))); 801 $this->assertEquals(array('Tag2', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user2->id))); 802 $this->assertEquals(array('TAG1', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'post', $blogpost->id))); 803 } 804 805 public function test_move_tags_with_related() { 806 global $DB; 807 list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags(); 808 809 // Set Tag1 to be related to Tag2 and Tag4 (in collection 1). 810 core_tag_tag::get_by_name($collid1, 'Tag1')->set_related_tags(array('Tag2', 'Tag4')); 811 812 // Set collection for 'post' tag area to be collection 2 and add some tags there. 813 $tagareablog = $DB->get_record('tag_area', array('itemtype' => 'post', 'component' => 'core')); 814 core_tag_area::update($tagareablog, array('tagcollid' => $collid2)); 815 816 core_tag_tag::set_item_tags('core', 'post', $blogpost->id, context_system::instance(), 817 array('TAG1', 'Tag3')); 818 819 // Move 'user' area from collection 1 to collection 2, make sure tags were moved completely. 820 $tagarea = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core')); 821 core_tag_area::update($tagarea, array('tagcollid' => $collid2)); 822 823 $tagsaftermove = $DB->get_records('tag'); 824 foreach ($tagsaftermove as $tag) { 825 // Confirm that the time modified has not been unset. 826 $this->assertNotEmpty($tag->timemodified); 827 } 828 829 $this->assertEquals(array('Tag1', 'Tag2', 'Tag4'), 830 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid1))); 831 $this->assertEquals(array('TAG1', 'Tag2', 'Tag3', 'Tag4', 'Tag5'), 832 $DB->get_fieldset_select('tag', 'rawname', 'tagcollid = ? ORDER BY name', array($collid2))); 833 $this->assertEquals(array('TAG1', 'Tag2'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user1->id))); 834 $this->assertEquals(array('Tag2', 'Tag3'), array_values(core_tag_tag::get_item_tags_array('core', 'user', $user2->id))); 835 836 $tag11 = core_tag_tag::get_by_name($collid1, 'Tag1'); 837 $related11 = tag_get_related_tags($tag11->id, TAG_RELATED_MANUAL); 838 $this->assertDebuggingCalled(); 839 $related11 = array_map('core_tag_tag::make_display_name', $related11); 840 sort($related11); // Order of related tags may be random. 841 $this->assertEquals('Tag2, Tag4', join(', ', $related11)); 842 843 $tag21 = core_tag_tag::get_by_name($collid2, 'TAG1'); 844 $related21 = tag_get_related_tags($tag21->id, TAG_RELATED_MANUAL); 845 $this->assertDebuggingCalled(); 846 $related21 = array_map('core_tag_tag::make_display_name', $related21); 847 sort($related21); // Order of related tags may be random. 848 $this->assertEquals('Tag2, Tag4', join(', ', $related21)); 849 } 850 851 public function test_move_tags_corrupted() { 852 global $DB; 853 list($collid1, $collid2, $user1, $user2, $blogpost) = $this->prepare_move_tags(); 854 $collid3 = core_tag_collection::create(array('name' => 'weirdcoll'))->id; 855 856 // We already have Tag1 in coll1, now let's create it in coll3. 857 $extratag1 = $this->getDataGenerator()->create_tag(array('rawname' => 'Tag1', 858 'tagcollid' => $collid3, 'isstandard' => 1)); 859 860 // Artificially add 'Tag1' from coll3 to user2. 861 $DB->insert_record('tag_instance', array('tagid' => $extratag1->id, 'itemtype' => 'user', 862 'component' => 'core', 'itemid' => $user2->id, 'ordering' => 3)); 863 864 // Now we have corrupted data: both users are tagged with 'Tag1', however these are two tags in different collections. 865 $user1tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user1->id)); 866 $user2tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user2->id)); 867 $this->assertEquals('Tag1', $user1tags[0]->rawname); 868 $this->assertEquals('Tag1', $user2tags[2]->rawname); 869 $this->assertNotEquals($user1tags[0]->tagcollid, $user2tags[2]->tagcollid); 870 871 // Move user interests tag area into coll2. 872 $tagarea = $DB->get_record('tag_area', array('itemtype' => 'user', 'component' => 'core')); 873 core_tag_area::update($tagarea, array('tagcollid' => $collid2)); 874 875 $tagsaftermove = $DB->get_records('tag'); 876 foreach ($tagsaftermove as $tag) { 877 // Confirm that the time modified has not been unset. 878 $this->assertNotEmpty($tag->timemodified); 879 } 880 881 // Now all tags are correctly moved to the new collection and both tags 'Tag1' were merged. 882 $user1tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user1->id)); 883 $user2tags = array_values(core_tag_tag::get_item_tags('core', 'user', $user2->id)); 884 $this->assertEquals('Tag1', $user1tags[0]->rawname); 885 $this->assertEquals('Tag1', $user2tags[2]->rawname); 886 $this->assertEquals($collid2, $user1tags[0]->tagcollid); 887 $this->assertEquals($collid2, $user2tags[2]->tagcollid); 888 } 889 890 public function test_normalize() { 891 $tagset = array('Cat', ' Dog ', '<Mouse', '<>', 'mouse', 'Dog'); 892 893 // Test function tag_normalize() that was deprecated in 3.1. 894 $this->assertEquals(array('Cat' => 'Cat', 'Dog' => 'Dog', '<Mouse' => 'Mouse', '<>' => '', 'mouse' => 'mouse'), 895 tag_normalize($tagset, TAG_CASE_ORIGINAL)); 896 $this->assertDebuggingCalled(); 897 $this->assertEquals(array('Cat' => 'cat', 'Dog' => 'dog', '<Mouse' => 'mouse', '<>' => '', 'mouse' => 'mouse'), 898 tag_normalize($tagset, TAG_CASE_LOWER)); 899 $this->assertDebuggingCalled(); 900 901 // Test replacement function core_tag_tag::normalize(). 902 $this->assertEquals(array('Cat' => 'Cat', 'Dog' => 'Dog', '<Mouse' => 'Mouse', '<>' => '', 'mouse' => 'mouse'), 903 core_tag_tag::normalize($tagset, false)); 904 $this->assertEquals(array('Cat' => 'cat', 'Dog' => 'dog', '<Mouse' => 'mouse', '<>' => '', 'mouse' => 'mouse'), 905 core_tag_tag::normalize($tagset, true)); 906 } 907 908 /** 909 * Test functions core_tag_tag::create_if_missing() and core_tag_tag::get_by_name_bulk(). 910 */ 911 public function test_create_get() { 912 $tagset = array('Cat', ' Dog ', '<Mouse', '<>', 'mouse', 'Dog'); 913 914 $collid = core_tag_collection::get_default(); 915 $tags = core_tag_tag::create_if_missing($collid, $tagset); 916 $this->assertEquals(array('cat', 'dog', 'mouse'), array_keys($tags)); 917 $this->assertEquals('Dog', $tags['dog']->rawname); 918 $this->assertEquals('mouse', $tags['mouse']->rawname); // Case of the last tag wins. 919 920 $tags2 = core_tag_tag::create_if_missing($collid, array('CAT', 'Elephant')); 921 $this->assertEquals(array('cat', 'elephant'), array_keys($tags2)); 922 $this->assertEquals('Cat', $tags2['cat']->rawname); 923 $this->assertEquals('Elephant', $tags2['elephant']->rawname); 924 $this->assertEquals($tags['cat']->id, $tags2['cat']->id); // Tag 'cat' already existed and was not created again. 925 926 $tags3 = core_tag_tag::get_by_name_bulk($collid, $tagset); 927 $this->assertEquals(array('cat', 'dog', 'mouse'), array_keys($tags3)); 928 $this->assertEquals('Dog', $tags3['dog']->rawname); 929 $this->assertEquals('mouse', $tags3['mouse']->rawname); 930 931 } 932 933 /** 934 * Testing function core_tag_tag::combine_tags() 935 */ 936 public function test_combine_tags() { 937 $initialtags = array( 938 array('Cat', 'Dog'), 939 array('Dog', 'Cat'), 940 array('Cats', 'Hippo'), 941 array('Hippo', 'Cats'), 942 array('Cat', 'Mouse', 'Kitten'), 943 array('Cats', 'Mouse', 'Kitten'), 944 array('Kitten', 'Mouse', 'Cat'), 945 array('Kitten', 'Mouse', 'Cats'), 946 array('Cats', 'Mouse', 'Kitten'), 947 array('Mouse', 'Hippo') 948 ); 949 950 $finaltags = array( 951 array('Cat', 'Dog'), 952 array('Dog', 'Cat'), 953 array('Cat', 'Hippo'), 954 array('Hippo', 'Cat'), 955 array('Cat', 'Mouse'), 956 array('Cat', 'Mouse'), 957 array('Mouse', 'Cat'), 958 array('Mouse', 'Cat'), 959 array('Cat', 'Mouse'), 960 array('Mouse', 'Hippo') 961 ); 962 963 $collid = core_tag_collection::get_default(); 964 $context = context_system::instance(); 965 foreach ($initialtags as $id => $taglist) { 966 core_tag_tag::set_item_tags('core', 'course', $id + 10, $context, $initialtags[$id]); 967 } 968 969 core_tag_tag::get_by_name($collid, 'Cats', '*')->update(array('isstandard' => 1)); 970 971 // Combine tags 'Cats' and 'Kitten' into 'Cat'. 972 $cat = core_tag_tag::get_by_name($collid, 'Cat', '*'); 973 $cats = core_tag_tag::get_by_name($collid, 'Cats', '*'); 974 $kitten = core_tag_tag::get_by_name($collid, 'Kitten', '*'); 975 $cat->combine_tags(array($cats, $kitten)); 976 977 foreach ($finaltags as $id => $taglist) { 978 $this->assertEquals($taglist, 979 array_values(core_tag_tag::get_item_tags_array('core', 'course', $id + 10)), 980 'Original array ('.join(', ', $initialtags[$id]).')'); 981 } 982 983 // Ensure combined tags are deleted and 'Cat' is now official (because 'Cats' was official). 984 $this->assertEmpty(core_tag_tag::get_by_name($collid, 'Cats')); 985 $this->assertEmpty(core_tag_tag::get_by_name($collid, 'Kitten')); 986 $cattag = core_tag_tag::get_by_name($collid, 'Cat', '*'); 987 $this->assertEquals(1, $cattag->isstandard); 988 } 989 990 /** 991 * Testing function core_tag_tag::combine_tags() when related tags are present. 992 */ 993 public function test_combine_tags_with_related() { 994 $collid = core_tag_collection::get_default(); 995 $context = context_system::instance(); 996 core_tag_tag::set_item_tags('core', 'course', 10, $context, array('Cat', 'Cats', 'Dog')); 997 core_tag_tag::get_by_name($collid, 'Cat', '*')->set_related_tags(array('Kitty')); 998 core_tag_tag::get_by_name($collid, 'Cats', '*')->set_related_tags(array('Cat', 'Kitten', 'Kitty')); 999 1000 // Combine tags 'Cats' into 'Cat'. 1001 $cat = core_tag_tag::get_by_name($collid, 'Cat', '*'); 1002 $cats = core_tag_tag::get_by_name($collid, 'Cats', '*'); 1003 $cat->combine_tags(array($cats)); 1004 1005 // Ensure 'Cat' is now related to 'Kitten' and 'Kitty' (order of related tags may be random). 1006 $relatedtags = array_map(function($t) {return $t->rawname;}, $cat->get_manual_related_tags()); 1007 sort($relatedtags); 1008 $this->assertEquals(array('Kitten', 'Kitty'), array_values($relatedtags)); 1009 } 1010 1011 /** 1012 * Testing function core_tag_tag::combine_tags() when correlated tags are present. 1013 */ 1014 public function test_combine_tags_with_correlated() { 1015 $task = new \core\task\tag_cron_task(); 1016 1017 $tags = $this->prepare_correlated(); 1018 1019 $task->compute_correlations(); 1020 // Now 'cat' is correlated with 'cats'. 1021 // Also 'dog', 'dogs' and 'puppy' are correlated. 1022 // There is a manual relation between 'cat' and 'kitten'. 1023 // See function test_correlations() for assertions. 1024 1025 // Combine tags 'dog' and 'kitten' into 'cat' and make sure that cat is now correlated with dogs and puppy. 1026 $tags['cat']->combine_tags(array($tags['dog'], $tags['kitten'])); 1027 1028 $correlatedtags = $this->get_correlated_tags_names($tags['cat']); 1029 $this->assertEquals(['cats', 'dogs', 'puppy'], $correlatedtags); 1030 1031 $correlatedtags = $this->get_correlated_tags_names($tags['dogs']); 1032 $this->assertEquals(['cat', 'puppy'], $correlatedtags); 1033 1034 $correlatedtags = $this->get_correlated_tags_names($tags['puppy']); 1035 $this->assertEquals(['cat', 'dogs'], $correlatedtags); 1036 1037 // Add tag that does not have any correlations. 1038 $user7 = $this->getDataGenerator()->create_user(); 1039 core_tag_tag::set_item_tags('core', 'user', $user7->id, context_user::instance($user7->id), array('hippo')); 1040 $tags['hippo'] = core_tag_tag::get_by_name(core_tag_collection::get_default(), 'hippo', '*'); 1041 1042 // Combine tag 'cat' into 'hippo'. Now 'hippo' should have the same correlations 'cat' used to have and also 1043 // tags 'dogs' and 'puppy' should have 'hippo' in correlations. 1044 $tags['hippo']->combine_tags(array($tags['cat'])); 1045 1046 $correlatedtags = $this->get_correlated_tags_names($tags['hippo']); 1047 $this->assertEquals(['cats', 'dogs', 'puppy'], $correlatedtags); 1048 1049 $correlatedtags = $this->get_correlated_tags_names($tags['dogs']); 1050 $this->assertEquals(['hippo', 'puppy'], $correlatedtags); 1051 1052 $correlatedtags = $this->get_correlated_tags_names($tags['puppy']); 1053 $this->assertEquals(['dogs', 'hippo'], $correlatedtags); 1054 } 1055 1056 /** 1057 * Help method to return sorted array of names of correlated tags to use for assertions 1058 * @param core_tag $tag 1059 * @return string 1060 */ 1061 protected function get_correlated_tags_names($tag) { 1062 $rv = array_map(function($t) { 1063 return $t->rawname; 1064 }, $tag->get_correlated_tags()); 1065 sort($rv); 1066 return array_values($rv); 1067 } 1068 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |