[ Index ] |
PHP Cross Reference of moodle-2.8 |
[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 * Unit tests for the condition tree class and related logic. 19 * 20 * @package core_availability 21 * @copyright 2014 The Open University 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 use core_availability\capability_checker; 26 use \core_availability\tree; 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 /** 31 * Unit tests for the condition tree class and related logic. 32 * 33 * @package core_availability 34 * @copyright 2014 The Open University 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class tree_testcase extends \advanced_testcase { 38 public function setUp() { 39 // Load the mock classes so they can be used. 40 require_once (__DIR__ . '/fixtures/mock_condition.php'); 41 require_once (__DIR__ . '/fixtures/mock_info.php'); 42 } 43 44 /** 45 * Tests constructing a tree with errors. 46 */ 47 public function test_construct_errors() { 48 try { 49 new tree('frog'); 50 $this->fail(); 51 } catch (coding_exception $e) { 52 $this->assertContains('not object', $e->getMessage()); 53 } 54 try { 55 new tree((object)array()); 56 $this->fail(); 57 } catch (coding_exception $e) { 58 $this->assertContains('missing ->op', $e->getMessage()); 59 } 60 try { 61 new tree((object)array('op' => '*')); 62 $this->fail(); 63 } catch (coding_exception $e) { 64 $this->assertContains('unknown ->op', $e->getMessage()); 65 } 66 try { 67 new tree((object)array('op' => '|')); 68 $this->fail(); 69 } catch (coding_exception $e) { 70 $this->assertContains('missing ->show', $e->getMessage()); 71 } 72 try { 73 new tree((object)array('op' => '|', 'show' => 0)); 74 $this->fail(); 75 } catch (coding_exception $e) { 76 $this->assertContains('->show not bool', $e->getMessage()); 77 } 78 try { 79 new tree((object)array('op' => '&')); 80 $this->fail(); 81 } catch (coding_exception $e) { 82 $this->assertContains('missing ->showc', $e->getMessage()); 83 } 84 try { 85 new tree((object)array('op' => '&', 'showc' => 0)); 86 $this->fail(); 87 } catch (coding_exception $e) { 88 $this->assertContains('->showc not array', $e->getMessage()); 89 } 90 try { 91 new tree((object)array('op' => '&', 'showc' => array(0))); 92 $this->fail(); 93 } catch (coding_exception $e) { 94 $this->assertContains('->showc value not bool', $e->getMessage()); 95 } 96 try { 97 new tree((object)array('op' => '|', 'show' => true)); 98 $this->fail(); 99 } catch (coding_exception $e) { 100 $this->assertContains('missing ->c', $e->getMessage()); 101 } 102 try { 103 new tree((object)array('op' => '|', 'show' => true, 104 'c' => 'side')); 105 $this->fail(); 106 } catch (coding_exception $e) { 107 $this->assertContains('->c not array', $e->getMessage()); 108 } 109 try { 110 new tree((object)array('op' => '|', 'show' => true, 111 'c' => array(3))); 112 $this->fail(); 113 } catch (coding_exception $e) { 114 $this->assertContains('child not object', $e->getMessage()); 115 } 116 try { 117 new tree((object)array('op' => '|', 'show' => true, 118 'c' => array((object)array('type' => 'doesnotexist')))); 119 $this->fail(); 120 } catch (coding_exception $e) { 121 $this->assertContains('Unknown condition type: doesnotexist', $e->getMessage()); 122 } 123 try { 124 new tree((object)array('op' => '|', 'show' => true, 125 'c' => array((object)array()))); 126 $this->fail(); 127 } catch (coding_exception $e) { 128 $this->assertContains('missing ->op', $e->getMessage()); 129 } 130 try { 131 new tree((object)array('op' => '&', 132 'c' => array((object)array('op' => '&', 'c' => array())), 133 'showc' => array(true, true) 134 )); 135 $this->fail(); 136 } catch (coding_exception $e) { 137 $this->assertContains('->c, ->showc mismatch', $e->getMessage()); 138 } 139 } 140 141 /** 142 * Tests constructing a tree with plugin that does not exist (ignored). 143 */ 144 public function test_construct_ignore_missing_plugin() { 145 // Construct a tree with & combination of one condition that doesn't exist. 146 $tree = new tree(tree::get_root_json(array( 147 (object)array('type' => 'doesnotexist')), tree::OP_OR), true); 148 // Expected result is an empty tree with | condition, shown. 149 $this->assertEquals('+|()', (string)$tree); 150 } 151 152 /** 153 * Tests constructing a tree with subtrees using all available operators. 154 */ 155 public function test_construct_just_trees() { 156 $structure = tree::get_root_json(array( 157 tree::get_nested_json(array(), tree::OP_OR), 158 tree::get_nested_json(array( 159 tree::get_nested_json(array(), tree::OP_NOT_OR)), tree::OP_NOT_AND)), 160 tree::OP_AND, array(true, true)); 161 $tree = new tree($structure); 162 $this->assertEquals('&(+|(),+!&(!|()))', (string)$tree); 163 } 164 165 /** 166 * Tests constructing tree using the mock plugin. 167 */ 168 public function test_construct_with_mock_plugin() { 169 $structure = tree::get_root_json(array( 170 self::mock(array('a' => true, 'm' => ''))), tree::OP_OR); 171 $tree = new tree($structure); 172 $this->assertEquals('+|({mock:y,})', (string)$tree); 173 } 174 175 /** 176 * Tests the check_available and get_result_information functions. 177 */ 178 public function test_check_available() { 179 global $USER; 180 181 // Setup. 182 $this->resetAfterTest(); 183 $info = new \core_availability\mock_info(); 184 $this->setAdminUser(); 185 $information = ''; 186 187 // No conditions. 188 $structure = tree::get_root_json(array(), tree::OP_OR); 189 list ($available, $information) = $this->get_available_results( 190 $structure, $info, $USER->id); 191 $this->assertTrue($available); 192 193 // One condition set to yes. 194 $structure->c = array( 195 self::mock(array('a' => true))); 196 list ($available, $information) = $this->get_available_results( 197 $structure, $info, $USER->id); 198 $this->assertTrue($available); 199 200 // One condition set to no. 201 $structure->c = array( 202 self::mock(array('a' => false, 'm' => 'no'))); 203 list ($available, $information) = $this->get_available_results( 204 $structure, $info, $USER->id); 205 $this->assertFalse($available); 206 $this->assertEquals('SA: no', $information); 207 208 // Two conditions, OR, resolving as true. 209 $structure->c = array( 210 self::mock(array('a' => false, 'm' => 'no')), 211 self::mock(array('a' => true))); 212 list ($available, $information) = $this->get_available_results( 213 $structure, $info, $USER->id); 214 $this->assertTrue($available); 215 $this->assertEquals('', $information); 216 217 // Two conditions, OR, resolving as false. 218 $structure->c = array( 219 self::mock(array('a' => false, 'm' => 'no')), 220 self::mock(array('a' => false, 'm' => 'way'))); 221 list ($available, $information) = $this->get_available_results( 222 $structure, $info, $USER->id); 223 $this->assertFalse($available); 224 $this->assertRegExp('~any of.*no.*way~', $information); 225 226 // Two conditions, OR, resolving as false, no display. 227 $structure->show = false; 228 list ($available, $information) = $this->get_available_results( 229 $structure, $info, $USER->id); 230 $this->assertFalse($available); 231 $this->assertEquals('', $information); 232 233 // Two conditions, AND, resolving as true. 234 $structure->op = '&'; 235 unset($structure->show); 236 $structure->showc = array(true, true); 237 $structure->c = array( 238 self::mock(array('a' => true)), 239 self::mock(array('a' => true))); 240 list ($available, $information) = $this->get_available_results( 241 $structure, $info, $USER->id); 242 $this->assertTrue($available); 243 244 // Two conditions, AND, one false. 245 $structure->c = array( 246 self::mock(array('a' => false, 'm' => 'wom')), 247 self::mock(array('a' => true, 'm' => ''))); 248 list ($available, $information) = $this->get_available_results( 249 $structure, $info, $USER->id); 250 $this->assertFalse($available); 251 $this->assertEquals('SA: wom', $information); 252 253 // Two conditions, AND, both false. 254 $structure->c = array( 255 self::mock(array('a' => false, 'm' => 'wom')), 256 self::mock(array('a' => false, 'm' => 'bat'))); 257 list ($available, $information) = $this->get_available_results( 258 $structure, $info, $USER->id); 259 $this->assertFalse($available); 260 $this->assertRegExp('~wom.*bat~', $information); 261 262 // Two conditions, AND, both false, show turned off for one. When 263 // show is turned off, that means if you don't have that condition 264 // you don't get to see anything at all. 265 $structure->showc[0] = false; 266 list ($available, $information) = $this->get_available_results( 267 $structure, $info, $USER->id); 268 $this->assertFalse($available); 269 $this->assertEquals('', $information); 270 $structure->showc[0] = true; 271 272 // Two conditions, NOT OR, both false. 273 $structure->op = '!|'; 274 list ($available, $information) = $this->get_available_results( 275 $structure, $info, $USER->id); 276 $this->assertTrue($available); 277 278 // Two conditions, NOT OR, one true. 279 $structure->c[0]->a = true; 280 list ($available, $information) = $this->get_available_results( 281 $structure, $info, $USER->id); 282 $this->assertFalse($available); 283 $this->assertEquals('SA: !wom', $information); 284 285 // Two conditions, NOT OR, both true. 286 $structure->c[1]->a = true; 287 list ($available, $information) = $this->get_available_results( 288 $structure, $info, $USER->id); 289 $this->assertFalse($available); 290 $this->assertRegExp('~!wom.*!bat~', $information); 291 292 // Two conditions, NOT AND, both true. 293 $structure->op = '!&'; 294 unset($structure->showc); 295 $structure->show = true; 296 list ($available, $information) = $this->get_available_results( 297 $structure, $info, $USER->id); 298 $this->assertFalse($available); 299 $this->assertRegExp('~any of.*!wom.*!bat~', $information); 300 301 // Two conditions, NOT AND, one true. 302 $structure->c[1]->a = false; 303 list ($available, $information) = $this->get_available_results( 304 $structure, $info, $USER->id); 305 $this->assertTrue($available); 306 307 // Nested NOT conditions; true. 308 $structure->c = array( 309 tree::get_nested_json(array( 310 self::mock(array('a' => true, 'm' => 'no'))), tree::OP_NOT_AND)); 311 list ($available, $information) = $this->get_available_results( 312 $structure, $info, $USER->id); 313 $this->assertTrue($available); 314 315 // Nested NOT conditions; false (note no ! in message). 316 $structure->c[0]->c[0]->a = false; 317 list ($available, $information) = $this->get_available_results( 318 $structure, $info, $USER->id); 319 $this->assertFalse($available); 320 $this->assertEquals('SA: no', $information); 321 322 // Nested condition groups, message test. 323 $structure->op = '|'; 324 $structure->c = array( 325 tree::get_nested_json(array( 326 self::mock(array('a' => false, 'm' => '1')), 327 self::mock(array('a' => false, 'm' => '2')) 328 ), tree::OP_AND), 329 self::mock(array('a' => false, 'm' => 3))); 330 list ($available, $information) = $this->get_available_results( 331 $structure, $info, $USER->id); 332 $this->assertFalse($available); 333 $this->assertRegExp('~<ul.*<ul.*<li.*1.*<li.*2.*</ul>.*<li.*3~', $information); 334 } 335 336 /** 337 * Shortcut function to check availability and also get information. 338 * 339 * @param stdClass $structure Tree structure 340 * @param \core_availability\info $info Location info 341 * @param int $userid User id 342 */ 343 protected function get_available_results($structure, \core_availability\info $info, $userid) { 344 $tree = new tree($structure); 345 $result = $tree->check_available(false, $info, true, $userid); 346 return array($result->is_available(), $tree->get_result_information($info, $result)); 347 } 348 349 /** 350 * Tests the is_available_for_all() function. 351 */ 352 public function test_is_available_for_all() { 353 // Empty tree is always available. 354 $structure = tree::get_root_json(array(), tree::OP_OR); 355 $tree = new tree($structure); 356 $this->assertTrue($tree->is_available_for_all()); 357 358 // Tree with normal item in it, not always available. 359 $structure->c[0] = (object)array('type' => 'mock'); 360 $tree = new tree($structure); 361 $this->assertFalse($tree->is_available_for_all()); 362 363 // OR tree with one always-available item. 364 $structure->c[1] = self::mock(array('all' => true)); 365 $tree = new tree($structure); 366 $this->assertTrue($tree->is_available_for_all()); 367 368 // AND tree with one always-available and one not. 369 $structure->op = '&'; 370 $structure->showc = array(true, true); 371 unset($structure->show); 372 $tree = new tree($structure); 373 $this->assertFalse($tree->is_available_for_all()); 374 375 // Test NOT conditions (items not always-available). 376 $structure->op = '!&'; 377 $structure->show = true; 378 unset($structure->showc); 379 $tree = new tree($structure); 380 $this->assertFalse($tree->is_available_for_all()); 381 382 // Test again with one item always-available for NOT mode. 383 $structure->c[1]->allnot = true; 384 $tree = new tree($structure); 385 $this->assertTrue($tree->is_available_for_all()); 386 } 387 388 /** 389 * Tests the get_full_information() function. 390 */ 391 public function test_get_full_information() { 392 // Setup. 393 $info = new \core_availability\mock_info(); 394 395 // No conditions. 396 $structure = tree::get_root_json(array(), tree::OP_OR); 397 $tree = new tree($structure); 398 $this->assertEquals('', $tree->get_full_information($info)); 399 400 // Condition (normal and NOT). 401 $structure->c = array( 402 self::mock(array('m' => 'thing'))); 403 $tree = new tree($structure); 404 $this->assertEquals('SA: [FULL]thing', 405 $tree->get_full_information($info)); 406 $structure->op = '!&'; 407 $tree = new tree($structure); 408 $this->assertEquals('SA: ![FULL]thing', 409 $tree->get_full_information($info)); 410 411 // Complex structure. 412 $structure->op = '|'; 413 $structure->c = array( 414 tree::get_nested_json(array( 415 self::mock(array('m' => '1')), 416 self::mock(array('m' => '2'))), tree::OP_AND), 417 self::mock(array('m' => 3))); 418 $tree = new tree($structure); 419 $this->assertRegExp('~<ul.*<ul.*<li.*1.*<li.*2.*</ul>.*<li.*3~', 420 $tree->get_full_information($info)); 421 422 // Test intro messages before list. First, OR message. 423 $structure->c = array( 424 self::mock(array('m' => '1')), 425 self::mock(array('m' => '2')) 426 ); 427 $tree = new tree($structure); 428 $this->assertRegExp('~Not available unless any of:.*<ul>~', 429 $tree->get_full_information($info)); 430 431 // Now, OR message when not shown. 432 $structure->show = false; 433 $tree = new tree($structure); 434 $this->assertRegExp('~hidden.*<ul>~', 435 $tree->get_full_information($info)); 436 437 // AND message. 438 $structure->op = '&'; 439 unset($structure->show); 440 $structure->showc = array(false, false); 441 $tree = new tree($structure); 442 $this->assertRegExp('~Not available unless:.*<ul>~', 443 $tree->get_full_information($info)); 444 445 // Hidden markers on items. 446 $this->assertRegExp('~1.*hidden.*2.*hidden~', 447 $tree->get_full_information($info)); 448 449 // Hidden markers on child tree and items. 450 $structure->c[1] = tree::get_nested_json(array( 451 self::mock(array('m' => '2')), 452 self::mock(array('m' => '3'))), tree::OP_AND); 453 $tree = new tree($structure); 454 $this->assertRegExp('~1.*hidden.*All of \(hidden.*2.*3~', 455 $tree->get_full_information($info)); 456 $structure->c[1]->op = '|'; 457 $tree = new tree($structure); 458 $this->assertRegExp('~1.*hidden.*Any of \(hidden.*2.*3~', 459 $tree->get_full_information($info)); 460 461 // Hidden markers on single-item display, AND and OR. 462 $structure->showc = array(false); 463 $structure->c = array( 464 self::mock(array('m' => '1')) 465 ); 466 $tree = new tree($structure); 467 $this->assertRegExp('~1.*hidden~', 468 $tree->get_full_information($info)); 469 470 unset($structure->showc); 471 $structure->show = false; 472 $structure->op = '|'; 473 $tree = new tree($structure); 474 $this->assertRegExp('~1.*hidden~', 475 $tree->get_full_information($info)); 476 477 // Hidden marker if single item is tree. 478 $structure->c[0] = tree::get_nested_json(array( 479 self::mock(array('m' => '1')), 480 self::mock(array('m' => '2'))), tree::OP_AND); 481 $tree = new tree($structure); 482 $this->assertRegExp('~Not available \(hidden.*1.*2~', 483 $tree->get_full_information($info)); 484 485 // Single item tree containing single item. 486 unset($structure->c[0]->c[1]); 487 $tree = new tree($structure); 488 $this->assertRegExp('~SA.*1.*hidden~', 489 $tree->get_full_information($info)); 490 } 491 492 /** 493 * Tests the is_empty() function. 494 */ 495 public function test_is_empty() { 496 // Tree with nothing in should be empty. 497 $structure = tree::get_root_json(array(), tree::OP_OR); 498 $tree = new tree($structure); 499 $this->assertTrue($tree->is_empty()); 500 501 // Tree with something in is not empty. 502 $structure = tree::get_root_json(array(self::mock(array('m' => '1'))), tree::OP_OR); 503 $tree = new tree($structure); 504 $this->assertFalse($tree->is_empty()); 505 } 506 507 /** 508 * Tests the get_all_children() function. 509 */ 510 public function test_get_all_children() { 511 // Create a tree with nothing in. 512 $structure = tree::get_root_json(array(), tree::OP_OR); 513 $tree1 = new tree($structure); 514 515 // Create second tree with complex structure. 516 $structure->c = array( 517 tree::get_nested_json(array( 518 self::mock(array('m' => '1')), 519 self::mock(array('m' => '2')) 520 ), tree::OP_OR), 521 self::mock(array('m' => 3))); 522 $tree2 = new tree($structure); 523 524 // Check list of conditions from both trees. 525 $this->assertEquals(array(), $tree1->get_all_children('core_availability\condition')); 526 $result = $tree2->get_all_children('core_availability\condition'); 527 $this->assertEquals(3, count($result)); 528 $this->assertEquals('{mock:n,1}', (string)$result[0]); 529 $this->assertEquals('{mock:n,2}', (string)$result[1]); 530 $this->assertEquals('{mock:n,3}', (string)$result[2]); 531 532 // Check specific type, should give same results. 533 $result2 = $tree2->get_all_children('availability_mock\condition'); 534 $this->assertEquals($result, $result2); 535 } 536 537 /** 538 * Tests the update_dependency_id() function. 539 */ 540 public function test_update_dependency_id() { 541 // Create tree with structure of 3 mocks. 542 $structure = tree::get_root_json(array( 543 tree::get_nested_json(array( 544 self::mock(array('table' => 'frogs', 'id' => 9)), 545 self::mock(array('table' => 'zombies', 'id' => 9)) 546 )), 547 self::mock(array('table' => 'frogs', 'id' => 9)))); 548 549 // Get 'before' value. 550 $tree = new tree($structure); 551 $before = $tree->save(); 552 553 // Try replacing a table or id that isn't used. 554 $this->assertFalse($tree->update_dependency_id('toads', 9, 13)); 555 $this->assertFalse($tree->update_dependency_id('frogs', 7, 8)); 556 $this->assertEquals($before, $tree->save()); 557 558 // Replace the zombies one. 559 $this->assertTrue($tree->update_dependency_id('zombies', 9, 666)); 560 $after = $tree->save(); 561 $this->assertEquals(666, $after->c[0]->c[1]->id); 562 563 // And the frogs one. 564 $this->assertTrue($tree->update_dependency_id('frogs', 9, 3)); 565 $after = $tree->save(); 566 $this->assertEquals(3, $after->c[0]->c[0]->id); 567 $this->assertEquals(3, $after->c[1]->id); 568 } 569 570 /** 571 * Tests the filter_users function. 572 */ 573 public function test_filter_users() { 574 $info = new \core_availability\mock_info(); 575 $checker = new capability_checker($info->get_context()); 576 577 // Don't need to create real users in database, just use these ids. 578 $users = array(1 => null, 2 => null, 3 => null); 579 580 // Test basic tree with one condition that doesn't filter. 581 $structure = tree::get_root_json(array(self::mock(array()))); 582 $tree = new tree($structure); 583 $result = $tree->filter_user_list($users, false, $info, $checker); 584 ksort($result); 585 $this->assertEquals(array(1, 2, 3), array_keys($result)); 586 587 // Now a tree with one condition that filters. 588 $structure = tree::get_root_json(array(self::mock(array('filter' => array(2, 3))))); 589 $tree = new tree($structure); 590 $result = $tree->filter_user_list($users, false, $info, $checker); 591 ksort($result); 592 $this->assertEquals(array(2, 3), array_keys($result)); 593 594 // Tree with two conditions that both filter (|). 595 $structure = tree::get_root_json(array( 596 self::mock(array('filter' => array(3))), 597 self::mock(array('filter' => array(1)))), tree::OP_OR); 598 $tree = new tree($structure); 599 $result = $tree->filter_user_list($users, false, $info, $checker); 600 ksort($result); 601 $this->assertEquals(array(1, 3), array_keys($result)); 602 603 // Tree with two condition that both filter (&). 604 $structure = tree::get_root_json(array( 605 self::mock(array('filter' => array(2, 3))), 606 self::mock(array('filter' => array(1, 2))))); 607 $tree = new tree($structure); 608 $result = $tree->filter_user_list($users, false, $info, $checker); 609 ksort($result); 610 $this->assertEquals(array(2), array_keys($result)); 611 612 // Tree with child tree with NOT condition. 613 $structure = tree::get_root_json(array( 614 tree::get_nested_json(array( 615 self::mock(array('filter' => array(1)))), tree::OP_NOT_AND))); 616 $tree = new tree($structure); 617 $result = $tree->filter_user_list($users, false, $info, $checker); 618 ksort($result); 619 $this->assertEquals(array(2, 3), array_keys($result)); 620 } 621 622 /** 623 * Tests the get_json methods in tree (which are mainly for use in testing 624 * but might be used elsewhere). 625 */ 626 public function test_get_json() { 627 // Create a simple child object (fake). 628 $child = (object)array('type' => 'fake'); 629 $childstr = json_encode($child); 630 631 // Minimal case. 632 $this->assertEquals( 633 (object)array('op' => '&', 'c' => array()), 634 tree::get_nested_json(array())); 635 // Children and different operator. 636 $this->assertEquals( 637 (object)array('op' => '|', 'c' => array($child, $child)), 638 tree::get_nested_json(array($child, $child), tree::OP_OR)); 639 640 // Root empty. 641 $this->assertEquals('{"op":"&","c":[],"showc":[]}', 642 json_encode(tree::get_root_json(array(), tree::OP_AND))); 643 // Root with children (multi-show operator). 644 $this->assertEquals('{"op":"&","c":[' . $childstr . ',' . $childstr . 645 '],"showc":[true,true]}', 646 json_encode(tree::get_root_json(array($child, $child), tree::OP_AND))); 647 // Root with children (single-show operator). 648 $this->assertEquals('{"op":"|","c":[' . $childstr . ',' . $childstr . 649 '],"show":true}', 650 json_encode(tree::get_root_json(array($child, $child), tree::OP_OR))); 651 // Root with children (specified show boolean). 652 $this->assertEquals('{"op":"&","c":[' . $childstr . ',' . $childstr . 653 '],"showc":[false,false]}', 654 json_encode(tree::get_root_json(array($child, $child), tree::OP_AND, false))); 655 // Root with children (specified show array). 656 $this->assertEquals('{"op":"&","c":[' . $childstr . ',' . $childstr . 657 '],"showc":[true,false]}', 658 json_encode(tree::get_root_json(array($child, $child), tree::OP_AND, array(true, false)))); 659 } 660 661 /** 662 * Tests get_user_list_sql. 663 */ 664 public function test_get_user_list_sql() { 665 global $DB; 666 $this->resetAfterTest(); 667 $generator = $this->getDataGenerator(); 668 669 // Create a test course with 2 groups and users in each combination of them. 670 $course = $generator->create_course(); 671 $group1 = $generator->create_group(array('courseid' => $course->id)); 672 $group2 = $generator->create_group(array('courseid' => $course->id)); 673 $userin1 = $generator->create_user(); 674 $userin2 = $generator->create_user(); 675 $userinboth = $generator->create_user(); 676 $userinneither = $generator->create_user(); 677 $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student')); 678 foreach (array($userin1, $userin2, $userinboth, $userinneither) as $user) { 679 $generator->enrol_user($user->id, $course->id, $studentroleid); 680 } 681 groups_add_member($group1, $userin1); 682 groups_add_member($group2, $userin2); 683 groups_add_member($group1, $userinboth); 684 groups_add_member($group2, $userinboth); 685 $info = new \core_availability\mock_info($course); 686 687 // Tree with single group condition. 688 $tree = new tree(tree::get_root_json(array( 689 \availability_group\condition::get_json($group1->id) 690 ))); 691 list($sql, $params) = $tree->get_user_list_sql(false, $info, false); 692 $result = $DB->get_fieldset_sql($sql, $params); 693 sort($result); 694 $this->assertEquals(array($userin1->id, $userinboth->id), $result); 695 696 // Tree with 'AND' of both group conditions. 697 $tree = new tree(tree::get_root_json(array( 698 \availability_group\condition::get_json($group1->id), 699 \availability_group\condition::get_json($group2->id) 700 ))); 701 list($sql, $params) = $tree->get_user_list_sql(false, $info, false); 702 $result = $DB->get_fieldset_sql($sql, $params); 703 sort($result); 704 $this->assertEquals(array($userinboth->id), $result); 705 706 // Tree with 'AND' of both group conditions. 707 $tree = new tree(tree::get_root_json(array( 708 \availability_group\condition::get_json($group1->id), 709 \availability_group\condition::get_json($group2->id) 710 ), tree::OP_OR)); 711 list($sql, $params) = $tree->get_user_list_sql(false, $info, false); 712 $result = $DB->get_fieldset_sql($sql, $params); 713 sort($result); 714 $this->assertEquals(array($userin1->id, $userin2->id, $userinboth->id), $result); 715 716 // Check with flipped logic (NOT above level of tree). 717 list($sql, $params) = $tree->get_user_list_sql(true, $info, false); 718 $result = $DB->get_fieldset_sql($sql, $params); 719 sort($result); 720 $this->assertEquals(array($userinneither->id), $result); 721 } 722 723 /** 724 * Utility function to build the PHP structure representing a mock condition. 725 * 726 * @param array $params Mock parameters 727 * @return \stdClass Structure object 728 */ 729 protected static function mock(array $params) { 730 $params['type'] = 'mock'; 731 return (object)$params; 732 } 733 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |