Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 namespace core_course; 18 19 use core_course_category; 20 use core_course_list_element; 21 use course_capability_assignment; 22 23 defined('MOODLE_INTERNAL') || die(); 24 25 global $CFG; 26 require_once($CFG->dirroot.'/course/lib.php'); 27 require_once($CFG->dirroot.'/course/tests/fixtures/course_capability_assignment.php'); 28 29 /** 30 * Course and category management helper class tests. 31 * 32 * @package core_course 33 * @copyright 2013 Sam Hemelryk 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class management_helper_test extends \advanced_testcase { 37 38 /** Category management capability: moodle/category:manage */ 39 const CATEGORY_MANAGE = 'moodle/category:manage'; 40 /** View hidden category capability: moodle/category:viewhiddencategories */ 41 const CATEGORY_VIEWHIDDEN = 'moodle/category:viewhiddencategories'; 42 /** View course capability: moodle/course:visibility */ 43 const COURSE_VIEW = 'moodle/course:visibility'; 44 /** View hidden course capability: moodle/course:viewhiddencourses */ 45 const COURSE_VIEWHIDDEN = 'moodle/course:viewhiddencourses'; 46 47 /** 48 * Returns a user object and its assigned new role. 49 * 50 * @param testing_data_generator $generator 51 * @param $contextid 52 * @return array The user object and the role ID 53 */ 54 protected function get_user_objects(\testing_data_generator $generator, $contextid) { 55 global $USER; 56 57 if (empty($USER->id)) { 58 $user = $generator->create_user(); 59 $this->setUser($user); 60 } 61 $roleid = create_role('Test role', 'testrole', 'Test role description'); 62 if (!is_array($contextid)) { 63 $contextid = array($contextid); 64 } 65 foreach ($contextid as $cid) { 66 $assignid = role_assign($roleid, $user->id, $cid); 67 } 68 return array($user, $roleid); 69 } 70 71 /** 72 * Tests: 73 * - action_category_hide 74 * - action_category_show 75 * 76 * In order to show/hide the user must have moodle/category:manage on the parent context. 77 * In order to view hidden categories the user must have moodle/category:viewhiddencategories 78 */ 79 public function test_action_category_hide_and_show() { 80 global $DB; 81 $this->resetAfterTest(true); 82 83 $generator = $this->getDataGenerator(); 84 $category = $generator->create_category(); 85 $subcategory = $generator->create_category(array('parent' => $category->id)); 86 $course = $generator->create_course(array('category' => $subcategory->id)); 87 $context = $category->get_context(); 88 $subcontext = $subcategory->get_context(); 89 $parentcontext = $context->get_parent_context(); 90 list($user, $roleid) = $this->get_user_objects($generator, $parentcontext->id); 91 92 $this->assertEquals(1, $category->visible); 93 94 $parentassignment = course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $parentcontext->id); 95 course_capability_assignment::allow(self::CATEGORY_VIEWHIDDEN, $roleid, $parentcontext->id); 96 course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $context->id); 97 course_capability_assignment::allow(array(self::COURSE_VIEW, self::COURSE_VIEWHIDDEN), $roleid, $subcontext->id); 98 99 $this->assertTrue(\core_course\management\helper::action_category_hide($category)); 100 $cat = core_course_category::get($category->id); 101 $subcat = core_course_category::get($subcategory->id); 102 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 103 $this->assertEquals(0, $cat->visible); 104 $this->assertEquals(0, $cat->visibleold); 105 $this->assertEquals(0, $subcat->visible); 106 $this->assertEquals(1, $subcat->visibleold); 107 $this->assertEquals(0, $course->visible); 108 $this->assertEquals(1, $course->visibleold); 109 // This doesn't change anything but should succeed still. 110 $this->assertTrue(\core_course\management\helper::action_category_hide($category)); 111 $cat = core_course_category::get($category->id); 112 $subcat = core_course_category::get($subcategory->id); 113 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 114 $this->assertEquals(0, $cat->visible); 115 $this->assertEquals(0, $cat->visibleold); 116 $this->assertEquals(0, $subcat->visible); 117 $this->assertEquals(1, $subcat->visibleold); 118 $this->assertEquals(0, $course->visible); 119 $this->assertEquals(1, $course->visibleold); 120 121 $this->assertTrue(\core_course\management\helper::action_category_show($category)); 122 $cat = core_course_category::get($category->id); 123 $subcat = core_course_category::get($subcategory->id); 124 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 125 $this->assertEquals(1, $cat->visible); 126 $this->assertEquals(1, $cat->visibleold); 127 $this->assertEquals(1, $subcat->visible); 128 $this->assertEquals(1, $subcat->visibleold); 129 $this->assertEquals(1, $course->visible); 130 $this->assertEquals(1, $course->visibleold); 131 // This doesn't change anything but should succeed still. 132 $this->assertTrue(\core_course\management\helper::action_category_show($category)); 133 $cat = core_course_category::get($category->id); 134 $subcat = core_course_category::get($subcategory->id); 135 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 136 $this->assertEquals(1, $cat->visible); 137 $this->assertEquals(1, $cat->visibleold); 138 $this->assertEquals(1, $subcat->visible); 139 $this->assertEquals(1, $subcat->visibleold); 140 $this->assertEquals(1, $course->visible); 141 $this->assertEquals(1, $course->visibleold); 142 143 $parentassignment->assign(CAP_PROHIBIT); 144 145 try { 146 \core_course\management\helper::action_category_hide($category); 147 $this->fail('Expected exception did not occur when trying to hide a category without permission.'); 148 } catch (\moodle_exception $ex) { 149 // The category must still be visible. 150 $cat = core_course_category::get($category->id); 151 $subcat = core_course_category::get($subcategory->id); 152 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 153 $this->assertEquals(1, $cat->visible); 154 $this->assertEquals(1, $cat->visibleold); 155 $this->assertEquals(1, $subcat->visible); 156 $this->assertEquals(1, $subcat->visibleold); 157 $this->assertEquals(1, $course->visible); 158 $this->assertEquals(1, $course->visibleold); 159 } 160 161 // Hide the category so that we can test helper::show. 162 $parentassignment->assign(CAP_ALLOW); 163 \core_course\management\helper::action_category_hide($category); 164 $cat = core_course_category::get($category->id); 165 $subcat = core_course_category::get($subcategory->id); 166 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 167 $this->assertEquals(0, $cat->visible); 168 $this->assertEquals(0, $cat->visibleold); 169 $this->assertEquals(0, $subcat->visible); 170 $this->assertEquals(1, $subcat->visibleold); 171 $this->assertEquals(0, $course->visible); 172 $this->assertEquals(1, $course->visibleold); 173 174 $parentassignment->assign(CAP_PROHIBIT); 175 176 try { 177 \core_course\management\helper::action_category_show($category); 178 $this->fail('Expected exception did not occur when trying to show a category without permission.'); 179 } catch (\moodle_exception $ex) { 180 // The category must still be hidden. 181 $cat = core_course_category::get($category->id); 182 $subcat = core_course_category::get($subcategory->id); 183 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 184 $this->assertEquals(0, $cat->visible); 185 $this->assertEquals(0, $cat->visibleold); 186 $this->assertEquals(0, $subcat->visible); 187 $this->assertEquals(1, $subcat->visibleold); 188 $this->assertEquals(0, $course->visible); 189 $this->assertEquals(1, $course->visibleold); 190 } 191 192 $parentassignment->assign(CAP_PREVENT); 193 // Now we have capability on the category and subcategory but not the parent. 194 // Try to mark the subcategory as visible. This should be possible although its parent is set to hidden. 195 $this->assertTrue(\core_course\management\helper::action_category_show($subcategory)); 196 $cat = core_course_category::get($category->id); 197 $subcat = core_course_category::get($subcategory->id); 198 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 199 $this->assertEquals(0, $cat->visible); 200 $this->assertEquals(0, $cat->visibleold); 201 $this->assertEquals(0, $subcat->visible); 202 $this->assertEquals(1, $subcat->visibleold); 203 $this->assertEquals(0, $course->visible); 204 $this->assertEquals(1, $course->visibleold); 205 206 // Now make the parent visible for the next test. 207 $parentassignment->assign(CAP_ALLOW); 208 $this->assertTrue(\core_course\management\helper::action_category_show($category)); 209 $cat = core_course_category::get($category->id); 210 $subcat = core_course_category::get($subcategory->id); 211 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 212 $this->assertEquals(1, $cat->visible); 213 $this->assertEquals(1, $cat->visibleold); 214 $this->assertEquals(1, $subcat->visible); 215 $this->assertEquals(1, $subcat->visibleold); 216 $this->assertEquals(1, $course->visible); 217 $this->assertEquals(1, $course->visibleold); 218 219 $parentassignment->assign(CAP_PREVENT); 220 // Make sure we can change the subcategory visibility. 221 $this->assertTrue(\core_course\management\helper::action_category_hide($subcategory)); 222 // But not the category visibility. 223 try { 224 \core_course\management\helper::action_category_hide($category); 225 $this->fail('Expected exception did not occur when trying to hide a category without permission.'); 226 } catch (\moodle_exception $ex) { 227 // The category must still be visible. 228 $this->assertEquals(1, core_course_category::get($category->id)->visible); 229 } 230 } 231 232 /** 233 * Tests hiding and showing of a category by its ID. 234 * 235 * This mimics the logic of {@link test_action_category_hide_and_show()} 236 */ 237 public function test_action_category_hide_and_show_by_id() { 238 global $DB; 239 $this->resetAfterTest(true); 240 241 $generator = $this->getDataGenerator(); 242 $category = $generator->create_category(); 243 $subcategory = $generator->create_category(array('parent' => $category->id)); 244 $course = $generator->create_course(array('category' => $subcategory->id)); 245 $context = $category->get_context(); 246 $parentcontext = $context->get_parent_context(); 247 $subcontext = $subcategory->get_context(); 248 list($user, $roleid) = $this->get_user_objects($generator, $parentcontext->id); 249 250 $this->assertEquals(1, $category->visible); 251 252 $parentassignment = course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $parentcontext->id); 253 course_capability_assignment::allow(self::CATEGORY_VIEWHIDDEN, $roleid, $parentcontext->id); 254 course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $context->id); 255 course_capability_assignment::allow(array(self::COURSE_VIEW, self::COURSE_VIEWHIDDEN), $roleid, $subcontext->id); 256 257 $this->assertTrue(\core_course\management\helper::action_category_hide_by_id($category->id)); 258 $cat = core_course_category::get($category->id); 259 $subcat = core_course_category::get($subcategory->id); 260 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 261 $this->assertEquals(0, $cat->visible); 262 $this->assertEquals(0, $cat->visibleold); 263 $this->assertEquals(0, $subcat->visible); 264 $this->assertEquals(1, $subcat->visibleold); 265 $this->assertEquals(0, $course->visible); 266 $this->assertEquals(1, $course->visibleold); 267 // This doesn't change anything but should succeed still. 268 $this->assertTrue(\core_course\management\helper::action_category_hide_by_id($category->id)); 269 $cat = core_course_category::get($category->id); 270 $subcat = core_course_category::get($subcategory->id); 271 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 272 $this->assertEquals(0, $cat->visible); 273 $this->assertEquals(0, $cat->visibleold); 274 $this->assertEquals(0, $subcat->visible); 275 $this->assertEquals(1, $subcat->visibleold); 276 $this->assertEquals(0, $course->visible); 277 $this->assertEquals(1, $course->visibleold); 278 279 $this->assertTrue(\core_course\management\helper::action_category_show_by_id($category->id)); 280 $cat = core_course_category::get($category->id); 281 $subcat = core_course_category::get($subcategory->id); 282 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 283 $this->assertEquals(1, $cat->visible); 284 $this->assertEquals(1, $cat->visibleold); 285 $this->assertEquals(1, $subcat->visible); 286 $this->assertEquals(1, $subcat->visibleold); 287 $this->assertEquals(1, $course->visible); 288 $this->assertEquals(1, $course->visibleold); 289 // This doesn't change anything but should succeed still. 290 $this->assertTrue(\core_course\management\helper::action_category_show_by_id($category->id)); 291 $cat = core_course_category::get($category->id); 292 $subcat = core_course_category::get($subcategory->id); 293 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 294 $this->assertEquals(1, $cat->visible); 295 $this->assertEquals(1, $cat->visibleold); 296 $this->assertEquals(1, $subcat->visible); 297 $this->assertEquals(1, $subcat->visibleold); 298 $this->assertEquals(1, $course->visible); 299 $this->assertEquals(1, $course->visibleold); 300 301 $parentassignment->assign(CAP_PROHIBIT); 302 303 try { 304 \core_course\management\helper::action_category_hide_by_id($category->id); 305 $this->fail('Expected exception did not occur when trying to hide a category without permission.'); 306 } catch (\moodle_exception $ex) { 307 // The category must still be visible. 308 $cat = core_course_category::get($category->id); 309 $subcat = core_course_category::get($subcategory->id); 310 $this->assertEquals(1, $cat->visible); 311 $this->assertEquals(1, $cat->visibleold); 312 $this->assertEquals(1, $subcat->visible); 313 $this->assertEquals(1, $subcat->visibleold); 314 $this->assertEquals(1, $course->visible); 315 $this->assertEquals(1, $course->visibleold); 316 } 317 318 // Hide the category so that we can test helper::show. 319 $parentassignment->assign(CAP_ALLOW); 320 \core_course\management\helper::action_category_hide_by_id($category->id); 321 $cat = core_course_category::get($category->id); 322 $subcat = core_course_category::get($subcategory->id); 323 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 324 $this->assertEquals(0, $cat->visible); 325 $this->assertEquals(0, $cat->visibleold); 326 $this->assertEquals(0, $subcat->visible); 327 $this->assertEquals(1, $subcat->visibleold); 328 $this->assertEquals(0, $course->visible); 329 $this->assertEquals(1, $course->visibleold); 330 331 $parentassignment->assign(CAP_PROHIBIT); 332 333 try { 334 \core_course\management\helper::action_category_show_by_id($category->id); 335 $this->fail('Expected exception did not occur when trying to show a category without permission.'); 336 } catch (\moodle_exception $ex) { 337 // The category must still be hidden. 338 $cat = core_course_category::get($category->id); 339 $subcat = core_course_category::get($subcategory->id); 340 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 341 $this->assertEquals(0, $cat->visible); 342 $this->assertEquals(0, $cat->visibleold); 343 $this->assertEquals(0, $subcat->visible); 344 $this->assertEquals(1, $subcat->visibleold); 345 $this->assertEquals(0, $course->visible); 346 $this->assertEquals(1, $course->visibleold); 347 } 348 349 $parentassignment->assign(CAP_PREVENT); 350 // Now we have capability on the category and subcategory but not the parent. 351 // Try to mark the subcategory as visible. This should be possible although its parent is set to hidden. 352 $this->assertTrue(\core_course\management\helper::action_category_show($subcategory)); 353 $cat = core_course_category::get($category->id); 354 $subcat = core_course_category::get($subcategory->id); 355 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 356 $this->assertEquals(0, $cat->visible); 357 $this->assertEquals(0, $cat->visibleold); 358 $this->assertEquals(0, $subcat->visible); 359 $this->assertEquals(1, $subcat->visibleold); 360 $this->assertEquals(0, $course->visible); 361 $this->assertEquals(1, $course->visibleold); 362 363 // Now make the parent visible for the next test. 364 $parentassignment->assign(CAP_ALLOW); 365 $this->assertTrue(\core_course\management\helper::action_category_show_by_id($category->id)); 366 $cat = core_course_category::get($category->id); 367 $subcat = core_course_category::get($subcategory->id); 368 $course = $DB->get_record('course', array('id' => $course->id), 'id, visible, visibleold', MUST_EXIST); 369 $this->assertEquals(1, $cat->visible); 370 $this->assertEquals(1, $cat->visibleold); 371 $this->assertEquals(1, $subcat->visible); 372 $this->assertEquals(1, $subcat->visibleold); 373 $this->assertEquals(1, $course->visible); 374 $this->assertEquals(1, $course->visibleold); 375 376 $parentassignment->assign(CAP_PREVENT); 377 // Make sure we can change the subcategory visibility. 378 $this->assertTrue(\core_course\management\helper::action_category_hide($subcategory)); 379 // But not the category visibility. 380 try { 381 \core_course\management\helper::action_category_hide_by_id($category->id); 382 $this->fail('Expected exception did not occur when trying to hide a category without permission.'); 383 } catch (\moodle_exception $ex) { 384 // The category must still be visible. 385 $this->assertEquals(1, core_course_category::get($category->id)->visible); 386 } 387 } 388 389 /** 390 * Test moving courses between categories. 391 */ 392 public function test_action_category_move_courses_into() { 393 global $DB, $CFG; 394 $this->resetAfterTest(true); 395 396 $generator = $this->getDataGenerator(); 397 $cat1 = $generator->create_category(); 398 $cat2 = $generator->create_category(); 399 $sub1 = $generator->create_category(array('parent' => $cat1->id)); 400 $sub2 = $generator->create_category(array('parent' => $cat1->id)); 401 $course1 = $generator->create_course(array('category' => $cat1->id)); 402 $course2 = $generator->create_course(array('category' => $sub1->id)); 403 $course3 = $generator->create_course(array('category' => $sub1->id)); 404 $course4 = $generator->create_course(array('category' => $cat2->id)); 405 406 $syscontext = \context_system::instance(); 407 408 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id); 409 410 course_capability_assignment::allow(array(self::CATEGORY_MANAGE, self::CATEGORY_VIEWHIDDEN), $roleid, $syscontext->id); 411 412 // Check they are where we think they are. 413 $this->assertEquals(1, $cat1->get_courses_count()); 414 $this->assertEquals(1, $cat2->get_courses_count()); 415 $this->assertEquals(2, $sub1->get_courses_count()); 416 $this->assertEquals(0, $sub2->get_courses_count()); 417 418 // Move the courses in sub category 1 to sub category 2. 419 $this->assertTrue( 420 \core_course\management\helper::action_category_move_courses_into($sub1, $sub2, array($course2->id, $course3->id)) 421 ); 422 423 $this->assertEquals(1, $cat1->get_courses_count()); 424 $this->assertEquals(1, $cat2->get_courses_count()); 425 $this->assertEquals(0, $sub1->get_courses_count()); 426 $this->assertEquals(2, $sub2->get_courses_count()); 427 428 $courses = $DB->get_records('course', array('category' => $sub2->id), 'id'); 429 $this->assertEquals(array((int)$course2->id, (int)$course3->id), array_keys($courses)); 430 431 // Move the courses in sub category 2 back into to sub category 1. 432 $this->assertTrue( 433 \core_course\management\helper::action_category_move_courses_into($sub2, $sub1, array($course2->id, $course3->id)) 434 ); 435 436 $this->assertEquals(1, $cat1->get_courses_count()); 437 $this->assertEquals(1, $cat2->get_courses_count()); 438 $this->assertEquals(2, $sub1->get_courses_count()); 439 $this->assertEquals(0, $sub2->get_courses_count()); 440 441 $courses = $DB->get_records('course', array('category' => $sub1->id), 'id'); 442 $this->assertEquals(array((int)$course2->id, (int)$course3->id), array_keys($courses)); 443 444 // Try moving just one course. 445 $this->assertTrue( 446 \core_course\management\helper::action_category_move_courses_into($cat2, $sub2, array($course4->id)) 447 ); 448 $this->assertEquals(1, $cat1->get_courses_count()); 449 $this->assertEquals(0, $cat2->get_courses_count()); 450 $this->assertEquals(2, $sub1->get_courses_count()); 451 $this->assertEquals(1, $sub2->get_courses_count()); 452 $courses = $DB->get_records('course', array('category' => $sub2->id), 'id'); 453 $this->assertEquals(array((int)$course4->id), array_keys($courses)); 454 455 // Try moving a course from a category its not part of. 456 try { 457 \core_course\management\helper::action_category_move_courses_into($cat2, $sub2, array($course4->id)); 458 $this->fail('Moved a course from a category it wasn\'t within'); 459 } catch (\moodle_exception $exception) { 460 // Check that everything is as it was. 461 $this->assertEquals(1, $cat1->get_courses_count()); 462 $this->assertEquals(0, $cat2->get_courses_count()); 463 $this->assertEquals(2, $sub1->get_courses_count()); 464 $this->assertEquals(1, $sub2->get_courses_count()); 465 } 466 467 // Now try that again with two courses, one of which is in the right place. 468 try { 469 \core_course\management\helper::action_category_move_courses_into($cat2, $sub2, array($course4->id, $course1->id)); 470 $this->fail('Moved a course from a category it wasn\'t within'); 471 } catch (\moodle_exception $exception) { 472 // Check that everything is as it was. Nothing should have been moved. 473 $this->assertEquals(1, $cat1->get_courses_count()); 474 $this->assertEquals(0, $cat2->get_courses_count()); 475 $this->assertEquals(2, $sub1->get_courses_count()); 476 $this->assertEquals(1, $sub2->get_courses_count()); 477 } 478 479 // Current state: 480 // * $cat1 => $course1 481 // * $sub1 => $course2, $course3 482 // * $sub2 => $course4 483 // * $cat2 =>. 484 485 // Prevent the user from being able to move into $sub2. 486 $sub2cap = course_capability_assignment::prohibit(self::CATEGORY_MANAGE, $roleid, $sub2->get_context()->id); 487 $sub2 = core_course_category::get($sub2->id); 488 // Suppress debugging messages for a moment. 489 $olddebug = $CFG->debug; 490 $CFG->debug = 0; 491 492 // Try to move a course into sub2. This shouldn't be possible because you should always be able to undo what you've done. 493 // Try moving just one course. 494 try { 495 \core_course\management\helper::action_category_move_courses_into($sub1, $sub2, array($course2->id)); 496 $this->fail('Invalid move of course between categories, action can\'t be undone.'); 497 } catch (\moodle_exception $ex) { 498 $this->assertEquals(get_string('cannotmovecourses', 'error'), $ex->getMessage()); 499 } 500 // Nothing should have changed. 501 $this->assertEquals(1, $cat1->get_courses_count()); 502 $this->assertEquals(0, $cat2->get_courses_count()); 503 $this->assertEquals(2, $sub1->get_courses_count()); 504 $this->assertEquals(1, $sub2->get_courses_count()); 505 506 // Now try moving a course out of sub2. Again should not be possible. 507 // Try to move a course into sub2. This shouldn't be possible because you should always be able to undo what you've done. 508 // Try moving just one course. 509 try { 510 \core_course\management\helper::action_category_move_courses_into($sub2, $cat2, array($course4->id)); 511 $this->fail('Invalid move of course between categories, action can\'t be undone.'); 512 } catch (\moodle_exception $ex) { 513 $this->assertEquals(get_string('cannotmovecourses', 'error'), $ex->getMessage()); 514 } 515 // Nothing should have changed. 516 $this->assertEquals(1, $cat1->get_courses_count()); 517 $this->assertEquals(0, $cat2->get_courses_count()); 518 $this->assertEquals(2, $sub1->get_courses_count()); 519 $this->assertEquals(1, $sub2->get_courses_count()); 520 521 $CFG->debug = $olddebug; 522 } 523 524 /** 525 * Test moving a categories up and down. 526 */ 527 public function test_action_category_movedown_and_moveup() { 528 global $DB; 529 $this->resetAfterTest(true); 530 531 $generator = $this->getDataGenerator(); 532 $parent = $generator->create_category(); 533 $cat1 = $generator->create_category(array('parent' => $parent->id, 'name' => 'One')); 534 $cat2 = $generator->create_category(array('parent' => $parent->id, 'name' => 'Two')); 535 $cat3 = $generator->create_category(array('parent' => $parent->id, 'name' => 'Three')); 536 537 $syscontext = \context_system::instance(); 538 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id); 539 course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $syscontext->id); 540 541 // Check everything is where we expect it to be. 542 $this->assertEquals( 543 array('One', 'Two', 'Three'), 544 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 545 ); 546 547 // Move the top category down one. 548 $this->assertTrue(\core_course\management\helper::action_category_change_sortorder_down_one($cat1)); 549 // Reload out objects. 550 $cat1 = core_course_category::get($cat1->id); 551 $cat2 = core_course_category::get($cat2->id); 552 $cat3 = core_course_category::get($cat3->id); 553 // Verify that caches were cleared. 554 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat1->id)), $cat1->sortorder); 555 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat2->id)), $cat2->sortorder); 556 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat3->id)), $cat3->sortorder); 557 // Verify sorting. 558 $this->assertEquals( 559 array('Two', 'One', 'Three'), 560 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 561 ); 562 563 // Move the bottom category up one. 564 $this->assertTrue(\core_course\management\helper::action_category_change_sortorder_up_one($cat3)); 565 // Reload out objects. 566 $cat1 = core_course_category::get($cat1->id); 567 $cat2 = core_course_category::get($cat2->id); 568 $cat3 = core_course_category::get($cat3->id); 569 // Verify that caches were cleared. 570 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat1->id)), $cat1->sortorder); 571 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat2->id)), $cat2->sortorder); 572 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat3->id)), $cat3->sortorder); 573 // Verify sorting. 574 $this->assertEquals( 575 array('Two', 'Three', 'One'), 576 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 577 ); 578 579 // Move the top category down one. 580 $this->assertTrue(\core_course\management\helper::action_category_change_sortorder_down_one_by_id($cat2->id)); 581 $this->assertEquals( 582 array('Three', 'Two', 'One'), 583 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 584 ); 585 586 // Move the top category down one. 587 $this->assertTrue(\core_course\management\helper::action_category_change_sortorder_up_one_by_id($cat1->id)); 588 $this->assertEquals( 589 array('Three', 'One', 'Two'), 590 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 591 ); 592 593 // Reload out objects the above actions will have caused the objects to become stale. 594 $cat1 = core_course_category::get($cat1->id); 595 $cat2 = core_course_category::get($cat2->id); 596 $cat3 = core_course_category::get($cat3->id); 597 // Verify that caches were cleared. 598 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat1->id)), $cat1->sortorder); 599 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat2->id)), $cat2->sortorder); 600 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat3->id)), $cat3->sortorder); 601 // Verify sorting. 602 603 // Test moving the top category up one. Nothing should change but it should return false. 604 $this->assertFalse(\core_course\management\helper::action_category_change_sortorder_up_one($cat3)); 605 // Reload out objects. 606 $cat1 = core_course_category::get($cat1->id); 607 $cat2 = core_course_category::get($cat2->id); 608 $cat3 = core_course_category::get($cat3->id); 609 // Verify that caches were cleared. 610 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat1->id)), $cat1->sortorder); 611 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat2->id)), $cat2->sortorder); 612 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat3->id)), $cat3->sortorder); 613 // Verify sorting. 614 $this->assertEquals( 615 array('Three', 'One', 'Two'), 616 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 617 ); 618 619 // Test moving the bottom category down one. Nothing should change but it should return false. 620 $this->assertFalse(\core_course\management\helper::action_category_change_sortorder_down_one($cat2)); 621 // Reload out objects. 622 $cat1 = core_course_category::get($cat1->id); 623 $cat2 = core_course_category::get($cat2->id); 624 $cat3 = core_course_category::get($cat3->id); 625 // Verify that caches were cleared. 626 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat1->id)), $cat1->sortorder); 627 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat2->id)), $cat2->sortorder); 628 $this->assertEquals($DB->get_field('course_categories', 'sortorder', array('id' => $cat3->id)), $cat3->sortorder); 629 // Verify sorting. 630 $this->assertEquals( 631 array('Three', 'One', 'Two'), 632 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 633 ); 634 635 // Prevent moving on the parent. 636 course_capability_assignment::prevent(self::CATEGORY_MANAGE, $roleid, $parent->get_context()->id); 637 try { 638 \core_course\management\helper::action_category_change_sortorder_up_one($cat1); 639 } catch (\moodle_exception $exception) { 640 // Check everything is still where it should be. 641 $this->assertEquals( 642 array('Three', 'One', 'Two'), 643 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 644 ); 645 } 646 try { 647 \core_course\management\helper::action_category_change_sortorder_down_one($cat3); 648 } catch (\moodle_exception $exception) { 649 // Check everything is still where it should be. 650 $this->assertEquals( 651 array('Three', 'One', 'Two'), 652 array_keys($DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder', 'name')) 653 ); 654 } 655 } 656 657 /** 658 * Test resorting of courses within a category. 659 * 660 * \core_course\management\helper::action_category_resort_courses 661 */ 662 public function test_action_category_resort_courses() { 663 global $DB; 664 $this->resetAfterTest(true); 665 666 $generator = $this->getDataGenerator(); 667 $category = $generator->create_category(); 668 $course1 = $generator->create_course(array('category' => $category->id, 'fullname' => 'Experimental Chemistry', 669 'shortname' => 'Course A', 'idnumber' => '10001')); 670 $course2 = $generator->create_course(array('category' => $category->id, 'fullname' => 'Learn to program: Jade', 671 'shortname' => 'Beginning Jade', 'idnumber' => '10003')); 672 $course3 = $generator->create_course(array('category' => $category->id, 'fullname' => 'Advanced algebra', 673 'shortname' => 'Advanced algebra', 'idnumber' => '10002')); 674 $syscontext = \context_system::instance(); 675 676 // Update category object from DB so the course count is correct. 677 $category = core_course_category::get($category->id); 678 679 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id); 680 $caps = course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $syscontext->id); 681 682 // Check that sort order in the DB matches what we've got in the cache. 683 $courses = $category->get_courses(); 684 $this->assertIsArray($courses); 685 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 686 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 687 688 // Resort by fullname. 689 \core_course\management\helper::action_category_resort_courses($category, 'fullname'); 690 $courses = $category->get_courses(); 691 $this->assertIsArray($courses); 692 $this->assertEquals(array($course3->id, $course1->id, $course2->id), array_keys($courses)); 693 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 694 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 695 696 // Resort by shortname. 697 \core_course\management\helper::action_category_resort_courses($category, 'shortname'); 698 $courses = $category->get_courses(); 699 $this->assertIsArray($courses); 700 $this->assertEquals(array($course3->id, $course2->id, $course1->id), array_keys($courses)); 701 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 702 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 703 704 // Resort by idnumber. 705 \core_course\management\helper::action_category_resort_courses($category, 'idnumber'); 706 $courses = $category->get_courses(); 707 $this->assertIsArray($courses); 708 $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses)); 709 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 710 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 711 712 // Try with a field that cannot be sorted on. 713 try { 714 \core_course\management\helper::action_category_resort_courses($category, 'category'); 715 $this->fail('Category courses resorted by invalid sort field.'); 716 } catch (\coding_exception $exception) { 717 // Test things are as they were before. 718 $courses = $category->get_courses(); 719 $this->assertIsArray($courses); 720 $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses)); 721 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 722 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 723 } 724 725 // Try with a completely bogus field. 726 try { 727 \core_course\management\helper::action_category_resort_courses($category, 'monkeys'); 728 $this->fail('Category courses resorted by completely ridiculous field.'); 729 } catch (\coding_exception $exception) { 730 // Test things are as they were before. 731 $courses = $category->get_courses(); 732 $this->assertIsArray($courses); 733 $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses)); 734 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 735 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 736 } 737 738 // Prohibit resorting. 739 $caps->assign(CAP_PROHIBIT); 740 // Refresh our coursecat object. 741 $category = core_course_category::get($category->id); 742 743 // We should no longer have permission to do this. Test it out! 744 try { 745 \core_course\management\helper::action_category_resort_courses($category, 'shortname'); 746 $this->fail('Courses sorted without having the required permission.'); 747 } catch (\moodle_exception $exception) { 748 // Check its the right exception. 749 $this->assertEquals('core_course_category::can_resort', $exception->debuginfo); 750 // Test things are as they were before. 751 $courses = $category->get_courses(); 752 $this->assertIsArray($courses); 753 $this->assertEquals(array($course1->id, $course3->id, $course2->id), array_keys($courses)); 754 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder'); 755 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 756 } 757 } 758 759 /** 760 * Tests resorting sub categories of a course. 761 * 762 * \core_course\management\helper::action_category_resort_courses 763 */ 764 public function test_action_category_resort_subcategories() { 765 global $DB; 766 $this->resetAfterTest(true); 767 768 $generator = $this->getDataGenerator(); 769 $parent = $generator->create_category(); 770 $cat1 = $generator->create_category(array('parent' => $parent->id, 'name' => 'School of Science', 'idnumber' => '10001')); 771 $cat2 = $generator->create_category(array('parent' => $parent->id, 'name' => 'School of Commerce', 'idnumber' => '10003')); 772 $cat3 = $generator->create_category(array('parent' => $parent->id, 'name' => 'School of Arts', 'idnumber' => '10002')); 773 774 $syscontext = \context_system::instance(); 775 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id); 776 $caps = course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $syscontext->id); 777 778 $categories = $parent->get_children(); 779 $this->assertIsArray($categories); 780 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder'); 781 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 782 783 // Test sorting by name. 784 \core_course\management\helper::action_category_resort_subcategories($parent, 'name'); 785 $categories = $parent->get_children(); 786 $this->assertIsArray($categories); 787 $this->assertEquals(array($cat3->id, $cat2->id, $cat1->id), array_keys($categories)); 788 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder'); 789 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 790 791 // Test sorting by idnumber. 792 \core_course\management\helper::action_category_resort_subcategories($parent, 'idnumber'); 793 $categories = $parent->get_children(); 794 $this->assertIsArray($categories); 795 $this->assertEquals(array($cat1->id, $cat3->id, $cat2->id), array_keys($categories)); 796 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder'); 797 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 798 799 // Try with an invalid field. 800 try { 801 \core_course\management\helper::action_category_resort_subcategories($parent, 'summary'); 802 $this->fail('Categories resorted by invalid field.'); 803 } catch (\coding_exception $exception) { 804 // Check that nothing was changed. 805 $categories = $parent->get_children(); 806 $this->assertIsArray($categories); 807 $this->assertEquals(array($cat1->id, $cat3->id, $cat2->id), array_keys($categories)); 808 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder'); 809 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 810 } 811 812 // Try with a completely bogus field. 813 try { 814 \core_course\management\helper::action_category_resort_subcategories($parent, 'monkeys'); 815 $this->fail('Categories resorted by completely bogus field.'); 816 } catch (\coding_exception $exception) { 817 // Check that nothing was changed. 818 $categories = $parent->get_children(); 819 $this->assertIsArray($categories); 820 $this->assertEquals(array($cat1->id, $cat3->id, $cat2->id), array_keys($categories)); 821 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder'); 822 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 823 } 824 825 // Test resorting the top level category (puke). 826 $topcat = core_course_category::get(0); 827 \core_course\management\helper::action_category_resort_subcategories($topcat, 'name'); 828 $categories = $topcat->get_children(); 829 $this->assertIsArray($categories); 830 $dbcategories = $DB->get_records('course_categories', array('parent' => '0'), 'sortorder'); 831 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 832 833 // Prohibit resorting. 834 $caps->assign(CAP_PROHIBIT); 835 // Refresh our coursecat object. 836 $parent = core_course_category::get($parent->id); 837 838 // We should no longer have permission to do this. Test it out! 839 try { 840 \core_course\management\helper::action_category_resort_subcategories($parent, 'idnumber'); 841 $this->fail('Categories sorted without having the required permission.'); 842 } catch (\moodle_exception $exception) { 843 // Check its the right exception. 844 $this->assertEquals('core_course_category::can_resort', $exception->debuginfo); 845 // Test things are as they were before. 846 $categories = $parent->get_children(); 847 $this->assertIsArray($categories); 848 $this->assertEquals(array($cat1->id, $cat3->id, $cat2->id), array_keys($categories)); 849 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id), 'sortorder'); 850 $this->assertEquals(array_keys($dbcategories), array_keys($categories)); 851 } 852 } 853 854 /** 855 * Test hiding and showing of a course. 856 * 857 * @see \core_course\management\helper::action_course_hide 858 * @see \core_course\management\helper::action_course_show 859 */ 860 public function test_action_course_hide_show() { 861 $this->resetAfterTest(true); 862 863 $generator = $this->getDataGenerator(); 864 $category = $generator->create_category(); 865 $course = $generator->create_course(); 866 867 $coursecontext = \context_course::instance($course->id); 868 869 list($user, $roleid) = $this->get_user_objects($generator, $coursecontext->id); 870 $caps = array(self::COURSE_VIEW, self::COURSE_VIEWHIDDEN); 871 $assignment = course_capability_assignment::allow($caps, $roleid, $coursecontext->id); 872 873 $course = new core_course_list_element(get_course($course->id)); 874 875 // Check it is set to what we think it is. 876 $this->assertEquals('1', $course->visible); 877 $this->assertEquals('1', $course->visibleold); 878 879 // Test hiding the course. 880 $this->assertTrue(\core_course\management\helper::action_course_hide($course)); 881 // Refresh the course. 882 $course = new core_course_list_element(get_course($course->id)); 883 $this->assertEquals('0', $course->visible); 884 $this->assertEquals('0', $course->visibleold); 885 886 // Test hiding the course again. 887 $this->assertTrue(\core_course\management\helper::action_course_hide($course)); 888 // Refresh the course. 889 $course = new core_course_list_element(get_course($course->id)); 890 $this->assertEquals('0', $course->visible); 891 $this->assertEquals('0', $course->visibleold); 892 893 // Test showing the course. 894 $this->assertTrue(\core_course\management\helper::action_course_show($course)); 895 // Refresh the course. 896 $course = new core_course_list_element(get_course($course->id)); 897 $this->assertEquals('1', $course->visible); 898 $this->assertEquals('1', $course->visibleold); 899 900 // Test showing the course again. Shouldn't change anything. 901 $this->assertTrue(\core_course\management\helper::action_course_show($course)); 902 // Refresh the course. 903 $course = new core_course_list_element(get_course($course->id)); 904 $this->assertEquals('1', $course->visible); 905 $this->assertEquals('1', $course->visibleold); 906 907 // Revoke the permissions. 908 $assignment->revoke(); 909 $course = new core_course_list_element(get_course($course->id)); 910 911 try { 912 \core_course\management\helper::action_course_show($course); 913 } catch (\moodle_exception $exception) { 914 $this->assertEquals('core_course_list_element::can_change_visbility', $exception->debuginfo); 915 } 916 } 917 918 /** 919 * Test hiding and showing of a course. 920 * 921 * @see \core_course\management\helper::action_course_hide_by_record 922 * @see \core_course\management\helper::action_course_show_by_record 923 */ 924 public function test_action_course_hide_show_by_record() { 925 $this->resetAfterTest(true); 926 927 $generator = $this->getDataGenerator(); 928 $category = $generator->create_category(); 929 $course = $generator->create_course(); 930 931 $coursecontext = \context_course::instance($course->id); 932 933 list($user, $roleid) = $this->get_user_objects($generator, $coursecontext->id); 934 $caps = array(self::COURSE_VIEW, self::COURSE_VIEWHIDDEN); 935 $assignment = course_capability_assignment::allow($caps, $roleid, $coursecontext->id); 936 937 $course = get_course($course->id); 938 939 // Check it is set to what we think it is. 940 $this->assertEquals('1', $course->visible); 941 $this->assertEquals('1', $course->visibleold); 942 943 // Test hiding the course. 944 $this->assertTrue(\core_course\management\helper::action_course_hide_by_record($course)); 945 // Refresh the course. 946 $course = get_course($course->id); 947 $this->assertEquals('0', $course->visible); 948 $this->assertEquals('0', $course->visibleold); 949 950 // Test hiding the course again. Shouldn't change anything. 951 $this->assertTrue(\core_course\management\helper::action_course_hide_by_record($course)); 952 // Refresh the course. 953 $course = get_course($course->id); 954 $this->assertEquals('0', $course->visible); 955 $this->assertEquals('0', $course->visibleold); 956 957 // Test showing the course. 958 $this->assertTrue(\core_course\management\helper::action_course_show_by_record($course)); 959 // Refresh the course. 960 $course = get_course($course->id); 961 $this->assertEquals('1', $course->visible); 962 $this->assertEquals('1', $course->visibleold); 963 964 // Test showing the course again. Shouldn't change anything. 965 $this->assertTrue(\core_course\management\helper::action_course_show_by_record($course)); 966 // Refresh the course. 967 $course = get_course($course->id); 968 $this->assertEquals('1', $course->visible); 969 $this->assertEquals('1', $course->visibleold); 970 971 // Revoke the permissions. 972 $assignment->revoke(); 973 $course = get_course($course->id); 974 975 try { 976 \core_course\management\helper::action_course_show_by_record($course); 977 } catch (\moodle_exception $exception) { 978 $this->assertEquals('core_course_list_element::can_change_visbility', $exception->debuginfo); 979 } 980 } 981 982 /** 983 * Tests moving a course up and down by one. 984 */ 985 public function test_action_course_movedown_and_moveup() { 986 global $DB; 987 988 $this->resetAfterTest(true); 989 990 $generator = $this->getDataGenerator(); 991 $category = $generator->create_category(); 992 $course3 = $generator->create_course(array('category' => $category->id)); 993 $course2 = $generator->create_course(array('category' => $category->id)); 994 $course1 = $generator->create_course(array('category' => $category->id)); 995 $context = $category->get_context(); 996 997 // Update category object from DB so the course count is correct. 998 $category = core_course_category::get($category->id); 999 1000 list($user, $roleid) = $this->get_user_objects($generator, $context->id); 1001 $caps = course_capability_assignment::allow(self::CATEGORY_MANAGE, $roleid, $context->id); 1002 1003 $courses = $category->get_courses(); 1004 $this->assertIsArray($courses); 1005 $this->assertEquals(array($course1->id, $course2->id, $course3->id), array_keys($courses)); 1006 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1007 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1008 1009 // Move a course down. 1010 $this->assertTrue( 1011 \core_course\management\helper::action_course_change_sortorder_down_one( 1012 new core_course_list_element(get_course($course1->id)), $category) 1013 ); 1014 $courses = $category->get_courses(); 1015 $this->assertIsArray($courses); 1016 $this->assertEquals(array($course2->id, $course1->id, $course3->id), array_keys($courses)); 1017 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1018 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1019 1020 // Move a course up. 1021 $this->assertTrue( 1022 \core_course\management\helper::action_course_change_sortorder_up_one( 1023 new core_course_list_element(get_course($course3->id)), $category) 1024 ); 1025 $courses = $category->get_courses(); 1026 $this->assertIsArray($courses); 1027 $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses)); 1028 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1029 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1030 1031 // Move a course down by record. 1032 $this->assertTrue( 1033 \core_course\management\helper::action_course_change_sortorder_down_one_by_record(get_course($course2->id), $category) 1034 ); 1035 $courses = $category->get_courses(); 1036 $this->assertIsArray($courses); 1037 $this->assertEquals(array($course3->id, $course2->id, $course1->id), array_keys($courses)); 1038 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1039 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1040 1041 // Move a course up by record. 1042 $this->assertTrue( 1043 \core_course\management\helper::action_course_change_sortorder_up_one_by_record(get_course($course2->id), $category) 1044 ); 1045 $courses = $category->get_courses(); 1046 $this->assertIsArray($courses); 1047 $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses)); 1048 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1049 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1050 1051 // Try move the bottom course down. This should return false and nothing changes. 1052 $this->assertFalse( 1053 \core_course\management\helper::action_course_change_sortorder_down_one( 1054 new core_course_list_element(get_course($course1->id)), $category) 1055 ); 1056 $courses = $category->get_courses(); 1057 $this->assertIsArray($courses); 1058 $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses)); 1059 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1060 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1061 1062 // Try move the top course up. This should return false and nothing changes. 1063 $this->assertFalse( 1064 \core_course\management\helper::action_course_change_sortorder_up_one( 1065 new core_course_list_element(get_course($course2->id)), $category) 1066 ); 1067 $courses = $category->get_courses(); 1068 $this->assertIsArray($courses); 1069 $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses)); 1070 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1071 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1072 1073 // Prohibit the ability to move. 1074 $caps->assign(CAP_PROHIBIT); 1075 // Reload the category. 1076 $category = core_course_category::get($category->id); 1077 1078 try { 1079 \core_course\management\helper::action_course_change_sortorder_down_one( 1080 new core_course_list_element(get_course($course2->id)), $category); 1081 $this->fail('Course moved without having the required permissions.'); 1082 } catch (\moodle_exception $exception) { 1083 // Check nothing has changed. 1084 $courses = $category->get_courses(); 1085 $this->assertIsArray($courses); 1086 $this->assertEquals(array($course2->id, $course3->id, $course1->id), array_keys($courses)); 1087 $dbcourses = $DB->get_records('course', array('category' => $category->id), 'sortorder', 'id'); 1088 $this->assertEquals(array_keys($dbcourses), array_keys($courses)); 1089 } 1090 } 1091 1092 /** 1093 * Tests the fetching of actions for a category. 1094 */ 1095 public function test_get_category_listitem_actions() { 1096 global $PAGE; 1097 $this->resetAfterTest(true); 1098 1099 $PAGE->set_url(new \moodle_url('/course/management.php')); 1100 1101 $generator = $this->getDataGenerator(); 1102 $category = $generator->create_category(); 1103 $context = \context_system::instance(); 1104 list($user, $roleid) = $this->get_user_objects($generator, $context->id); 1105 course_capability_assignment::allow(array( 1106 self::CATEGORY_MANAGE, 1107 self::CATEGORY_VIEWHIDDEN, 1108 'moodle/role:assign', 1109 'moodle/cohort:view', 1110 'moodle/filter:manage' 1111 ), $roleid, $context->id); 1112 1113 $actions = \core_course\management\helper::get_category_listitem_actions($category); 1114 $this->assertIsArray($actions); 1115 $this->assertArrayHasKey('edit', $actions); 1116 $this->assertArrayHasKey('hide', $actions); 1117 $this->assertArrayHasKey('show', $actions); 1118 $this->assertArrayHasKey('moveup', $actions); 1119 $this->assertArrayHasKey('movedown', $actions); 1120 $this->assertArrayHasKey('delete', $actions); 1121 $this->assertArrayHasKey('assignroles', $actions); 1122 $this->assertArrayHasKey('permissions', $actions); 1123 $this->assertArrayHasKey('cohorts', $actions); 1124 $this->assertArrayHasKey('filters', $actions); 1125 } 1126 1127 /** 1128 * Tests fetching the course actions. 1129 */ 1130 public function test_get_course_detail_actions() { 1131 $this->resetAfterTest(true); 1132 1133 $generator = $this->getDataGenerator(); 1134 $category = $generator->create_category(); 1135 $course = $generator->create_course(); 1136 $context = \context_system::instance(); 1137 list($user, $roleid) = $this->get_user_objects($generator, $context->id); 1138 $generator->enrol_user($user->id, $course->id, $roleid); 1139 course_capability_assignment::allow(array( 1140 self::COURSE_VIEW, 1141 self::COURSE_VIEWHIDDEN, 1142 'moodle/course:update', 1143 'moodle/course:enrolreview', 1144 'moodle/course:delete', 1145 'moodle/backup:backupcourse', 1146 'moodle/restore:restorecourse' 1147 ), $roleid, $context->id); 1148 1149 $actions = \core_course\management\helper::get_course_detail_actions(new core_course_list_element($course)); 1150 $this->assertIsArray($actions); 1151 $this->assertArrayHasKey('view', $actions); 1152 $this->assertArrayHasKey('edit', $actions); 1153 $this->assertArrayHasKey('enrolledusers', $actions); 1154 $this->assertArrayHasKey('delete', $actions); 1155 $this->assertArrayHasKey('hide', $actions); 1156 $this->assertArrayHasKey('backup', $actions); 1157 $this->assertArrayHasKey('restore', $actions); 1158 } 1159 1160 /** 1161 * Test fetching course details. 1162 */ 1163 public function test_get_course_detail_array() { 1164 $this->resetAfterTest(true); 1165 1166 $generator = $this->getDataGenerator(); 1167 $category = $generator->create_category(); 1168 $course = $generator->create_course(); 1169 $context = \context_system::instance(); 1170 list($user, $roleid) = $this->get_user_objects($generator, $context->id); 1171 $generator->enrol_user($user->id, $course->id, $roleid); 1172 course_capability_assignment::allow(array( 1173 self::COURSE_VIEW, 1174 self::COURSE_VIEWHIDDEN, 1175 'moodle/course:update', 1176 'moodle/course:enrolreview', 1177 'moodle/course:delete', 1178 'moodle/backup:backupcourse', 1179 'moodle/restore:restorecourse', 1180 'moodle/site:accessallgroups' 1181 ), $roleid, $context->id); 1182 1183 $details = \core_course\management\helper::get_course_detail_array(new core_course_list_element($course)); 1184 $this->assertIsArray($details); 1185 $this->assertArrayHasKey('format', $details); 1186 $this->assertArrayHasKey('fullname', $details); 1187 $this->assertArrayHasKey('shortname', $details); 1188 $this->assertArrayHasKey('idnumber', $details); 1189 $this->assertArrayHasKey('category', $details); 1190 $this->assertArrayHasKey('groupings', $details); 1191 $this->assertArrayHasKey('groups', $details); 1192 $this->assertArrayHasKey('roleassignments', $details); 1193 $this->assertArrayHasKey('enrolmentmethods', $details); 1194 $this->assertArrayHasKey('sections', $details); 1195 $this->assertArrayHasKey('modulesused', $details); 1196 } 1197 1198 public function test_move_courses_into_category() { 1199 global $DB, $CFG; 1200 $this->resetAfterTest(true); 1201 1202 $generator = $this->getDataGenerator(); 1203 $cat1 = $generator->create_category(); 1204 $cat2 = $generator->create_category(); 1205 $sub1 = $generator->create_category(array('parent' => $cat1->id)); 1206 $sub2 = $generator->create_category(array('parent' => $cat1->id)); 1207 $course1 = $generator->create_course(array('category' => $cat1->id)); 1208 $course2 = $generator->create_course(array('category' => $sub1->id)); 1209 $course3 = $generator->create_course(array('category' => $sub1->id)); 1210 $course4 = $generator->create_course(array('category' => $cat2->id)); 1211 1212 $syscontext = \context_system::instance(); 1213 1214 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id); 1215 1216 course_capability_assignment::allow(array(self::CATEGORY_MANAGE, self::CATEGORY_VIEWHIDDEN), $roleid, $syscontext->id); 1217 1218 // Check they are where we think they are. 1219 $this->assertEquals(1, $cat1->get_courses_count()); 1220 $this->assertEquals(1, $cat2->get_courses_count()); 1221 $this->assertEquals(2, $sub1->get_courses_count()); 1222 $this->assertEquals(0, $sub2->get_courses_count()); 1223 1224 // Move the courses in sub category 1 to sub category 2. 1225 $this->assertTrue( 1226 \core_course\management\helper::move_courses_into_category($sub2->id, array($course2->id, $course3->id)) 1227 ); 1228 1229 $this->assertEquals(1, $cat1->get_courses_count()); 1230 $this->assertEquals(1, $cat2->get_courses_count()); 1231 $this->assertEquals(0, $sub1->get_courses_count()); 1232 $this->assertEquals(2, $sub2->get_courses_count()); 1233 1234 $courses = $DB->get_records('course', array('category' => $sub2->id), 'id'); 1235 $this->assertEquals(array((int)$course2->id, (int)$course3->id), array_keys($courses)); 1236 1237 // Move the courses in sub category 2 back into to sub category 1. 1238 $this->assertTrue( 1239 \core_course\management\helper::move_courses_into_category($sub1->id, array($course2->id, $course3->id)) 1240 ); 1241 1242 $this->assertEquals(1, $cat1->get_courses_count()); 1243 $this->assertEquals(1, $cat2->get_courses_count()); 1244 $this->assertEquals(2, $sub1->get_courses_count()); 1245 $this->assertEquals(0, $sub2->get_courses_count()); 1246 1247 $courses = $DB->get_records('course', array('category' => $sub1->id), 'id'); 1248 $this->assertEquals(array((int)$course2->id, (int)$course3->id), array_keys($courses)); 1249 1250 // Try moving just one course. 1251 $this->assertTrue( 1252 \core_course\management\helper::move_courses_into_category($sub2->id, $course4->id) 1253 ); 1254 $this->assertEquals(1, $cat1->get_courses_count()); 1255 $this->assertEquals(0, $cat2->get_courses_count()); 1256 $this->assertEquals(2, $sub1->get_courses_count()); 1257 $this->assertEquals(1, $sub2->get_courses_count()); 1258 $courses = $DB->get_records('course', array('category' => $sub2->id), 'id'); 1259 $this->assertEquals(array((int)$course4->id), array_keys($courses)); 1260 1261 // Current state: 1262 // * $cat1 => $course1 1263 // * $sub1 => $course2, $course3 1264 // * $sub2 => $course4 1265 // * $cat2 =>. 1266 1267 // Prevent the user from being able to move into $sub2. 1268 $sub2cap = course_capability_assignment::prohibit(self::CATEGORY_MANAGE, $roleid, $sub2->get_context()->id); 1269 $sub2 = core_course_category::get($sub2->id); 1270 // Suppress debugging messages for a moment. 1271 $olddebug = $CFG->debug; 1272 $CFG->debug = 0; 1273 1274 // Try to move a course into sub2. This shouldn't be possible because you should always be able to undo what you've done. 1275 // Try moving just one course. 1276 try { 1277 \core_course\management\helper::move_courses_into_category($sub2->id, array($course2->id)); 1278 $this->fail('Invalid move of course between categories, action can\'t be undone.'); 1279 } catch (\moodle_exception $ex) { 1280 $this->assertEquals(get_string('cannotmovecourses', 'error'), $ex->getMessage()); 1281 } 1282 // Nothing should have changed. 1283 $this->assertEquals(1, $cat1->get_courses_count()); 1284 $this->assertEquals(0, $cat2->get_courses_count()); 1285 $this->assertEquals(2, $sub1->get_courses_count()); 1286 $this->assertEquals(1, $sub2->get_courses_count()); 1287 1288 // Now try moving a course out of sub2. Again should not be possible. 1289 // Try to move a course into sub2. This shouldn't be possible because you should always be able to undo what you've done. 1290 // Try moving just one course. 1291 try { 1292 \core_course\management\helper::move_courses_into_category($cat2->id, array($course4->id)); 1293 $this->fail('Invalid move of course between categories, action can\'t be undone.'); 1294 } catch (\moodle_exception $ex) { 1295 $this->assertEquals(get_string('cannotmovecourses', 'error'), $ex->getMessage()); 1296 } 1297 // Nothing should have changed. 1298 $this->assertEquals(1, $cat1->get_courses_count()); 1299 $this->assertEquals(0, $cat2->get_courses_count()); 1300 $this->assertEquals(2, $sub1->get_courses_count()); 1301 $this->assertEquals(1, $sub2->get_courses_count()); 1302 1303 $CFG->debug = $olddebug; 1304 } 1305 1306 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body