2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Course and category management helper class tests.
20 * @package core_course
21 * @copyright 2013 Sam Hemelryk
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 defined('MOODLE_INTERNAL') ||
die();
28 require_once($CFG->dirroot
.'/course/lib.php');
29 require_once($CFG->dirroot
.'/course/tests/fixtures/course_capability_assignment.php');
32 * Class core_course_management_helper_test
34 * This class tests \core_course\management\helper
36 class core_course_management_helper_test
extends advanced_testcase
{
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';
48 * Returns a user object and its assigned new role.
50 * @param testing_data_generator $generator
52 * @return array The user object and the role ID
54 protected function get_user_objects(testing_data_generator
$generator, $contextid) {
57 if (empty($USER->id
)) {
58 $user = $generator->create_user();
59 $this->setUser($user);
61 $roleid = create_role('Test role', 'testrole', 'Test role description');
62 if (!is_array($contextid)) {
63 $contextid = array($contextid);
65 foreach ($contextid as $cid) {
66 $assignid = role_assign($roleid, $user->id
, $cid);
68 return array($user, $roleid);
73 * - action_category_hide
74 * - action_category_show
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
79 public function test_action_category_hide_and_show() {
81 $this->resetAfterTest(true);
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
);
92 $this->assertEquals(1, $category->visible
);
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
);
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
);
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
);
143 $parentassignment->assign(CAP_PROHIBIT
);
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
);
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
);
174 $parentassignment->assign(CAP_PROHIBIT
);
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
);
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
);
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
);
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.
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
);
233 * Tests hiding and showing of a category by its ID.
235 * This mimics the logic of {@link test_action_category_hide_and_show()}
237 public function test_action_category_hide_and_show_by_id() {
239 $this->resetAfterTest(true);
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
);
250 $this->assertEquals(1, $category->visible
);
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
);
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
);
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
);
301 $parentassignment->assign(CAP_PROHIBIT
);
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
);
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
);
331 $parentassignment->assign(CAP_PROHIBIT
);
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
);
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
);
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
);
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.
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
);
390 * Test moving courses between categories.
392 public function test_action_category_move_courses_into() {
394 $this->resetAfterTest(true);
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
));
406 $syscontext = context_system
::instance();
408 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id
);
410 course_capability_assignment
::allow(array(self
::CATEGORY_MANAGE
, self
::CATEGORY_VIEWHIDDEN
), $roleid, $syscontext->id
);
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());
418 // Move the courses in sub category 1 to sub category 2.
420 \core_course\management\helper
::action_category_move_courses_into($sub1, $sub2, array($course2->id
, $course3->id
))
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());
428 $courses = $DB->get_records('course', array('category' => $sub2->id
), 'id');
429 $this->assertEquals(array((int)$course2->id
, (int)$course3->id
), array_keys($courses));
431 // Move the courses in sub category 2 back into to sub category 1.
433 \core_course\management\helper
::action_category_move_courses_into($sub2, $sub1, array($course2->id
, $course3->id
))
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());
441 $courses = $DB->get_records('course', array('category' => $sub1->id
), 'id');
442 $this->assertEquals(array((int)$course2->id
, (int)$course3->id
), array_keys($courses));
444 // Try moving just one course.
446 \core_course\management\helper
::action_category_move_courses_into($cat2, $sub2, array($course4->id
))
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));
455 // Try moving a course from a category its not part of.
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());
467 // Now try that again with two courses, one of which is in the right place.
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());
480 // * $cat1 => $course1
481 // * $sub1 => $course2, $course3
482 // * $sub2 => $course4
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
;
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.
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());
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());
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.
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());
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());
521 $CFG->debug
= $olddebug;
525 * Test moving a categories up and down.
527 public function test_action_category_movedown_and_moveup() {
529 $this->resetAfterTest(true);
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'));
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
);
541 // Check everything is where we expect it to be.
543 array('One', 'Two', 'Three'),
544 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
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
);
559 array('Two', 'One', 'Three'),
560 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
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
);
575 array('Two', 'Three', 'One'),
576 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
579 // Move the top category down one.
580 $this->assertTrue(\core_course\management\helper
::action_category_change_sortorder_down_one_by_id($cat2->id
));
582 array('Three', 'Two', 'One'),
583 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
586 // Move the top category down one.
587 $this->assertTrue(\core_course\management\helper
::action_category_change_sortorder_up_one_by_id($cat1->id
));
589 array('Three', 'One', 'Two'),
590 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
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
);
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
);
615 array('Three', 'One', 'Two'),
616 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
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
);
631 array('Three', 'One', 'Two'),
632 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
635 // Prevent moving on the parent.
636 course_capability_assignment
::prevent(self
::CATEGORY_MANAGE
, $roleid, $parent->get_context()->id
);
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.
642 array('Three', 'One', 'Two'),
643 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
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.
651 array('Three', 'One', 'Two'),
652 array_keys($DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder', 'name'))
658 * Test resorting of courses within a category.
660 * \core_course\management\helper::action_category_resort_courses
662 public function test_action_category_resort_courses() {
664 $this->resetAfterTest(true);
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();
676 // Update category object from DB so the course count is correct.
677 $category = core_course_category
::get($category->id
);
679 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id
);
680 $caps = course_capability_assignment
::allow(self
::CATEGORY_MANAGE
, $roleid, $syscontext->id
);
682 // Check that sort order in the DB matches what we've got in the cache.
683 $courses = $category->get_courses();
684 $this->assertInternalType('array', $courses);
685 $dbcourses = $DB->get_records('course', array('category' => $category->id
), 'sortorder');
686 $this->assertEquals(array_keys($dbcourses), array_keys($courses));
688 // Resort by fullname.
689 \core_course\management\helper
::action_category_resort_courses($category, 'fullname');
690 $courses = $category->get_courses();
691 $this->assertInternalType('array', $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));
696 // Resort by shortname.
697 \core_course\management\helper
::action_category_resort_courses($category, 'shortname');
698 $courses = $category->get_courses();
699 $this->assertInternalType('array', $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));
704 // Resort by idnumber.
705 \core_course\management\helper
::action_category_resort_courses($category, 'idnumber');
706 $courses = $category->get_courses();
707 $this->assertInternalType('array', $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));
712 // Try with a field that cannot be sorted on.
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->assertInternalType('array', $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));
725 // Try with a completely bogus field.
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->assertInternalType('array', $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));
738 // Prohibit resorting.
739 $caps->assign(CAP_PROHIBIT
);
740 // Refresh our coursecat object.
741 $category = core_course_category
::get($category->id
);
743 // We should no longer have permission to do this. Test it out!
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->assertInternalType('array', $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));
760 * Tests resorting sub categories of a course.
762 * \core_course\management\helper::action_category_resort_courses
764 public function test_action_category_resort_subcategories() {
766 $this->resetAfterTest(true);
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'));
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
);
778 $categories = $parent->get_children();
779 $this->assertInternalType('array', $categories);
780 $dbcategories = $DB->get_records('course_categories', array('parent' => $parent->id
), 'sortorder');
781 $this->assertEquals(array_keys($dbcategories), array_keys($categories));
783 // Test sorting by name.
784 \core_course\management\helper
::action_category_resort_subcategories($parent, 'name');
785 $categories = $parent->get_children();
786 $this->assertInternalType('array', $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));
791 // Test sorting by idnumber.
792 \core_course\management\helper
::action_category_resort_subcategories($parent, 'idnumber');
793 $categories = $parent->get_children();
794 $this->assertInternalType('array', $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));
799 // Try with an invalid field.
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->assertInternalType('array', $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));
812 // Try with a completely bogus field.
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->assertInternalType('array', $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));
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->assertInternalType('array', $categories);
830 $dbcategories = $DB->get_records('course_categories', array('parent' => '0'), 'sortorder');
831 $this->assertEquals(array_keys($dbcategories), array_keys($categories));
833 // Prohibit resorting.
834 $caps->assign(CAP_PROHIBIT
);
835 // Refresh our coursecat object.
836 $parent = core_course_category
::get($parent->id
);
838 // We should no longer have permission to do this. Test it out!
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->assertInternalType('array', $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));
855 * Test hiding and showing of a course.
857 * @see \core_course\management\helper::action_course_hide
858 * @see \core_course\management\helper::action_course_show
860 public function test_action_course_hide_show() {
861 $this->resetAfterTest(true);
863 $generator = $this->getDataGenerator();
864 $category = $generator->create_category();
865 $course = $generator->create_course();
867 $coursecontext = context_course
::instance($course->id
);
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
);
873 $course = new core_course_list_element(get_course($course->id
));
875 // Check it is set to what we think it is.
876 $this->assertEquals('1', $course->visible
);
877 $this->assertEquals('1', $course->visibleold
);
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
);
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
);
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
);
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
);
907 // Revoke the permissions.
908 $assignment->revoke();
909 $course = new core_course_list_element(get_course($course->id
));
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
);
919 * Test hiding and showing of a course.
921 * @see \core_course\management\helper::action_course_hide_by_record
922 * @see \core_course\management\helper::action_course_show_by_record
924 public function test_action_course_hide_show_by_record() {
925 $this->resetAfterTest(true);
927 $generator = $this->getDataGenerator();
928 $category = $generator->create_category();
929 $course = $generator->create_course();
931 $coursecontext = context_course
::instance($course->id
);
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
);
937 $course = get_course($course->id
);
939 // Check it is set to what we think it is.
940 $this->assertEquals('1', $course->visible
);
941 $this->assertEquals('1', $course->visibleold
);
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
);
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
);
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
);
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
);
971 // Revoke the permissions.
972 $assignment->revoke();
973 $course = get_course($course->id
);
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
);
983 * Tests moving a course up and down by one.
985 public function test_action_course_movedown_and_moveup() {
988 $this->resetAfterTest(true);
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();
997 // Update category object from DB so the course count is correct.
998 $category = core_course_category
::get($category->id
);
1000 list($user, $roleid) = $this->get_user_objects($generator, $context->id
);
1001 $caps = course_capability_assignment
::allow(self
::CATEGORY_MANAGE
, $roleid, $context->id
);
1003 $courses = $category->get_courses();
1004 $this->assertInternalType('array', $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));
1009 // Move a course down.
1011 \core_course\management\helper
::action_course_change_sortorder_down_one(
1012 new core_course_list_element(get_course($course1->id
)), $category)
1014 $courses = $category->get_courses();
1015 $this->assertInternalType('array', $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));
1020 // Move a course up.
1022 \core_course\management\helper
::action_course_change_sortorder_up_one(
1023 new core_course_list_element(get_course($course3->id
)), $category)
1025 $courses = $category->get_courses();
1026 $this->assertInternalType('array', $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));
1031 // Move a course down by record.
1033 \core_course\management\helper
::action_course_change_sortorder_down_one_by_record(get_course($course2->id
), $category)
1035 $courses = $category->get_courses();
1036 $this->assertInternalType('array', $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));
1041 // Move a course up by record.
1043 \core_course\management\helper
::action_course_change_sortorder_up_one_by_record(get_course($course2->id
), $category)
1045 $courses = $category->get_courses();
1046 $this->assertInternalType('array', $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));
1051 // Try move the bottom course down. This should return false and nothing changes.
1053 \core_course\management\helper
::action_course_change_sortorder_down_one(
1054 new core_course_list_element(get_course($course1->id
)), $category)
1056 $courses = $category->get_courses();
1057 $this->assertInternalType('array', $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));
1062 // Try move the top course up. This should return false and nothing changes.
1064 \core_course\management\helper
::action_course_change_sortorder_up_one(
1065 new core_course_list_element(get_course($course2->id
)), $category)
1067 $courses = $category->get_courses();
1068 $this->assertInternalType('array', $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));
1073 // Prohibit the ability to move.
1074 $caps->assign(CAP_PROHIBIT
);
1075 // Reload the category.
1076 $category = core_course_category
::get($category->id
);
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->assertInternalType('array', $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));
1093 * Tests the fetching of actions for a category.
1095 public function test_get_category_listitem_actions() {
1097 $this->resetAfterTest(true);
1099 $PAGE->set_url(new moodle_url('/course/management.php'));
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
);
1113 $actions = \core_course\management\helper
::get_category_listitem_actions($category);
1114 $this->assertInternalType('array', $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);
1128 * Tests fetching the course actions.
1130 public function test_get_course_detail_actions() {
1131 $this->resetAfterTest(true);
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(
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
);
1149 $actions = \core_course\management\helper
::get_course_detail_actions(new core_course_list_element($course));
1150 $this->assertInternalType('array', $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);
1161 * Test fetching course details.
1163 public function test_get_course_detail_array() {
1164 $this->resetAfterTest(true);
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(
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
);
1183 $details = \core_course\management\helper
::get_course_detail_array(new core_course_list_element($course));
1184 $this->assertInternalType('array', $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);
1198 public function test_move_courses_into_category() {
1200 $this->resetAfterTest(true);
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
));
1212 $syscontext = context_system
::instance();
1214 list($user, $roleid) = $this->get_user_objects($generator, $syscontext->id
);
1216 course_capability_assignment
::allow(array(self
::CATEGORY_MANAGE
, self
::CATEGORY_VIEWHIDDEN
), $roleid, $syscontext->id
);
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());
1224 // Move the courses in sub category 1 to sub category 2.
1226 \core_course\management\helper
::move_courses_into_category($sub2->id
, array($course2->id
, $course3->id
))
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());
1234 $courses = $DB->get_records('course', array('category' => $sub2->id
), 'id');
1235 $this->assertEquals(array((int)$course2->id
, (int)$course3->id
), array_keys($courses));
1237 // Move the courses in sub category 2 back into to sub category 1.
1239 \core_course\management\helper
::move_courses_into_category($sub1->id
, array($course2->id
, $course3->id
))
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());
1247 $courses = $DB->get_records('course', array('category' => $sub1->id
), 'id');
1248 $this->assertEquals(array((int)$course2->id
, (int)$course3->id
), array_keys($courses));
1250 // Try moving just one course.
1252 \core_course\management\helper
::move_courses_into_category($sub2->id
, $course4->id
)
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));
1262 // * $cat1 => $course1
1263 // * $sub1 => $course2, $course3
1264 // * $sub2 => $course4
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
;
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.
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());
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());
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.
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());
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());
1303 $CFG->debug
= $olddebug;