[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/availability/tests/ -> tree_test.php (source)

   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  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1