[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/tests/ -> coursecatlib_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   * Tests for class coursecat from lib/coursecatlib.php
  19   *
  20   * @package    core
  21   * @category   phpunit
  22   * @copyright  2013 Marina Glancy
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  defined('MOODLE_INTERNAL') || die();
  27  
  28  global $CFG;
  29  require_once($CFG->libdir . '/coursecatlib.php');
  30  
  31  /**
  32   * Functional test for coursecatlib.php
  33   */
  34  class core_coursecatlib_testcase extends advanced_testcase {
  35  
  36      protected $roles;
  37  
  38      protected function setUp() {
  39          parent::setUp();
  40          $this->resetAfterTest();
  41          $user = $this->getDataGenerator()->create_user();
  42          $this->setUser($user);
  43      }
  44  
  45      protected function get_roleid($context = null) {
  46          global $USER;
  47          if ($context === null) {
  48              $context = context_system::instance();
  49          }
  50          if (is_object($context)) {
  51              $context = $context->id;
  52          }
  53          if (empty($this->roles)) {
  54              $this->roles = array();
  55          }
  56          if (empty($this->roles[$USER->id])) {
  57              $this->roles[$USER->id] = array();
  58          }
  59          if (empty($this->roles[$USER->id][$context])) {
  60              $this->roles[$USER->id][$context] = create_role('Role for '.$USER->id.' in '.$context, 'role'.$USER->id.'-'.$context, '-');
  61              role_assign($this->roles[$USER->id][$context], $USER->id, $context);
  62          }
  63          return $this->roles[$USER->id][$context];
  64      }
  65  
  66      protected function assign_capability($capability, $permission = CAP_ALLOW, $contextid = null) {
  67          if ($contextid === null) {
  68              $contextid = context_system::instance();
  69          }
  70          if (is_object($contextid)) {
  71              $contextid = $contextid->id;
  72          }
  73          assign_capability($capability, $permission, $this->get_roleid($contextid), $contextid, true);
  74          accesslib_clear_all_caches_for_unit_testing();
  75      }
  76  
  77      public function test_create_coursecat() {
  78          // Create the category.
  79          $data = new stdClass();
  80          $data->name = 'aaa';
  81          $data->description = 'aaa';
  82          $data->idnumber = '';
  83  
  84          $category1 = coursecat::create($data);
  85  
  86          // Initially confirm that base data was inserted correctly.
  87          $this->assertSame($data->name, $category1->name);
  88          $this->assertSame($data->description, $category1->description);
  89          $this->assertSame($data->idnumber, $category1->idnumber);
  90  
  91          $this->assertGreaterThanOrEqual(1, $category1->sortorder);
  92  
  93          // Create two more categories and test the sortorder worked correctly.
  94          $data->name = 'ccc';
  95          $category2 = coursecat::create($data);
  96  
  97          $data->name = 'bbb';
  98          $category3 = coursecat::create($data);
  99  
 100          $this->assertGreaterThan($category1->sortorder, $category2->sortorder);
 101          $this->assertGreaterThan($category2->sortorder, $category3->sortorder);
 102      }
 103  
 104      public function test_name_idnumber_exceptions() {
 105          try {
 106              coursecat::create(array('name' => ''));
 107              $this->fail('Missing category name exception expected in coursecat::create');
 108          } catch (moodle_exception $e) {
 109              $this->assertInstanceOf('moodle_exception', $e);
 110          }
 111          $cat1 = coursecat::create(array('name' => 'Cat1', 'idnumber' => '1'));
 112          try {
 113              $cat1->update(array('name' => ''));
 114              $this->fail('Missing category name exception expected in coursecat::update');
 115          } catch (moodle_exception $e) {
 116              $this->assertInstanceOf('moodle_exception', $e);
 117          }
 118          try {
 119              coursecat::create(array('name' => 'Cat2', 'idnumber' => '1'));
 120              $this->fail('Duplicate idnumber exception expected in coursecat::create');
 121          } catch (moodle_exception $e) {
 122              $this->assertInstanceOf('moodle_exception', $e);
 123          }
 124          $cat2 = coursecat::create(array('name' => 'Cat2', 'idnumber' => '2'));
 125          try {
 126              $cat2->update(array('idnumber' => '1'));
 127              $this->fail('Duplicate idnumber exception expected in coursecat::update');
 128          } catch (moodle_exception $e) {
 129              $this->assertInstanceOf('moodle_exception', $e);
 130          }
 131      }
 132  
 133      public function test_visibility() {
 134          $this->assign_capability('moodle/category:viewhiddencategories');
 135          $this->assign_capability('moodle/category:manage');
 136  
 137          // Create category 1 initially hidden.
 138          $category1 = coursecat::create(array('name' => 'Cat1', 'visible' => 0));
 139          $this->assertEquals(0, $category1->visible);
 140          $this->assertEquals(0, $category1->visibleold);
 141  
 142          // Create category 2 initially hidden as a child of hidden category 1.
 143          $category2 = coursecat::create(array('name' => 'Cat2', 'visible' => 0, 'parent' => $category1->id));
 144          $this->assertEquals(0, $category2->visible);
 145          $this->assertEquals(0, $category2->visibleold);
 146  
 147          // Create category 3 initially visible as a child of hidden category 1.
 148          $category3 = coursecat::create(array('name' => 'Cat3', 'visible' => 1, 'parent' => $category1->id));
 149          $this->assertEquals(0, $category3->visible);
 150          $this->assertEquals(1, $category3->visibleold);
 151  
 152          // Show category 1 and make sure that category 2 is hidden and category 3 is visible.
 153          $category1->show();
 154          $this->assertEquals(1, coursecat::get($category1->id)->visible);
 155          $this->assertEquals(0, coursecat::get($category2->id)->visible);
 156          $this->assertEquals(1, coursecat::get($category3->id)->visible);
 157  
 158          // Create visible category 4.
 159          $category4 = coursecat::create(array('name' => 'Cat4'));
 160          $this->assertEquals(1, $category4->visible);
 161          $this->assertEquals(1, $category4->visibleold);
 162  
 163          // Create visible category 5 as a child of visible category 4.
 164          $category5 = coursecat::create(array('name' => 'Cat5', 'parent' => $category4->id));
 165          $this->assertEquals(1, $category5->visible);
 166          $this->assertEquals(1, $category5->visibleold);
 167  
 168          // Hide category 4 and make sure category 5 is hidden too.
 169          $category4->hide();
 170          $this->assertEquals(0, $category4->visible);
 171          $this->assertEquals(0, $category4->visibleold);
 172          $category5 = coursecat::get($category5->id); // We have to re-read from DB.
 173          $this->assertEquals(0, $category5->visible);
 174          $this->assertEquals(1, $category5->visibleold);
 175  
 176          // Show category 4 and make sure category 5 is visible too.
 177          $category4->show();
 178          $this->assertEquals(1, $category4->visible);
 179          $this->assertEquals(1, $category4->visibleold);
 180          $category5 = coursecat::get($category5->id); // We have to re-read from DB.
 181          $this->assertEquals(1, $category5->visible);
 182          $this->assertEquals(1, $category5->visibleold);
 183  
 184          // Move category 5 under hidden category 2 and make sure it became hidden.
 185          $category5->change_parent($category2->id);
 186          $this->assertEquals(0, $category5->visible);
 187          $this->assertEquals(1, $category5->visibleold);
 188  
 189          // Re-read object for category 5 from DB and check again.
 190          $category5 = coursecat::get($category5->id);
 191          $this->assertEquals(0, $category5->visible);
 192          $this->assertEquals(1, $category5->visibleold);
 193  
 194          // Rricky one! Move hidden category 5 under visible category ("Top") and make sure it is still hidden-
 195          // WHY? Well, different people may expect different behaviour here. So better keep it hidden.
 196          $category5->change_parent(0);
 197          $this->assertEquals(0, $category5->visible);
 198          $this->assertEquals(1, $category5->visibleold);
 199      }
 200  
 201      public function test_hierarchy() {
 202          $this->assign_capability('moodle/category:viewhiddencategories');
 203          $this->assign_capability('moodle/category:manage');
 204  
 205          $category1 = coursecat::create(array('name' => 'Cat1'));
 206          $category2 = coursecat::create(array('name' => 'Cat2', 'parent' => $category1->id));
 207          $category3 = coursecat::create(array('name' => 'Cat3', 'parent' => $category1->id));
 208          $category4 = coursecat::create(array('name' => 'Cat4', 'parent' => $category2->id));
 209  
 210          // Check function get_children().
 211          $this->assertEquals(array($category2->id, $category3->id), array_keys($category1->get_children()));
 212          // Check function get_parents().
 213          $this->assertEquals(array($category1->id, $category2->id), $category4->get_parents());
 214  
 215          // Can not move category to itself or to it's children.
 216          $this->assertFalse($category1->can_change_parent($category2->id));
 217          $this->assertFalse($category2->can_change_parent($category2->id));
 218          // Can move category to grandparent.
 219          $this->assertTrue($category4->can_change_parent($category1->id));
 220  
 221          try {
 222              $category2->change_parent($category4->id);
 223              $this->fail('Exception expected - can not move category');
 224          } catch (moodle_exception $e) {
 225              $this->assertInstanceOf('moodle_exception', $e);
 226          }
 227  
 228          $category4->change_parent(0);
 229          $this->assertEquals(array(), $category4->get_parents());
 230          $this->assertEquals(array($category2->id, $category3->id), array_keys($category1->get_children()));
 231          $this->assertEquals(array(), array_keys($category2->get_children()));
 232      }
 233  
 234      public function test_update() {
 235          $category1 = coursecat::create(array('name' => 'Cat1'));
 236          $timecreated = $category1->timemodified;
 237          $this->assertSame('Cat1', $category1->name);
 238          $this->assertTrue(empty($category1->description));
 239          sleep(2);
 240          $testdescription = 'This is cat 1 а также русский текст';
 241          $category1->update(array('description' => $testdescription));
 242          $this->assertSame($testdescription, $category1->description);
 243          $category1 = coursecat::get($category1->id);
 244          $this->assertSame($testdescription, $category1->description);
 245          cache_helper::purge_by_event('changesincoursecat');
 246          $category1 = coursecat::get($category1->id);
 247          $this->assertSame($testdescription, $category1->description);
 248  
 249          $this->assertGreaterThan($timecreated, $category1->timemodified);
 250      }
 251  
 252      public function test_delete() {
 253          global $DB;
 254  
 255          $this->assign_capability('moodle/category:manage');
 256          $this->assign_capability('moodle/course:create');
 257  
 258          $initialcatid = $DB->get_field_sql('SELECT max(id) from {course_categories}');
 259  
 260          $category1 = coursecat::create(array('name' => 'Cat1'));
 261          $category2 = coursecat::create(array('name' => 'Cat2', 'parent' => $category1->id));
 262          $category3 = coursecat::create(array('name' => 'Cat3'));
 263          $category4 = coursecat::create(array('name' => 'Cat4', 'parent' => $category2->id));
 264  
 265          $course1 = $this->getDataGenerator()->create_course(array('category' => $category2->id));
 266          $course2 = $this->getDataGenerator()->create_course(array('category' => $category4->id));
 267          $course3 = $this->getDataGenerator()->create_course(array('category' => $category4->id));
 268          $course4 = $this->getDataGenerator()->create_course(array('category' => $category1->id));
 269  
 270          // Now we have
 271          // $category1
 272          //   $category2
 273          //      $category4
 274          //        $course2
 275          //        $course3
 276          //      $course1
 277          //   $course4
 278          // $category3
 279          // structure.
 280  
 281          // Login as another user to test course:delete capability (user who created course can delete it within 24h even without cap).
 282          $this->setUser($this->getDataGenerator()->create_user());
 283  
 284          // Delete category 2 and move content to category 3.
 285          $this->assertFalse($category2->can_move_content_to($category3->id)); // No luck!
 286          // Add necessary capabilities.
 287          $this->assign_capability('moodle/course:create', CAP_ALLOW, context_coursecat::instance($category3->id));
 288          $this->assign_capability('moodle/category:manage');
 289          $this->assertTrue($category2->can_move_content_to($category3->id)); // Hurray!
 290          $category2->delete_move($category3->id);
 291  
 292          // Make sure we have:
 293          // $category1
 294          //   $course4
 295          // $category3
 296          //    $category4
 297          //      $course2
 298          //      $course3
 299          //    $course1
 300          // structure.
 301  
 302          $this->assertNull(coursecat::get($category2->id, IGNORE_MISSING, true));
 303          $this->assertEquals(array(), $category1->get_children());
 304          $this->assertEquals(array($category4->id), array_keys($category3->get_children()));
 305          $this->assertEquals($category4->id, $DB->get_field('course', 'category', array('id' => $course2->id)));
 306          $this->assertEquals($category4->id, $DB->get_field('course', 'category', array('id' => $course3->id)));
 307          $this->assertEquals($category3->id, $DB->get_field('course', 'category', array('id' => $course1->id)));
 308  
 309          // Delete category 3 completely.
 310          $this->assertFalse($category3->can_delete_full()); // No luck!
 311          // Add necessary capabilities.
 312          $this->assign_capability('moodle/course:delete', CAP_ALLOW, context_coursecat::instance($category3->id));
 313          $this->assertTrue($category3->can_delete_full()); // Hurray!
 314          $category3->delete_full();
 315  
 316          // Make sure we have:
 317          // $category1
 318          //   $course4
 319          // structure.
 320  
 321          // Note that we also have default 'Miscellaneous' category and default 'site' course.
 322          $this->assertEquals(1, $DB->get_field_sql('SELECT count(*) FROM {course_categories} WHERE id > ?', array($initialcatid)));
 323          $this->assertEquals($category1->id, $DB->get_field_sql('SELECT max(id) FROM {course_categories}'));
 324          $this->assertEquals(1, $DB->get_field_sql('SELECT count(*) FROM {course} WHERE id <> ?', array(SITEID)));
 325          $this->assertEquals(array('id' => $course4->id, 'category' => $category1->id),
 326                  (array)$DB->get_record_sql('SELECT id, category from {course} where id <> ?', array(SITEID)));
 327      }
 328  
 329      public function test_get_children() {
 330          $category1 = coursecat::create(array('name' => 'Cat1'));
 331          $category2 = coursecat::create(array('name' => 'Cat2', 'parent' => $category1->id));
 332          $category3 = coursecat::create(array('name' => 'Cat3', 'parent' => $category1->id, 'visible' => 0));
 333          $category4 = coursecat::create(array('name' => 'Cat4', 'idnumber' => '12', 'parent' => $category1->id));
 334          $category5 = coursecat::create(array('name' => 'Cat5', 'idnumber' => '11', 'parent' => $category1->id, 'visible' => 0));
 335          $category6 = coursecat::create(array('name' => 'Cat6', 'idnumber' => '10', 'parent' => $category1->id));
 336          $category7 = coursecat::create(array('name' => 'Cat0', 'parent' => $category1->id));
 337  
 338          $children = $category1->get_children();
 339          // User does not have the capability to view hidden categories, so the list should be
 340          // 2, 4, 6, 7.
 341          $this->assertEquals(array($category2->id, $category4->id, $category6->id, $category7->id), array_keys($children));
 342          $this->assertEquals(4, $category1->get_children_count());
 343  
 344          $children = $category1->get_children(array('offset' => 2));
 345          $this->assertEquals(array($category6->id, $category7->id), array_keys($children));
 346          $this->assertEquals(4, $category1->get_children_count());
 347  
 348          $children = $category1->get_children(array('limit' => 2));
 349          $this->assertEquals(array($category2->id, $category4->id), array_keys($children));
 350  
 351          $children = $category1->get_children(array('offset' => 1, 'limit' => 2));
 352          $this->assertEquals(array($category4->id, $category6->id), array_keys($children));
 353  
 354          $children = $category1->get_children(array('sort' => array('name' => 1)));
 355          // Must be 7, 2, 4, 6.
 356          $this->assertEquals(array($category7->id, $category2->id, $category4->id, $category6->id), array_keys($children));
 357  
 358          $children = $category1->get_children(array('sort' => array('idnumber' => 1, 'name' => -1)));
 359          // Must be 2, 7, 6, 4.
 360          $this->assertEquals(array($category2->id, $category7->id, $category6->id, $category4->id), array_keys($children));
 361  
 362          // Check that everything is all right after purging the caches.
 363          cache_helper::purge_by_event('changesincoursecat');
 364          $children = $category1->get_children();
 365          $this->assertEquals(array($category2->id, $category4->id, $category6->id, $category7->id), array_keys($children));
 366          $this->assertEquals(4, $category1->get_children_count());
 367      }
 368  
 369      /**
 370       * Test the countall function
 371       */
 372      public function test_count_all() {
 373          global $DB;
 374          // Dont assume there is just one. An add-on might create a category as part of the install.
 375          $numcategories = $DB->count_records('course_categories');
 376          $this->assertEquals($numcategories, coursecat::count_all());
 377          $category1 = coursecat::create(array('name' => 'Cat1'));
 378          $category2 = coursecat::create(array('name' => 'Cat2', 'parent' => $category1->id));
 379          $category3 = coursecat::create(array('name' => 'Cat3', 'parent' => $category2->id, 'visible' => 0));
 380          // Now we've got three more.
 381          $this->assertEquals($numcategories + 3, coursecat::count_all());
 382          cache_helper::purge_by_event('changesincoursecat');
 383          // We should still have 4.
 384          $this->assertEquals($numcategories + 3, coursecat::count_all());
 385      }
 386  
 387      /**
 388       * Test a categories ability to resort courses.
 389       */
 390      public function test_resort_courses() {
 391          $this->resetAfterTest(true);
 392          $generator = $this->getDataGenerator();
 393          $category = $generator->create_category();
 394          $course1 = $generator->create_course(array(
 395              'category' => $category->id,
 396              'idnumber' => '006-01',
 397              'shortname' => 'Biome Study',
 398              'fullname' => '<span lang="ar" class="multilang">'.'دراسة منطقة إحيائية'.'</span><span lang="en" class="multilang">Biome Study</span>',
 399              'timecreated' => '1000000001'
 400          ));
 401          $course2 = $generator->create_course(array(
 402              'category' => $category->id,
 403              'idnumber' => '007-02',
 404              'shortname' => 'Chemistry Revision',
 405              'fullname' => 'Chemistry Revision',
 406              'timecreated' => '1000000002'
 407          ));
 408          $course3 = $generator->create_course(array(
 409              'category' => $category->id,
 410              'idnumber' => '007-03',
 411              'shortname' => 'Swiss Rolls and Sunflowers',
 412              'fullname' => 'Aarkvarks guide to Swiss Rolls and Sunflowers',
 413              'timecreated' => '1000000003'
 414          ));
 415          $course4 = $generator->create_course(array(
 416              'category' => $category->id,
 417              'idnumber' => '006-04',
 418              'shortname' => 'Scratch',
 419              'fullname' => '<a href="test.php">Basic Scratch</a>',
 420              'timecreated' => '1000000004'
 421          ));
 422          $c1 = (int)$course1->id;
 423          $c2 = (int)$course2->id;
 424          $c3 = (int)$course3->id;
 425          $c4 = (int)$course4->id;
 426  
 427          $coursecat = coursecat::get($category->id);
 428          $this->assertTrue($coursecat->resort_courses('idnumber'));
 429          $this->assertSame(array($c1, $c4, $c2, $c3), array_keys($coursecat->get_courses()));
 430  
 431          $this->assertTrue($coursecat->resort_courses('shortname'));
 432          $this->assertSame(array($c1, $c2, $c4, $c3), array_keys($coursecat->get_courses()));
 433  
 434          $this->assertTrue($coursecat->resort_courses('timecreated'));
 435          $this->assertSame(array($c1, $c2, $c3, $c4), array_keys($coursecat->get_courses()));
 436  
 437          try {
 438              // Enable the multilang filter and set it to apply to headings and content.
 439              filter_set_global_state('multilang', TEXTFILTER_ON);
 440              filter_set_applies_to_strings('multilang', true);
 441              $expected = array($c3, $c4, $c1, $c2);
 442          } catch (coding_exception $ex) {
 443              $expected = array($c3, $c4, $c2, $c1);
 444          }
 445          $this->assertTrue($coursecat->resort_courses('fullname'));
 446          $this->assertSame($expected, array_keys($coursecat->get_courses()));
 447      }
 448  
 449      public function test_get_search_courses() {
 450          $cat1 = coursecat::create(array('name' => 'Cat1'));
 451          $cat2 = coursecat::create(array('name' => 'Cat2', 'parent' => $cat1->id));
 452          $c1 = $this->getDataGenerator()->create_course(array('category' => $cat1->id, 'fullname' => 'Test 3', 'summary' => ' ', 'idnumber' => 'ID3'));
 453          $c2 = $this->getDataGenerator()->create_course(array('category' => $cat1->id, 'fullname' => 'Test 1', 'summary' => ' ', 'visible' => 0));
 454          $c3 = $this->getDataGenerator()->create_course(array('category' => $cat1->id, 'fullname' => 'Математика', 'summary' => ' Test '));
 455          $c4 = $this->getDataGenerator()->create_course(array('category' => $cat1->id, 'fullname' => 'Test 4', 'summary' => ' ', 'idnumber' => 'ID4'));
 456  
 457          $c5 = $this->getDataGenerator()->create_course(array('category' => $cat2->id, 'fullname' => 'Test 5', 'summary' => ' '));
 458          $c6 = $this->getDataGenerator()->create_course(array('category' => $cat2->id, 'fullname' => 'Дискретная Математика', 'summary' => ' '));
 459          $c7 = $this->getDataGenerator()->create_course(array('category' => $cat2->id, 'fullname' => 'Test 7', 'summary' => ' ', 'visible' => 0));
 460          $c8 = $this->getDataGenerator()->create_course(array('category' => $cat2->id, 'fullname' => 'Test 8', 'summary' => ' '));
 461  
 462          // Get courses in category 1 (returned visible only because user is not enrolled).
 463          $res = $cat1->get_courses(array('sortorder' => 1));
 464          $this->assertEquals(array($c4->id, $c3->id, $c1->id), array_keys($res)); // Courses are added in reverse order.
 465          $this->assertEquals(3, $cat1->get_courses_count());
 466  
 467          // Get courses in category 1 recursively (returned visible only because user is not enrolled).
 468          $res = $cat1->get_courses(array('recursive' => 1));
 469          $this->assertEquals(array($c4->id, $c3->id, $c1->id, $c8->id, $c6->id, $c5->id), array_keys($res));
 470          $this->assertEquals(6, $cat1->get_courses_count(array('recursive' => 1)));
 471  
 472          // Get courses sorted by fullname.
 473          $res = $cat1->get_courses(array('sort' => array('fullname' => 1)));
 474          $this->assertEquals(array($c1->id, $c4->id, $c3->id), array_keys($res));
 475          $this->assertEquals(3, $cat1->get_courses_count(array('sort' => array('fullname' => 1))));
 476  
 477          // Get courses sorted by fullname recursively.
 478          $res = $cat1->get_courses(array('recursive' => 1, 'sort' => array('fullname' => 1)));
 479          $this->assertEquals(array($c1->id, $c4->id, $c5->id, $c8->id, $c6->id, $c3->id), array_keys($res));
 480          $this->assertEquals(6, $cat1->get_courses_count(array('recursive' => 1, 'sort' => array('fullname' => 1))));
 481  
 482          // Get courses sorted by fullname recursively, use offset and limit.
 483          $res = $cat1->get_courses(array('recursive' => 1, 'offset' => 1, 'limit' => 2, 'sort' => array('fullname' => -1)));
 484          $this->assertEquals(array($c6->id, $c8->id), array_keys($res));
 485          // Offset and limit do not affect get_courses_count().
 486          $this->assertEquals(6, $cat1->get_courses_count(array('recursive' => 1, 'offset' => 1, 'limit' => 2, 'sort' => array('fullname' => 1))));
 487  
 488          // Calling get_courses_count without prior call to get_courses().
 489          $this->assertEquals(3, $cat2->get_courses_count(array('recursive' => 1, 'sort' => array('idnumber' => 1))));
 490  
 491          // Search courses.
 492  
 493          // Search by text.
 494          $res = coursecat::search_courses(array('search' => 'Test'));
 495          $this->assertEquals(array($c4->id, $c3->id, $c1->id, $c8->id, $c5->id), array_keys($res));
 496          $this->assertEquals(5, coursecat::search_courses_count(array('search' => 'Test')));
 497  
 498          // Search by text with specified offset and limit.
 499          $options = array('sort' => array('fullname' => 1), 'offset' => 1, 'limit' => 2);
 500          $res = coursecat::search_courses(array('search' => 'Test'), $options);
 501          $this->assertEquals(array($c4->id, $c5->id), array_keys($res));
 502          $this->assertEquals(5, coursecat::search_courses_count(array('search' => 'Test'), $options));
 503  
 504          // IMPORTANT: the tests below may fail on some databases
 505          // case-insensitive search.
 506          $res = coursecat::search_courses(array('search' => 'test'));
 507          $this->assertEquals(array($c4->id, $c3->id, $c1->id, $c8->id, $c5->id), array_keys($res));
 508          $this->assertEquals(5, coursecat::search_courses_count(array('search' => 'test')));
 509  
 510          // Non-latin language search.
 511          $res = coursecat::search_courses(array('search' => 'Математика'));
 512          $this->assertEquals(array($c3->id, $c6->id), array_keys($res));
 513          $this->assertEquals(2, coursecat::search_courses_count(array('search' => 'Математика'), array()));
 514  
 515          $this->setUser($this->getDataGenerator()->create_user());
 516  
 517          // Add necessary capabilities.
 518          $this->assign_capability('moodle/course:create', CAP_ALLOW, context_coursecat::instance($cat2->id));
 519          // Do another search with restricted capabilities.
 520          $reqcaps = array('moodle/course:create');
 521          $res = coursecat::search_courses(array('search' => 'test'), array(), $reqcaps);
 522          $this->assertEquals(array($c8->id, $c5->id), array_keys($res));
 523          $this->assertEquals(2, coursecat::search_courses_count(array('search' => 'test'), array(), $reqcaps));
 524      }
 525  
 526      public function test_course_contacts() {
 527          global $DB, $CFG;
 528          $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'));
 529          $managerrole = $DB->get_record('role', array('shortname'=>'manager'));
 530          $studentrole = $DB->get_record('role', array('shortname'=>'student'));
 531          $oldcoursecontact = $CFG->coursecontact;
 532  
 533          $CFG->coursecontact = $managerrole->id. ','. $teacherrole->id;
 534  
 535          /*
 536           * User is listed in course contacts for the course if he has one of the
 537           * "course contact" roles ($CFG->coursecontact) AND is enrolled in the course.
 538           * If the user has several roles only the highest is displayed.
 539           */
 540  
 541          // Test case:
 542          //
 543          // == Cat1 (user2 has teacher role)
 544          //   == Cat2
 545          //     -- course21 (user2 is enrolled as manager) | [Expected] Manager: F2 L2
 546          //     -- course22 (user2 is enrolled as student) | [Expected] Teacher: F2 L2
 547          //     == Cat4 (user2 has manager role)
 548          //       -- course41 (user4 is enrolled as teacher, user5 is enrolled as manager) | [Expected] Manager: F5 L5, Teacher: F4 L4
 549          //       -- course42 (user2 is enrolled as teacher) | [Expected] Manager: F2 L2
 550          //   == Cat3 (user3 has manager role)
 551          //     -- course31 (user3 is enrolled as student) | [Expected] Manager: F3 L3
 552          //     -- course32                                | [Expected]
 553          //   -- course11 (user1 is enrolled as teacher)   | [Expected] Teacher: F1 L1
 554          //   -- course12 (user1 has teacher role)         | [Expected]
 555          //                also user4 is enrolled as teacher but enrolment is not active
 556          $category = $course = $enrol = $user = array();
 557          $category[1] = coursecat::create(array('name' => 'Cat1'))->id;
 558          $category[2] = coursecat::create(array('name' => 'Cat2', 'parent' => $category[1]))->id;
 559          $category[3] = coursecat::create(array('name' => 'Cat3', 'parent' => $category[1]))->id;
 560          $category[4] = coursecat::create(array('name' => 'Cat4', 'parent' => $category[2]))->id;
 561          foreach (array(1, 2, 3, 4) as $catid) {
 562              foreach (array(1, 2) as $courseid) {
 563                  $course[$catid][$courseid] = $this->getDataGenerator()->create_course(array('idnumber' => 'id'.$catid.$courseid,
 564                      'category' => $category[$catid]))->id;
 565                  $enrol[$catid][$courseid] = $DB->get_record('enrol', array('courseid'=>$course[$catid][$courseid], 'enrol'=>'manual'), '*', MUST_EXIST);
 566              }
 567          }
 568          foreach (array(1, 2, 3, 4, 5) as $userid) {
 569              $user[$userid] = $this->getDataGenerator()->create_user(array('firstname' => 'F'.$userid, 'lastname' => 'L'.$userid))->id;
 570          }
 571  
 572          $manual = enrol_get_plugin('manual');
 573  
 574          // Nobody is enrolled now and course contacts are empty.
 575          $allcourses = coursecat::get(0)->get_courses(array('recursive' => true, 'coursecontacts' => true, 'sort' => array('idnumber' => 1)));
 576          foreach ($allcourses as $onecourse) {
 577              $this->assertEmpty($onecourse->get_course_contacts());
 578          }
 579  
 580          // Cat1 (user2 has teacher role)
 581          role_assign($teacherrole->id, $user[2], context_coursecat::instance($category[1]));
 582          // course21 (user2 is enrolled as manager)
 583          $manual->enrol_user($enrol[2][1], $user[2], $managerrole->id);
 584          // course22 (user2 is enrolled as student)
 585          $manual->enrol_user($enrol[2][2], $user[2], $studentrole->id);
 586          // Cat4 (user2 has manager role)
 587          role_assign($managerrole->id, $user[2], context_coursecat::instance($category[4]));
 588          // course41 (user4 is enrolled as teacher, user5 is enrolled as manager)
 589          $manual->enrol_user($enrol[4][1], $user[4], $teacherrole->id);
 590          $manual->enrol_user($enrol[4][1], $user[5], $managerrole->id);
 591          // course42 (user2 is enrolled as teacher)
 592          $manual->enrol_user($enrol[4][2], $user[2], $teacherrole->id);
 593          // Cat3 (user3 has manager role)
 594          role_assign($managerrole->id, $user[3], context_coursecat::instance($category[3]));
 595          // course31 (user3 is enrolled as student)
 596          $manual->enrol_user($enrol[3][1], $user[3], $studentrole->id);
 597          // course11 (user1 is enrolled as teacher)
 598          $manual->enrol_user($enrol[1][1], $user[1], $teacherrole->id);
 599          // -- course12 (user1 has teacher role)
 600          //                also user4 is enrolled as teacher but enrolment is not active
 601          role_assign($teacherrole->id, $user[1], context_course::instance($course[1][2]));
 602          $manual->enrol_user($enrol[1][2], $user[4], $teacherrole->id, 0, 0, ENROL_USER_SUSPENDED);
 603  
 604          $allcourses = coursecat::get(0)->get_courses(array('recursive' => true, 'coursecontacts' => true, 'sort' => array('idnumber' => 1)));
 605          // Simplify the list of contacts for each course (similar as renderer would do).
 606          $contacts = array();
 607          foreach (array(1, 2, 3, 4) as $catid) {
 608              foreach (array(1, 2) as $courseid) {
 609                  $tmp = array();
 610                  foreach ($allcourses[$course[$catid][$courseid]]->get_course_contacts() as $contact) {
 611                      $tmp[] = $contact['rolename']. ': '. $contact['username'];
 612                  }
 613                  $contacts[$catid][$courseid] = join(', ', $tmp);
 614              }
 615          }
 616  
 617          // Assert:
 618          //     -- course21 (user2 is enrolled as manager) | Manager: F2 L2
 619          $this->assertSame('Manager: F2 L2', $contacts[2][1]);
 620          //     -- course22 (user2 is enrolled as student) | Teacher: F2 L2
 621          $this->assertSame('Teacher: F2 L2', $contacts[2][2]);
 622          //       -- course41 (user4 is enrolled as teacher, user5 is enrolled as manager) | Manager: F5 L5, Teacher: F4 L4
 623          $this->assertSame('Manager: F5 L5, Teacher: F4 L4', $contacts[4][1]);
 624          //       -- course42 (user2 is enrolled as teacher) | [Expected] Manager: F2 L2
 625          $this->assertSame('Manager: F2 L2', $contacts[4][2]);
 626          //     -- course31 (user3 is enrolled as student) | Manager: F3 L3
 627          $this->assertSame('Manager: F3 L3', $contacts[3][1]);
 628          //     -- course32                                |
 629          $this->assertSame('', $contacts[3][2]);
 630          //   -- course11 (user1 is enrolled as teacher)   | Teacher: F1 L1
 631          $this->assertSame('Teacher: F1 L1', $contacts[1][1]);
 632          //   -- course12 (user1 has teacher role)         |
 633          $this->assertSame('', $contacts[1][2]);
 634  
 635          // Suspend user 4 and make sure he is no longer in contacts of course 1 in category 4.
 636          $manual->enrol_user($enrol[4][1], $user[4], $teacherrole->id, 0, 0, ENROL_USER_SUSPENDED);
 637          $allcourses = coursecat::get(0)->get_courses(array('recursive' => true, 'coursecontacts' => true, 'sort' => array('idnumber' => 1)));
 638          $contacts = $allcourses[$course[4][1]]->get_course_contacts();
 639          $this->assertCount(1, $contacts);
 640          $contact = reset($contacts);
 641          $this->assertEquals('F5 L5', $contact['username']);
 642  
 643          $CFG->coursecontact = $oldcoursecontact;
 644      }
 645  
 646      public function test_overview_files() {
 647          global $CFG;
 648          $this->setAdminUser();
 649          $cat1 = coursecat::create(array('name' => 'Cat1'));
 650  
 651          // Create course c1 with one image file.
 652          $dratid1 = $this->fill_draft_area(array('filename.jpg' => 'Test file contents1'));
 653          $c1 = $this->getDataGenerator()->create_course(array('category' => $cat1->id,
 654              'fullname' => 'Test 1', 'overviewfiles_filemanager' => $dratid1));
 655          // Create course c2 with two image files (only one file will be added because of settings).
 656          $dratid2 = $this->fill_draft_area(array('filename21.jpg' => 'Test file contents21', 'filename22.jpg' => 'Test file contents22'));
 657          $c2 = $this->getDataGenerator()->create_course(array('category' => $cat1->id,
 658              'fullname' => 'Test 2', 'overviewfiles_filemanager' => $dratid2));
 659          // Create course c3 without files.
 660          $c3 = $this->getDataGenerator()->create_course(array('category' => $cat1->id, 'fullname' => 'Test 3'));
 661  
 662          // Change the settings to allow multiple files of any types.
 663          $CFG->courseoverviewfileslimit = 3;
 664          $CFG->courseoverviewfilesext = '*';
 665          // Create course c5 with two image files.
 666          $dratid4 = $this->fill_draft_area(array('filename41.jpg' => 'Test file contents41', 'filename42.jpg' => 'Test file contents42'));
 667          $c4 = $this->getDataGenerator()->create_course(array('category' => $cat1->id,
 668              'fullname' => 'Test 4', 'overviewfiles_filemanager' => $dratid4));
 669          // Create course c6 with non-image file.
 670          $dratid5 = $this->fill_draft_area(array('filename51.zip' => 'Test file contents51'));
 671          $c5 = $this->getDataGenerator()->create_course(array('category' => $cat1->id,
 672              'fullname' => 'Test 5', 'overviewfiles_filemanager' => $dratid5));
 673  
 674          // Reset default settings.
 675          $CFG->courseoverviewfileslimit = 1;
 676          $CFG->courseoverviewfilesext = '.jpg,.gif,.png';
 677  
 678          $courses = $cat1->get_courses();
 679          $this->assertTrue($courses[$c1->id]->has_course_overviewfiles());
 680          $this->assertTrue($courses[$c2->id]->has_course_overviewfiles());
 681          $this->assertFalse($courses[$c3->id]->has_course_overviewfiles());
 682          $this->assertTrue($courses[$c4->id]->has_course_overviewfiles());
 683          $this->assertTrue($courses[$c5->id]->has_course_overviewfiles()); // Does not validate the filetypes.
 684  
 685          $this->assertEquals(1, count($courses[$c1->id]->get_course_overviewfiles()));
 686          $this->assertEquals(1, count($courses[$c2->id]->get_course_overviewfiles()));
 687          $this->assertEquals(0, count($courses[$c3->id]->get_course_overviewfiles()));
 688          $this->assertEquals(1, count($courses[$c4->id]->get_course_overviewfiles()));
 689          $this->assertEquals(0, count($courses[$c5->id]->get_course_overviewfiles())); // Validate the filetypes.
 690  
 691          // Overview files are not allowed, all functions return empty values.
 692          $CFG->courseoverviewfileslimit = 0;
 693  
 694          $this->assertFalse($courses[$c1->id]->has_course_overviewfiles());
 695          $this->assertFalse($courses[$c2->id]->has_course_overviewfiles());
 696          $this->assertFalse($courses[$c3->id]->has_course_overviewfiles());
 697          $this->assertFalse($courses[$c4->id]->has_course_overviewfiles());
 698          $this->assertFalse($courses[$c5->id]->has_course_overviewfiles());
 699  
 700          $this->assertEquals(0, count($courses[$c1->id]->get_course_overviewfiles()));
 701          $this->assertEquals(0, count($courses[$c2->id]->get_course_overviewfiles()));
 702          $this->assertEquals(0, count($courses[$c3->id]->get_course_overviewfiles()));
 703          $this->assertEquals(0, count($courses[$c4->id]->get_course_overviewfiles()));
 704          $this->assertEquals(0, count($courses[$c5->id]->get_course_overviewfiles()));
 705  
 706          // Multiple overview files are allowed but still limited to images.
 707          $CFG->courseoverviewfileslimit = 3;
 708  
 709          $this->assertTrue($courses[$c1->id]->has_course_overviewfiles());
 710          $this->assertTrue($courses[$c2->id]->has_course_overviewfiles());
 711          $this->assertFalse($courses[$c3->id]->has_course_overviewfiles());
 712          $this->assertTrue($courses[$c4->id]->has_course_overviewfiles());
 713          $this->assertTrue($courses[$c5->id]->has_course_overviewfiles()); // Still does not validate the filetypes.
 714  
 715          $this->assertEquals(1, count($courses[$c1->id]->get_course_overviewfiles()));
 716          $this->assertEquals(1, count($courses[$c2->id]->get_course_overviewfiles())); // Only 1 file was actually added.
 717          $this->assertEquals(0, count($courses[$c3->id]->get_course_overviewfiles()));
 718          $this->assertEquals(2, count($courses[$c4->id]->get_course_overviewfiles()));
 719          $this->assertEquals(0, count($courses[$c5->id]->get_course_overviewfiles()));
 720  
 721          // Multiple overview files of any type are allowed.
 722          $CFG->courseoverviewfilesext = '*';
 723  
 724          $this->assertTrue($courses[$c1->id]->has_course_overviewfiles());
 725          $this->assertTrue($courses[$c2->id]->has_course_overviewfiles());
 726          $this->assertFalse($courses[$c3->id]->has_course_overviewfiles());
 727          $this->assertTrue($courses[$c4->id]->has_course_overviewfiles());
 728          $this->assertTrue($courses[$c5->id]->has_course_overviewfiles());
 729  
 730          $this->assertEquals(1, count($courses[$c1->id]->get_course_overviewfiles()));
 731          $this->assertEquals(1, count($courses[$c2->id]->get_course_overviewfiles()));
 732          $this->assertEquals(0, count($courses[$c3->id]->get_course_overviewfiles()));
 733          $this->assertEquals(2, count($courses[$c4->id]->get_course_overviewfiles()));
 734          $this->assertEquals(1, count($courses[$c5->id]->get_course_overviewfiles()));
 735      }
 736  
 737      /**
 738       * Creates a draft area for current user and fills it with fake files
 739       *
 740       * @param array $files array of files that need to be added to filearea, filename => filecontents
 741       * @return int draftid for the filearea
 742       */
 743      protected function fill_draft_area(array $files) {
 744          global $USER;
 745          $usercontext = context_user::instance($USER->id);
 746          $draftid = file_get_unused_draft_itemid();
 747          foreach ($files as $filename => $filecontents) {
 748              // Add actual file there.
 749              $filerecord = array('component' => 'user', 'filearea' => 'draft',
 750                      'contextid' => $usercontext->id, 'itemid' => $draftid,
 751                      'filename' => $filename, 'filepath' => '/');
 752              $fs = get_file_storage();
 753              $fs->create_file_from_string($filerecord, $filecontents);
 754          }
 755          return $draftid;
 756      }
 757  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1