Commit | Line | Data |
---|---|---|
e922fe23 PS |
1 | <?php |
2 | // This file is part of Moodle - http://moodle.org/ | |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | /** | |
18 | * Full functional accesslib test | |
19 | * | |
20 | * It is implemented as one test case because it would take hours | |
21 | * to prepare the fake test site for each test, at the same time | |
22 | * we have to work around multiple problems in UnitTestCaseUsingDatabase. | |
23 | * | |
24 | * @package core | |
25 | * @copyright 2011 Petr Skoda (http://skodak.org) | |
26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
27 | */ | |
28 | ||
29 | defined('MOODLE_INTERNAL') || die(); | |
30 | ||
31 | ||
32 | /** | |
33 | * Context caching fixture | |
34 | */ | |
35 | class context_inspection extends context_helper { | |
36 | public static function test_context_cache_size() { | |
37 | return self::$cache_count; | |
38 | } | |
39 | } | |
40 | ||
41 | ||
42 | /** | |
43 | * Functional test for accesslib.php | |
44 | * | |
45 | * Note: execution may take many minutes especially on slower servers. | |
46 | */ | |
47 | class accesslib_test extends UnitTestCaseUsingDatabase { | |
48 | // NOTE: The UnitTestCaseUsingDatabase is problematic and VERY dangerous especially for production servers! | |
49 | // | |
50 | // 1. We could create full install without plugins and use the test DB since the very beginning in lib/setup.php. | |
51 | // 2. We should not execute the tests from the web UI because the static caches all over the place collide, instead | |
52 | // we could use CLI | |
53 | // 3. SimpleTest appears to be dead - unfortunately nobody else thinks we should switch to PHPUnit asap | |
54 | // 4. switching of USER->id alone is not acceptable at all, we must switch the complete USER record | |
55 | // and probably deal with _SESSION['USER'] too | |
56 | // 5. we must close session before messing with anything in $USER or $SESSION | |
57 | // 6. $SITE is not switched | |
58 | // 7. tons of other static caches are not reset | |
59 | // 8. etc. | |
60 | // | |
61 | // -- | |
62 | // skodak | |
63 | ||
64 | //TODO: add more tests for the remaining accesslib parts that were not touched by the refactoring in 2.2dev | |
65 | ||
66 | public static $includecoverage = array('lib/accesslib.php'); | |
67 | ||
68 | protected $accesslibprevuser = null; | |
69 | protected $accesslibprevsite = null; | |
70 | ||
71 | /** | |
72 | * A small functional test of accesslib functions and classes. | |
73 | */ | |
74 | public function test_everything_in_accesslib() { | |
75 | global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE; | |
76 | ||
77 | // First of all finalize the session, we must not carry over any of this mess to the next page via SESSION!!! | |
78 | session_get_instance()->write_close(); | |
79 | ||
80 | // hack - this is going to take very long time | |
81 | set_time_limit(3600); | |
82 | ||
83 | // Get rid of current user that would not work anyway, | |
84 | // do NOT even think about using $this->switch_global_user_id()! | |
85 | if (!isset($this->accesslibprevuser)) { | |
86 | $this->accesslibprevuser = clone($USER); | |
87 | $USER = new stdClass(); | |
88 | $USER->id = 0; | |
89 | } | |
90 | ||
91 | // Backup $SITE global | |
92 | if (!isset($this->accesslibprevsite)) { | |
93 | $this->accesslibprevsite = $SITE; | |
94 | } | |
95 | ||
96 | // Switch DB, if it somehow fails or you specified wrong unittest prefix it will nuke real data, you have been warned! | |
97 | $this->switch_to_test_db(); | |
98 | ||
99 | // Let's switch the CFG | |
100 | $prevcfg = clone($CFG); | |
101 | $this->switch_to_test_cfg(); | |
102 | $CFG->config_php_settings = $prevcfg->config_php_settings; | |
103 | $CFG->noemailever = true; | |
104 | $CFG->admin = $prevcfg->admin; | |
105 | $CFG->lang = 'en'; | |
106 | $CFG->tempdir = $prevcfg->tempdir; | |
107 | $CFG->cachedir = $prevcfg->cachedir; | |
108 | $CFG->directorypermissions = $prevcfg->directorypermissions; | |
109 | $CFG->filepermissions = $prevcfg->filepermissions; | |
110 | ||
111 | // Reset all caches | |
112 | accesslib_clear_all_caches_for_unit_testing(); | |
113 | ||
114 | // Add some core tables - this is known to break constantly because we keep adding dependencies... | |
115 | $tablenames = array('config', 'config_plugins', 'modules', 'course', 'course_modules', 'course_sections', 'course_categories', 'mnet_host', 'mnet_application', | |
116 | 'capabilities', 'context', 'context_temp', 'role', 'role_capabilities', 'role_allow_switch', 'license', 'my_pages', 'block', 'block_instances', 'block_positions', | |
117 | 'role_allow_assign', 'role_allow_override', 'role_assignments', 'role_context_levels' ,'enrol', 'user_enrolments', 'filter_active', 'filter_config', 'comments', | |
8a238aee | 118 | 'user', 'groups_members', 'cache_flags', 'events_handlers', 'user_lastaccess', 'rating', 'files', 'role_names', 'user_preferences', 'grading_areas'); |
e922fe23 PS |
119 | $this->create_test_tables($tablenames, 'lib'); |
120 | ||
121 | // Create all core default records and default settings | |
122 | require_once("$CFG->libdir/db/install.php"); | |
123 | xmldb_main_install(); // installs the capabilities too | |
124 | ||
125 | // Fake mod_page install | |
126 | $tablenames = array('page'); | |
127 | $this->create_test_tables($tablenames, 'mod/page'); | |
128 | $module = new stdClass(); | |
129 | require($CFG->dirroot .'/mod/page/version.php'); | |
130 | $module->name = 'page'; | |
131 | $pagemoduleid = $DB->insert_record('modules', $module); | |
132 | update_capabilities('mod_page'); | |
133 | ||
134 | // Fake block_online_users install | |
135 | $plugin = new stdClass(); | |
136 | $plugin->version = NULL; | |
137 | $plugin->cron = 0; | |
138 | include($CFG->dirroot.'/blocks/online_users/version.php'); | |
139 | $plugin->name = 'online_users'; | |
140 | $onlineusersblockid = $DB->insert_record('block', $plugin); | |
141 | update_capabilities('block_online_users'); | |
142 | ||
143 | // Finish roles setup | |
144 | set_config('defaultfrontpageroleid', $DB->get_field('role', 'id', array('archetype'=>'frontpage'))); | |
145 | set_config('defaultuserroleid', $DB->get_field('role', 'id', array('archetype'=>'user'))); | |
146 | set_config('notloggedinroleid', $DB->get_field('role', 'id', array('archetype'=>'guest'))); | |
147 | set_config('rolesactive', 1); | |
148 | ||
149 | // Init manual enrol | |
150 | set_config('status', ENROL_INSTANCE_ENABLED, 'enrol_manual'); | |
151 | set_config('defaultperiod', 0, 'enrol_manual'); | |
152 | $manualenrol = enrol_get_plugin('manual'); | |
153 | ||
154 | // Fill the site with some real data | |
155 | $testcategories = array(); | |
156 | $testcourses = array(); | |
157 | $testpages = array(); | |
158 | $testblocks = array(); | |
159 | $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id'); | |
160 | ||
161 | $systemcontext = context_system::instance(); | |
162 | $frontpagecontext = context_course::instance(SITEID); | |
163 | ||
164 | // Add block to system context | |
165 | $bi = new stdClass(); | |
166 | $bi->blockname = 'online_users'; | |
167 | $bi->parentcontextid = $systemcontext->id; | |
168 | $bi->showinsubcontexts = 1; | |
169 | $bi->pagetypepattern = ''; | |
170 | $bi->subpagepattern = ''; | |
171 | $bi->defaultregion = ''; | |
172 | $bi->defaultweight = 0; | |
173 | $bi->configdata = ''; | |
174 | $biid = $DB->insert_record('block_instances', $bi); | |
175 | context_block::instance($biid); | |
176 | $testblocks[] = $biid; | |
177 | ||
178 | // Some users | |
179 | $testusers = array(); | |
180 | for($i=0; $i<20; $i++) { | |
181 | $user = new stdClass(); | |
182 | $user->auth = 'manual'; | |
183 | $user->firstname = 'user'.$i; | |
184 | $user->lastname = 'user'.$i; | |
185 | $user->username = 'user'.$i; | |
186 | $user->password = 'doesnotexist'; | |
187 | $user->email = "user$i@example.com"; | |
188 | $user->confirmed = 1; | |
189 | $user->mnethostid = $CFG->mnet_localhost_id; | |
190 | $user->lang = $CFG->lang; | |
191 | $user->maildisplay = 1; | |
192 | $user->timemodified = time(); | |
193 | $user->deleted = 0; | |
194 | $user->lastip = '0.0.0.0'; | |
195 | $userid = $DB->insert_record('user', $user); | |
196 | $testusers[$i] = $userid; | |
197 | $usercontext = context_user::instance($userid); | |
198 | ||
199 | // Add block to user profile | |
200 | $bi->parentcontextid = $usercontext->id; | |
201 | $biid = $DB->insert_record('block_instances', $bi); | |
202 | context_block::instance($biid); | |
203 | $testblocks[] = $biid; | |
204 | } | |
205 | // Deleted user - should be ignored everywhere, can not have context | |
206 | $user = new stdClass(); | |
207 | $user->auth = 'manual'; | |
208 | $user->firstname = ''; | |
209 | $user->lastname = ''; | |
210 | $user->username = 'user@example.com121132132'; | |
211 | $user->password = ''; | |
212 | $user->email = ''; | |
213 | $user->confirmed = 1; | |
214 | $user->mnethostid = $CFG->mnet_localhost_id; | |
215 | $user->lang = $CFG->lang; | |
216 | $user->maildisplay = 1; | |
217 | $user->timemodified = time(); | |
218 | $user->deleted = 1; | |
219 | $user->lastip = '0.0.0.0'; | |
220 | $DB->insert_record('user', $user); | |
221 | unset($user); | |
222 | ||
223 | // Add block to frontpage | |
224 | $bi->parentcontextid = $frontpagecontext->id; | |
225 | $biid = $DB->insert_record('block_instances', $bi); | |
226 | $frontpageblockcontext = context_block::instance($biid); | |
227 | $testblocks[] = $biid; | |
228 | ||
229 | // Add a resource to frontpage | |
230 | $page = new stdClass(); | |
231 | $page->course = $SITE->id; | |
232 | $page->intro = '...'; | |
233 | $page->introformat = FORMAT_HTML; | |
234 | $page->content = '...'; | |
235 | $page->contentformat = FORMAT_HTML; | |
236 | $pageid = $DB->insert_record('page', $page); | |
237 | $testpages[] = $pageid; | |
238 | $cm = new stdClass(); | |
239 | $cm->course = $SITE->id; | |
240 | $cm->module = $pagemoduleid; | |
241 | $cm->section = 1; | |
242 | $cm->instance = $pageid; | |
243 | $cmid = $DB->insert_record('course_modules', $cm); | |
244 | $frontpagepagecontext = context_module::instance($cmid); | |
245 | ||
246 | // Add block to frontpage resource | |
247 | $bi->parentcontextid = $frontpagepagecontext->id; | |
248 | $biid = $DB->insert_record('block_instances', $bi); | |
249 | $frontpagepageblockcontext = context_block::instance($biid); | |
250 | $testblocks[] = $biid; | |
251 | ||
252 | // Some nested course categories with courses | |
253 | require_once("$CFG->dirroot/course/lib.php"); | |
254 | $path = ''; | |
255 | $parentcat = 0; | |
256 | for($i=0; $i<5; $i++) { | |
257 | $cat = new stdClass(); | |
258 | $cat->name = 'category'.$i; | |
259 | $cat->parent = $parentcat; | |
260 | $cat->depth = $i+1; | |
261 | $cat->sortorder = MAX_COURSES_IN_CATEGORY * ($i+2); | |
262 | $cat->timemodified = time(); | |
263 | $catid = $DB->insert_record('course_categories', $cat); | |
264 | $path = $path . '/' . $catid; | |
265 | $DB->set_field('course_categories', 'path', $path, array('id'=>$catid)); | |
266 | $parentcat = $catid; | |
267 | $testcategories[] = $catid; | |
268 | $catcontext = context_coursecat::instance($catid); | |
269 | ||
270 | if ($i >=4) { | |
271 | continue; | |
272 | } | |
273 | ||
274 | // Add resource to each category | |
275 | $bi->parentcontextid = $catcontext->id; | |
276 | $biid = $DB->insert_record('block_instances', $bi); | |
277 | context_block::instance($biid); | |
278 | ||
279 | // Add a few courses to each category | |
280 | for($j=0; $j<6; $j++) { | |
281 | $course = new stdClass(); | |
282 | $course->fullname = 'course'.$j; | |
283 | $course->shortname = 'c'.$j; | |
284 | $course->summary = 'bah bah bah'; | |
285 | $course->newsitems = 0; | |
286 | $course->numsections = 1; | |
287 | $course->category = $catid; | |
288 | $course->format = 'topics'; | |
289 | $course->timecreated = time(); | |
290 | $course->visible = 1; | |
291 | $course->timemodified = $course->timecreated; | |
292 | $courseid = $DB->insert_record('course', $course); | |
293 | $section = new stdClass(); | |
294 | $section->course = $courseid; | |
295 | $section->section = 0; | |
296 | $section->summaryformat = FORMAT_HTML; | |
297 | $DB->insert_record('course_sections', $section); | |
298 | $section->section = 1; | |
299 | $DB->insert_record('course_sections', $section); | |
300 | $testcourses[] = $courseid; | |
301 | $coursecontext = context_course::instance($courseid); | |
302 | ||
303 | if ($j >= 5) { | |
304 | continue; | |
305 | } | |
306 | // Add manual enrol instance | |
307 | $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$courseid))); | |
308 | ||
309 | // Add block to each course | |
310 | $bi->parentcontextid = $coursecontext->id; | |
311 | $biid = $DB->insert_record('block_instances', $bi); | |
312 | context_block::instance($biid); | |
313 | $testblocks[] = $biid; | |
314 | ||
315 | // Add a resource to each course | |
316 | $page->course = $courseid; | |
317 | $pageid = $DB->insert_record('page', $page); | |
318 | $testpages[] = $pageid; | |
319 | $cm->course = $courseid; | |
320 | $cm->instance = $pageid; | |
321 | $cm->id = $DB->insert_record('course_modules', $cm); | |
322 | $modcontext = context_module::instance($cm->id); | |
323 | ||
324 | // Add block to each module | |
325 | $bi->parentcontextid = $modcontext->id; | |
326 | $biid = $DB->insert_record('block_instances', $bi); | |
327 | context_block::instance($biid); | |
328 | $testblocks[] = $biid; | |
329 | } | |
330 | } | |
331 | ||
332 | // Make sure all contexts were created properly | |
333 | $count = 1; //system | |
334 | $count += $DB->count_records('user', array('deleted'=>0)); | |
335 | $count += $DB->count_records('course_categories'); | |
336 | $count += $DB->count_records('course'); | |
337 | $count += $DB->count_records('course_modules'); | |
338 | $count += $DB->count_records('block_instances'); | |
339 | $this->assertEqual($DB->count_records('context'), $count); | |
340 | $this->assertEqual($DB->count_records('context', array('depth'=>0)), 0); | |
341 | $this->assertEqual($DB->count_records('context', array('path'=>NULL)), 0); | |
342 | ||
343 | ||
344 | // ====== context_helper::get_level_name() ================================ | |
345 | ||
346 | $levels = context_helper::get_all_levels(); | |
347 | foreach ($levels as $level=>$classname) { | |
348 | $name = context_helper::get_level_name($level); | |
349 | $this->assertFalse(empty($name)); | |
350 | } | |
351 | ||
352 | ||
353 | // ======= context::instance_by_id(), context_xxx::instance(); | |
354 | ||
355 | $context = context::instance_by_id($frontpagecontext->id); | |
356 | $this->assertidentical($context->contextlevel, CONTEXT_COURSE); | |
357 | $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING)); | |
358 | try { | |
359 | context::instance_by_id(-1); | |
360 | $this->fail('exception expected'); | |
361 | } catch (Exception $e) { | |
362 | $this->assertTrue(true); | |
363 | } | |
364 | $this->assertTrue(context_system::instance() instanceof context_system); | |
365 | $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat); | |
366 | $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course); | |
367 | $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module); | |
368 | $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block); | |
369 | ||
370 | $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING)); | |
371 | $this->assertFalse(context_course::instance(-1, IGNORE_MISSING)); | |
372 | $this->assertFalse(context_module::instance(-1, IGNORE_MISSING)); | |
373 | $this->assertFalse(context_block::instance(-1, IGNORE_MISSING)); | |
374 | try { | |
375 | context_coursecat::instance(-1); | |
376 | $this->fail('exception expected'); | |
377 | } catch (Exception $e) { | |
378 | $this->assertTrue(true); | |
379 | } | |
380 | try { | |
381 | context_course::instance(-1); | |
382 | $this->fail('exception expected'); | |
383 | } catch (Exception $e) { | |
384 | $this->assertTrue(true); | |
385 | } | |
386 | try { | |
387 | context_module::instance(-1); | |
388 | $this->fail('exception expected'); | |
389 | } catch (Exception $e) { | |
390 | $this->assertTrue(true); | |
391 | } | |
392 | try { | |
393 | context_block::instance(-1); | |
394 | $this->fail('exception expected'); | |
395 | } catch (Exception $e) { | |
396 | $this->assertTrue(true); | |
397 | } | |
398 | ||
399 | ||
400 | // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() ========= | |
401 | ||
402 | $testcontexts = array(); | |
403 | $testcontexts[CONTEXT_SYSTEM] = context_system::instance(); | |
404 | $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]); | |
405 | $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]); | |
406 | $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]); | |
407 | $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]); | |
408 | ||
409 | foreach ($testcontexts as $context) { | |
410 | $name = $context->get_context_name(true, true); | |
411 | $this->assertFalse(empty($name)); | |
412 | ||
413 | $this->assertTrue($context->get_url() instanceof moodle_url); | |
414 | ||
415 | $caps = $context->get_capabilities(); | |
416 | $this->assertTrue(is_array($caps)); | |
417 | foreach ($caps as $cap) { | |
418 | $cap = (array)$cap; | |
419 | $this->assertIdentical(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask')); | |
420 | } | |
421 | } | |
422 | unset($testcontexts); | |
423 | ||
424 | // ===== $context->get_course_context() ========================================= | |
425 | ||
426 | $this->assertFalse($systemcontext->get_course_context(false)); | |
427 | try { | |
428 | $systemcontext->get_course_context(); | |
429 | $this->fail('exception expected'); | |
430 | } catch (Exception $e) { | |
431 | $this->assertTrue(true); | |
432 | } | |
433 | $context = context_coursecat::instance($testcategories[0]); | |
434 | $this->assertFalse($context->get_course_context(false)); | |
435 | try { | |
436 | $context->get_course_context(); | |
437 | $this->fail('exception expected'); | |
438 | } catch (Exception $e) { | |
439 | $this->assertTrue(true); | |
440 | } | |
441 | $this->assertIdentical($frontpagecontext->get_course_context(true), $frontpagecontext); | |
442 | $this->assertIdentical($frontpagepagecontext->get_course_context(true), $frontpagecontext); | |
443 | $this->assertIdentical($frontpagepageblockcontext->get_course_context(true), $frontpagecontext); | |
444 | ||
445 | ||
446 | // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() ======= | |
447 | ||
448 | $userid = reset($testusers); | |
449 | $usercontext = context_user::instance($userid); | |
450 | $this->assertIdentical($usercontext->get_parent_context(), $systemcontext); | |
451 | $this->assertIdentical($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext)); | |
452 | $this->assertIdentical($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext)); | |
453 | ||
454 | $this->assertIdentical($systemcontext->get_parent_contexts(), array()); | |
455 | $this->assertIdentical($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext)); | |
456 | $this->assertIdentical($systemcontext->get_parent_context_ids(), array()); | |
457 | $this->assertIdentical($systemcontext->get_parent_context_ids(true), array($systemcontext->id)); | |
458 | ||
459 | $this->assertIdentical($frontpagecontext->get_parent_context(), $systemcontext); | |
460 | $this->assertIdentical($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext)); | |
461 | $this->assertIdentical($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext)); | |
462 | $this->assertIdentical($frontpagecontext->get_parent_context_ids(), array($systemcontext->id)); | |
463 | $this->assertEqual($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id)); | |
464 | ||
465 | $this->assertIdentical($systemcontext->get_parent_context(), false); | |
466 | $frontpagecontext = context_course::instance($SITE->id); | |
467 | $parent = $systemcontext; | |
468 | foreach ($testcategories as $catid) { | |
469 | $catcontext = context_coursecat::instance($catid); | |
470 | $this->assertIdentical($catcontext->get_parent_context(), $parent); | |
471 | $parent = $catcontext; | |
472 | } | |
473 | $this->assertIdentical($frontpagepagecontext->get_parent_context(), $frontpagecontext); | |
474 | $this->assertIdentical($frontpageblockcontext->get_parent_context(), $frontpagecontext); | |
475 | $this->assertIdentical($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext); | |
476 | ||
477 | ||
478 | // ====== $context->get_child_contexts() ================================ | |
479 | ||
480 | $children = $systemcontext->get_child_contexts(); | |
481 | $this->assertEqual(count($children)+1, $DB->count_records('context')); | |
482 | ||
483 | $context = context_coursecat::instance($testcategories[3]); | |
484 | $children = $context->get_child_contexts(); | |
485 | $countcats = 0; | |
486 | $countcourses = 0; | |
487 | $countblocks = 0; | |
488 | foreach ($children as $child) { | |
489 | if ($child->contextlevel == CONTEXT_COURSECAT) { | |
490 | $countcats++; | |
491 | } | |
492 | if ($child->contextlevel == CONTEXT_COURSE) { | |
493 | $countcourses++; | |
494 | } | |
495 | if ($child->contextlevel == CONTEXT_BLOCK) { | |
496 | $countblocks++; | |
497 | } | |
498 | } | |
499 | $this->assertEqual(count($children), 8); | |
500 | $this->assertEqual($countcats, 1); | |
501 | $this->assertEqual($countcourses, 6); | |
502 | $this->assertEqual($countblocks, 1); | |
503 | ||
504 | $context = context_course::instance($testcourses[2]); | |
505 | $children = $context->get_child_contexts(); | |
506 | $this->assertEqual(count($children), 3); | |
507 | ||
508 | $context = context_module::instance($testpages[3]); | |
509 | $children = $context->get_child_contexts(); | |
510 | $this->assertEqual(count($children), 1); | |
511 | ||
512 | $context = context_block::instance($testblocks[1]); | |
513 | $children = $context->get_child_contexts(); | |
514 | $this->assertEqual(count($children), 0); | |
515 | ||
516 | unset($children); | |
517 | unset($countcats); | |
518 | unset($countcourses); | |
519 | unset($countblocks); | |
520 | ||
521 | ||
522 | // ======= context_helper::reset_caches() ============================ | |
523 | ||
524 | context_helper::reset_caches(); | |
525 | $this->assertEqual(context_inspection::test_context_cache_size(), 0); | |
526 | context_course::instance($SITE->id); | |
527 | $this->assertEqual(context_inspection::test_context_cache_size(), 1); | |
528 | ||
529 | ||
530 | // ======= context preloading ======================================== | |
531 | ||
532 | context_helper::reset_caches(); | |
533 | $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')." | |
534 | FROM {context} c | |
535 | WHERE c.contextlevel <> ".CONTEXT_SYSTEM; | |
536 | $records = $DB->get_records_sql($sql); | |
537 | $firstrecord = reset($records); | |
538 | $columns = context_helper::get_preload_record_columns('c'); | |
539 | $firstrecord = (array)$firstrecord; | |
540 | $this->assertIdentical(array_keys($firstrecord), array_values($columns)); | |
541 | context_helper::reset_caches(); | |
542 | foreach ($records as $record) { | |
543 | context_helper::preload_from_record($record); | |
544 | $this->assertIdentical($record, new stdClass()); | |
545 | } | |
546 | $this->assertEqual(context_inspection::test_context_cache_size(), count($records)); | |
547 | unset($records); | |
548 | unset($columns); | |
549 | ||
550 | context_helper::reset_caches(); | |
551 | context_helper::preload_course($SITE->id); | |
552 | $this->assertEqual(context_inspection::test_context_cache_size(), 4); | |
553 | ||
554 | // ====== assign_capability(), unassign_capability() ==================== | |
555 | ||
556 | $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); | |
557 | $this->assertFalse($rc); | |
558 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id); | |
559 | $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); | |
560 | $this->assertEqual($rc->permission, CAP_ALLOW); | |
561 | assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id); | |
562 | $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); | |
563 | $this->assertEqual($rc->permission, CAP_ALLOW); | |
564 | assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true); | |
565 | $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); | |
566 | $this->assertEqual($rc->permission, CAP_PREVENT); | |
567 | ||
568 | assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext); | |
569 | $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); | |
570 | $this->assertFalse($rc); | |
571 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext); | |
572 | unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true); | |
573 | $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups')); | |
574 | $this->assertFalse($rc); | |
575 | unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true); | |
576 | unset($rc); | |
577 | ||
578 | accesslib_clear_all_caches(false); // must be done after assign_capability() | |
579 | ||
580 | ||
581 | // ======= role_assign(), role_unassign(), role_unassign_all() ============== | |
582 | ||
583 | $context = context_course::instance($testcourses[1]); | |
584 | $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0); | |
585 | role_assign($allroles['teacher'], $testusers[1], $context->id); | |
586 | role_assign($allroles['teacher'], $testusers[2], $context->id); | |
587 | role_assign($allroles['manager'], $testusers[1], $context->id); | |
588 | $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3); | |
589 | role_unassign($allroles['teacher'], $testusers[1], $context->id); | |
590 | $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2); | |
591 | role_unassign_all(array('contextid'=>$context->id)); | |
592 | $this->assertEqual($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0); | |
593 | unset($context); | |
594 | ||
595 | accesslib_clear_all_caches(false); // just in case | |
596 | ||
597 | ||
598 | // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ======================== | |
599 | ||
600 | $adminid = get_admin()->id; | |
601 | $guestid = $CFG->siteguest; | |
602 | ||
603 | // Enrol some users into some courses | |
604 | $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST); | |
605 | $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST); | |
606 | $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id'); | |
607 | $cm1 = reset($cms); | |
608 | $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id'); | |
609 | $block1 = reset($blocks); | |
610 | $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id)); | |
611 | $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id)); | |
612 | for($i=0; $i<9; $i++) { | |
613 | $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']); | |
614 | } | |
615 | $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']); | |
616 | $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']); | |
617 | ||
618 | for($i=10; $i<15; $i++) { | |
619 | $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']); | |
620 | } | |
621 | $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']); | |
622 | ||
623 | // Add tons of role assignments - the more the better | |
624 | role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2])); | |
625 | role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1])); | |
626 | role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id)); | |
627 | role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id)); | |
628 | role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id)); | |
629 | role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id)); | |
630 | role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id)); | |
631 | role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id)); | |
632 | ||
633 | role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id)); | |
634 | role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id)); | |
635 | ||
636 | // Add tons of overrides - the more the better | |
637 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true); | |
638 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true); | |
639 | assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true); | |
640 | assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true); | |
641 | assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true); | |
642 | ||
643 | assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true); | |
644 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true); | |
645 | assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true); | |
646 | assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true); | |
647 | assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true); | |
648 | ||
649 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true); | |
650 | assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true); | |
651 | assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true); | |
652 | assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true); | |
653 | ||
654 | assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true); | |
655 | ||
656 | accesslib_clear_all_caches(false); // must be done after assign_capability() | |
657 | ||
658 | // Extra tests for guests and not-logged-in users because they can not be verified by cross checking | |
659 | // with get_users_by_capability() where they are ignored | |
660 | $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid)); | |
661 | $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid)); | |
662 | $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid)); | |
663 | $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid)); | |
664 | ||
665 | $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0)); | |
666 | $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0)); | |
667 | $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0)); | |
668 | $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0)); | |
669 | ||
670 | $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11])); | |
671 | $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11])); | |
672 | $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11])); | |
673 | $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11])); | |
674 | ||
675 | $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9])); | |
676 | $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9])); | |
677 | $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9])); | |
678 | ||
679 | // Test the list of enrolled users | |
680 | $coursecontext = context_course::instance($course1->id); | |
681 | $enrolled = get_enrolled_users($coursecontext); | |
682 | $this->assertEqual(count($enrolled), 10); | |
683 | for($i=0; $i<10; $i++) { | |
684 | $this->assertTrue(isset($enrolled[$testusers[$i]])); | |
685 | } | |
686 | $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update'); | |
687 | $this->assertEqual(count($enrolled), 1); | |
688 | $this->assertTrue(isset($enrolled[$testusers[9]])); | |
689 | unset($enrolled); | |
690 | ||
691 | // role switching | |
692 | $userid = $testusers[9]; | |
693 | $USER = $DB->get_record('user', array('id'=>$userid)); | |
694 | load_all_capabilities(); | |
695 | $coursecontext = context_course::instance($course1->id); | |
696 | $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); | |
697 | $this->assertFalse(is_role_switched($course1->id)); | |
698 | role_switch($allroles['student'], $coursecontext); | |
699 | $this->assertTrue(is_role_switched($course1->id)); | |
700 | $this->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']); | |
701 | $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); | |
702 | reload_all_capabilities(); | |
703 | $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); | |
704 | role_switch(0, $coursecontext); | |
705 | $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); | |
706 | $userid = $adminid; | |
707 | $USER = $DB->get_record('user', array('id'=>$userid)); | |
708 | load_all_capabilities(); | |
709 | $coursecontext = context_course::instance($course1->id); | |
710 | $blockcontext = context_block::instance($block1->id); | |
711 | $this->assertTrue(has_capability('moodle/course:update', $blockcontext)); | |
712 | role_switch($allroles['student'], $coursecontext); | |
713 | $this->assertEqual($USER->access['rsw'][$coursecontext->path], $allroles['student']); | |
714 | $this->assertFalse(has_capability('moodle/course:update', $blockcontext)); | |
715 | reload_all_capabilities(); | |
716 | $this->assertFalse(has_capability('moodle/course:update', $blockcontext)); | |
717 | load_all_capabilities(); | |
718 | $this->assertTrue(has_capability('moodle/course:update', $blockcontext)); | |
719 | ||
720 | // temp course role for enrol | |
721 | $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem... | |
722 | $userid = $testusers[5]; | |
723 | $roleid = $allroles['editingteacher']; | |
724 | $USER = $DB->get_record('user', array('id'=>$userid)); | |
725 | load_all_capabilities(); | |
726 | $coursecontext = context_course::instance($course1->id); | |
727 | $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); | |
728 | $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid])); | |
729 | load_temp_course_role($coursecontext, $roleid); | |
730 | $this->assertEqual($USER->access['ra'][$coursecontext->path][$roleid], $roleid); | |
731 | $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); | |
732 | remove_temp_course_roles($coursecontext); | |
733 | $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid)); | |
734 | load_temp_course_role($coursecontext, $roleid); | |
735 | reload_all_capabilities(); | |
736 | $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid)); | |
737 | $USER = new stdClass(); | |
738 | $USER->id = 0; | |
739 | ||
740 | // Now cross check has_capability() with get_users_by_capability(), each using different code paths, | |
741 | // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong, | |
742 | // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users) | |
743 | $contexts = $DB->get_records('context', array(), 'id'); | |
744 | $contexts = array_values($contexts); | |
745 | $capabilities = $DB->get_records('capabilities', array(), 'id'); | |
746 | $capabilities = array_values($capabilities); | |
747 | $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']); | |
748 | ||
749 | // Random time! | |
750 | srand(666); | |
751 | foreach($testusers as $userid) { // no guest or deleted | |
752 | // each user gets 0-20 random roles | |
753 | $rcount = rand(0, 10); | |
754 | for($j=0; $j<$rcount; $j++) { | |
755 | $roleid = $roles[rand(0, count($roles)-1)]; | |
756 | $contextid = $contexts[rand(0, count($contexts)-1)]->id; | |
757 | role_assign($roleid, $userid, $contextid); | |
758 | } | |
759 | } | |
760 | $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT); | |
761 | for($j=0; $j<10000; $j++) { | |
762 | $roleid = $roles[rand(0, count($roles)-1)]; | |
763 | $contextid = $contexts[rand(0, count($contexts)-1)]->id; | |
764 | $permission = $permissions[rand(0,count($permissions)-1)]; | |
765 | $capname = $capabilities[rand(0, count($capabilities)-1)]->name; | |
766 | assign_capability($capname, $permission, $roleid, $contextid, true); | |
767 | } | |
768 | unset($permissions); | |
769 | unset($roles); | |
770 | unset($contexts); | |
771 | unset($users); | |
772 | unset($capabilities); | |
773 | ||
774 | accesslib_clear_all_caches(false); // must be done after assign_capability() | |
775 | ||
776 | // Test time - let's set up some real user, just in case the logic for USER affects the others... | |
777 | $USER = $DB->get_record('user', array('id'=>$testusers[3])); | |
778 | load_all_capabilities(); | |
779 | ||
780 | $contexts = $DB->get_records('context', array(), 'id'); | |
781 | $users = $DB->get_records('user', array(), 'id', 'id'); | |
782 | $capabilities = $DB->get_records('capabilities', array(), 'id'); | |
783 | $users[0] = null; // not-logged-in user | |
784 | $users[-1] = null; // non-existent user | |
785 | ||
786 | foreach ($contexts as $crecord) { | |
787 | $context = context::instance_by_id($crecord->id); | |
788 | if ($coursecontext = $context->get_course_context(false)) { | |
789 | $enrolled = get_enrolled_users($context); | |
790 | } else { | |
791 | $enrolled = array(); | |
792 | } | |
793 | foreach ($capabilities as $cap) { | |
794 | $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username'); | |
795 | if ($enrolled) { | |
796 | $enrolledwithcap = get_enrolled_users($context, $cap->name); | |
797 | } else { | |
798 | $enrolledwithcap = array(); | |
799 | } | |
800 | foreach ($users as $userid=>$unused) { | |
801 | if ($userid == 0 or isguestuser($userid)) { | |
802 | if ($userid == 0) { | |
803 | $CFG->forcelogin = true; | |
804 | $this->assertFalse(has_capability($cap->name, $context, $userid)); | |
805 | unset($CFG->forcelogin); | |
806 | } | |
807 | if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) { | |
808 | $this->assertFalse(has_capability($cap->name, $context, $userid)); | |
809 | } | |
810 | $this->assertFalse(isset($allowed[$userid])); | |
811 | } else { | |
812 | if (is_siteadmin($userid)) { | |
813 | $this->assertTrue(has_capability($cap->name, $context, $userid, true)); | |
814 | } | |
815 | $hascap = has_capability($cap->name, $context, $userid, false); | |
816 | $this->assertIdentical($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." "); | |
817 | if (isset($enrolled[$userid])) { | |
818 | $this->assertIdentical(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." "); | |
819 | } | |
820 | } | |
821 | } | |
822 | } | |
823 | } | |
824 | // Back to nobody | |
825 | $USER = new stdClass(); | |
826 | $USER->id = 0; | |
827 | unset($contexts); | |
828 | unset($users); | |
829 | unset($capabilities); | |
830 | ||
831 | // Now let's do all the remaining tests that break our carefully prepared fake site | |
832 | ||
833 | ||
834 | ||
835 | // ======= $context->mark_dirty() ======================================= | |
836 | ||
837 | $DB->delete_records('cache_flags', array()); | |
838 | accesslib_clear_all_caches(false); | |
839 | $systemcontext->mark_dirty(); | |
840 | $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2); | |
841 | $this->assertTrue(isset($dirty[$systemcontext->path])); | |
842 | $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path])); | |
843 | ||
844 | ||
845 | // ======= $context->reload_if_dirty(); ================================= | |
846 | ||
847 | $DB->delete_records('cache_flags', array()); | |
848 | accesslib_clear_all_caches(false); | |
849 | load_all_capabilities(); | |
850 | $context = context_course::instance($testcourses[2]); | |
851 | $page = $DB->get_record('page', array('course'=>$testcourses[2])); | |
852 | $pagecontext = context_module::instance($page->id); | |
853 | ||
854 | $context->mark_dirty(); | |
855 | $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path])); | |
856 | $USER->access['test'] = true; | |
857 | $context->reload_if_dirty(); | |
858 | $this->assertFalse(isset($USER->access['test'])); | |
859 | ||
860 | $context->mark_dirty(); | |
861 | $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path])); | |
862 | $USER->access['test'] = true; | |
863 | $pagecontext->reload_if_dirty(); | |
864 | $this->assertFalse(isset($USER->access['test'])); | |
865 | ||
866 | ||
867 | // ======= context_helper::build_all_paths() ============================ | |
868 | ||
869 | $oldcontexts = $DB->get_records('context', array(), 'id'); | |
870 | $DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM); | |
871 | $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM); | |
872 | context_helper::build_all_paths(); | |
873 | $newcontexts = $DB->get_records('context', array(), 'id'); | |
874 | $this->assertIdentical($oldcontexts, $newcontexts); | |
875 | unset($oldcontexts); | |
876 | unset($newcontexts); | |
877 | ||
878 | ||
879 | // ======= $context->reset_paths() ====================================== | |
880 | ||
881 | $context = context_course::instance($testcourses[2]); | |
882 | $children = $context->get_child_contexts(); | |
883 | $context->reset_paths(false); | |
884 | $this->assertIdentical($DB->get_field('context', 'path', array('id'=>$context->id)), NULL); | |
885 | $this->assertEqual($DB->get_field('context', 'depth', array('id'=>$context->id)), 0); | |
886 | foreach ($children as $child) { | |
887 | $this->assertIdentical($DB->get_field('context', 'path', array('id'=>$child->id)), NULL); | |
888 | $this->assertEqual($DB->get_field('context', 'depth', array('id'=>$child->id)), 0); | |
889 | } | |
890 | $this->assertEqual(count($children)+1, $DB->count_records('context', array('depth'=>0))); | |
891 | $this->assertEqual(count($children)+1, $DB->count_records('context', array('path'=>NULL))); | |
892 | ||
893 | $context = context_course::instance($testcourses[2]); | |
894 | $context->reset_paths(true); | |
895 | $context = context_course::instance($testcourses[2]); | |
896 | $this->assertEqual($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path); | |
897 | $this->assertEqual($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth); | |
898 | $this->assertEqual(0, $DB->count_records('context', array('depth'=>0))); | |
899 | $this->assertEqual(0, $DB->count_records('context', array('path'=>NULL))); | |
900 | ||
901 | ||
902 | // ====== $context->update_moved(); ====================================== | |
903 | ||
904 | accesslib_clear_all_caches(false); | |
905 | $DB->delete_records('cache_flags', array()); | |
906 | $course = $DB->get_record('course', array('id'=>$testcourses[0])); | |
907 | $context = context_course::instance($course->id); | |
908 | $oldpath = $context->path; | |
909 | $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); | |
910 | $categorycontext = context_coursecat::instance($miscid); | |
911 | $course->category = $miscid; | |
912 | $DB->update_record('course', $course); | |
913 | $context->update_moved($categorycontext); | |
914 | ||
915 | $context = context_course::instance($course->id); | |
916 | $this->assertIdentical($context->get_parent_context(), $categorycontext); | |
917 | $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2); | |
918 | $this->assertTrue(isset($dirty[$oldpath])); | |
919 | $this->assertTrue(isset($dirty[$context->path])); | |
920 | ||
921 | ||
922 | // ====== $context->delete_content() ===================================== | |
923 | ||
924 | context_helper::reset_caches(); | |
925 | $context = context_module::instance($testpages[3]); | |
926 | $this->assertTrue($DB->record_exists('context', array('id'=>$context->id))); | |
927 | $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id))); | |
928 | $context->delete_content(); | |
929 | $this->assertTrue($DB->record_exists('context', array('id'=>$context->id))); | |
930 | $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id))); | |
931 | ||
932 | ||
933 | // ====== $context->delete() ============================= | |
934 | ||
935 | context_helper::reset_caches(); | |
936 | $context = context_module::instance($testpages[4]); | |
937 | $this->assertTrue($DB->record_exists('context', array('id'=>$context->id))); | |
938 | $this->assertEqual(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id))); | |
939 | $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id)); | |
940 | $bicontext = context_block::instance($bi->id); | |
941 | $DB->delete_records('cache_flags', array()); | |
942 | $context->delete(); // should delete also linked blocks | |
943 | $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2); | |
944 | $this->assertTrue(isset($dirty[$context->path])); | |
945 | $this->assertFalse($DB->record_exists('context', array('id'=>$context->id))); | |
946 | $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id))); | |
947 | $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4]))); | |
948 | $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id))); | |
949 | $this->assertEqual(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id))); | |
950 | context_module::instance($testpages[4]); | |
951 | ||
952 | ||
953 | // ====== context_helper::delete_instance() ============================= | |
954 | ||
955 | context_helper::reset_caches(); | |
956 | $lastcourse = array_pop($testcourses); | |
957 | $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse))); | |
958 | $coursecontext = context_course::instance($lastcourse); | |
959 | $this->assertEqual(context_inspection::test_context_cache_size(), 1); | |
960 | $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE); | |
961 | $DB->delete_records('cache_flags', array()); | |
962 | context_helper::delete_instance(CONTEXT_COURSE, $lastcourse); | |
963 | $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2); | |
964 | $this->assertTrue(isset($dirty[$coursecontext->path])); | |
965 | $this->assertEqual(context_inspection::test_context_cache_size(), 0); | |
966 | $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse))); | |
967 | context_course::instance($lastcourse); | |
968 | ||
969 | ||
970 | // ======= context_helper::create_instances() ========================== | |
971 | ||
972 | $prevcount = $DB->count_records('context'); | |
973 | $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK)); | |
974 | context_helper::create_instances(null, true); | |
975 | $this->assertIdentical($DB->count_records('context'), $prevcount); | |
976 | $this->assertEqual($DB->count_records('context', array('depth'=>0)), 0); | |
977 | $this->assertEqual($DB->count_records('context', array('path'=>NULL)), 0); | |
978 | ||
979 | $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK)); | |
980 | $DB->delete_records('block_instances', array()); | |
981 | $prevcount = $DB->count_records('context'); | |
982 | $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM); | |
983 | context_helper::create_instances(null, true); | |
984 | $this->assertIdentical($DB->count_records('context'), $prevcount); | |
985 | $this->assertEqual($DB->count_records('context', array('depth'=>0)), 0); | |
986 | $this->assertEqual($DB->count_records('context', array('path'=>NULL)), 0); | |
987 | ||
988 | ||
989 | // ======= context_helper::cleanup_instances() ========================== | |
990 | ||
991 | $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}"); | |
992 | $DB->delete_records('course', array('id'=>$lastcourse)); | |
993 | $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}"); | |
994 | $DB->delete_records('course_categories', array('id'=>$lastcategory)); | |
995 | $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0"); | |
996 | $DB->delete_records('user', array('id'=>$lastuser)); | |
997 | $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id)); | |
998 | $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid)); | |
999 | context_helper::cleanup_instances(); | |
1000 | $count = 1; //system | |
1001 | $count += $DB->count_records('user', array('deleted'=>0)); | |
1002 | $count += $DB->count_records('course_categories'); | |
1003 | $count += $DB->count_records('course'); | |
1004 | $count += $DB->count_records('course_modules'); | |
1005 | $count += $DB->count_records('block_instances'); | |
1006 | $this->assertEqual($DB->count_records('context'), $count); | |
1007 | ||
1008 | ||
1009 | // ======= context cache size restrictions ============================== | |
1010 | ||
1011 | $testusers= array(); | |
1012 | for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) { | |
1013 | $user = new stdClass(); | |
1014 | $user->auth = 'manual'; | |
1015 | $user->firstname = 'xuser'.$i; | |
1016 | $user->lastname = 'xuser'.$i; | |
1017 | $user->username = 'xuser'.$i; | |
1018 | $user->password = 'doesnotexist'; | |
1019 | $user->email = "xuser$i@example.com"; | |
1020 | $user->confirmed = 1; | |
1021 | $user->mnethostid = $CFG->mnet_localhost_id; | |
1022 | $user->lang = $CFG->lang; | |
1023 | $user->maildisplay = 1; | |
1024 | $user->timemodified = time(); | |
1025 | $user->lastip = '0.0.0.0'; | |
1026 | $userid = $DB->insert_record('user', $user); | |
1027 | $testusers[$i] = $userid; | |
1028 | } | |
1029 | context_helper::create_instances(null, true); | |
1030 | context_helper::reset_caches(); | |
1031 | for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) { | |
1032 | context_user::instance($testusers[$i]); | |
1033 | if ($i == CONTEXT_CACHE_MAX_SIZE - 1) { | |
1034 | $this->assertEqual(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE); | |
1035 | } else if ($i == CONTEXT_CACHE_MAX_SIZE) { | |
1036 | // once the limit is reached roughly 1/3 of records should be removed from cache | |
1037 | $this->assertEqual(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102)); | |
1038 | } | |
1039 | } | |
1040 | // We keep the first 100 cached | |
1041 | $prevsize = context_inspection::test_context_cache_size(); | |
1042 | for ($i=0; $i<100; $i++) { | |
1043 | context_user::instance($testusers[$i]); | |
1044 | $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize); | |
1045 | } | |
1046 | context_user::instance($testusers[102]); | |
1047 | $this->assertEqual(context_inspection::test_context_cache_size(), $prevsize+1); | |
1048 | unset($testusers); | |
1049 | ||
1050 | ||
1051 | ||
1052 | // ================================================================= | |
1053 | // ======= basic test of legacy functions ========================== | |
1054 | // ================================================================= | |
1055 | // note: watch out, the fake site might be pretty borked already | |
1056 | ||
1057 | $this->assertIdentical(get_system_context(), context_system::instance()); | |
1058 | ||
1059 | foreach ($DB->get_records('context') as $contextid=>$record) { | |
1060 | $context = context::instance_by_id($contextid); | |
1061 | $this->assertIdentical(get_context_instance_by_id($contextid), $context); | |
1062 | $this->assertIdentical(get_context_instance($record->contextlevel, $record->instanceid), $context); | |
1063 | $this->assertIdentical(get_parent_contexts($context), $context->get_parent_context_ids()); | |
1064 | if ($context->id == SYSCONTEXTID) { | |
1065 | $this->assertIdentical(get_parent_contextid($context), false); | |
1066 | } else { | |
1067 | $this->assertIdentical(get_parent_contextid($context), $context->get_parent_context()->id); | |
1068 | } | |
1069 | } | |
1070 | ||
1071 | $children = get_child_contexts($systemcontext); | |
1072 | $this->assertEqual(count($children), $DB->count_records('context')-1); | |
1073 | unset($children); | |
1074 | ||
1075 | $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK)); | |
1076 | create_contexts(); | |
1077 | $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK))); | |
1078 | ||
1079 | $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK)); | |
1080 | build_context_path(); | |
1081 | $this->assertFalse($DB->record_exists('context', array('depth'=>0))); | |
1082 | ||
1083 | $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}"); | |
1084 | $DB->delete_records('course', array('id'=>$lastcourse)); | |
1085 | $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}"); | |
1086 | $DB->delete_records('course_categories', array('id'=>$lastcategory)); | |
1087 | $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0"); | |
1088 | $DB->delete_records('user', array('id'=>$lastuser)); | |
1089 | $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id)); | |
1090 | $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid)); | |
1091 | cleanup_contexts(); | |
1092 | $count = 1; //system | |
1093 | $count += $DB->count_records('user', array('deleted'=>0)); | |
1094 | $count += $DB->count_records('course_categories'); | |
1095 | $count += $DB->count_records('course'); | |
1096 | $count += $DB->count_records('course_modules'); | |
1097 | $count += $DB->count_records('block_instances'); | |
1098 | $this->assertEqual($DB->count_records('context'), $count); | |
1099 | ||
1100 | context_helper::reset_caches(); | |
1101 | preload_course_contexts($SITE->id); | |
1102 | $this->assertEqual(context_inspection::test_context_cache_size(), 1); | |
1103 | ||
1104 | context_helper::reset_caches(); | |
1105 | list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx'); | |
1106 | $sql = "SELECT c.id $select FROM {course_categories} c $join"; | |
1107 | $records = $DB->get_records_sql($sql); | |
1108 | foreach ($records as $record) { | |
1109 | context_instance_preload($record); | |
1110 | $record = (array)$record; | |
1111 | $this->assertEqual(1, count($record)); // only id left | |
1112 | } | |
1113 | $this->assertEqual(count($records), context_inspection::test_context_cache_size()); | |
1114 | ||
1115 | accesslib_clear_all_caches(true); | |
1116 | $DB->delete_records('cache_flags', array()); | |
1117 | mark_context_dirty($systemcontext->path); | |
1118 | $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2); | |
1119 | $this->assertTrue(isset($dirty[$systemcontext->path])); | |
1120 | ||
1121 | accesslib_clear_all_caches(false); | |
1122 | $DB->delete_records('cache_flags', array()); | |
1123 | $course = $DB->get_record('course', array('id'=>$testcourses[2])); | |
1124 | $context = get_context_instance(CONTEXT_COURSE, $course->id); | |
1125 | $oldpath = $context->path; | |
1126 | $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); | |
1127 | $categorycontext = context_coursecat::instance($miscid); | |
1128 | $course->category = $miscid; | |
1129 | $DB->update_record('course', $course); | |
1130 | context_moved($context, $categorycontext); | |
1131 | $context = get_context_instance(CONTEXT_COURSE, $course->id); | |
1132 | $this->assertIdentical($context->get_parent_context(), $categorycontext); | |
1133 | ||
1134 | $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2]))); | |
1135 | delete_context(CONTEXT_COURSE, $testcourses[2]); | |
1136 | $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2]))); | |
1137 | ||
1138 | $name = get_contextlevel_name(CONTEXT_COURSE); | |
1139 | $this->assertFalse(empty($name)); | |
1140 | ||
1141 | $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]); | |
1142 | $name = print_context_name($context); | |
1143 | $this->assertFalse(empty($name)); | |
1144 | ||
1145 | $url = get_context_url($coursecontext); | |
1146 | $this->assertFalse($url instanceof modole_url); | |
1147 | ||
1148 | $page = $DB->get_record('page', array('id'=>$testpages[7])); | |
1149 | $context = get_context_instance(CONTEXT_MODULE, $page->id); | |
1150 | $coursecontext = get_course_context($context); | |
1151 | $this->assertEqual($coursecontext->contextlevel, CONTEXT_COURSE); | |
1152 | $this->assertEqual(get_courseid_from_context($context), $page->course); | |
1153 | ||
1154 | $caps = fetch_context_capabilities($systemcontext); | |
1155 | $this->assertTrue(is_array($caps)); | |
1156 | unset($caps); | |
1157 | } | |
1158 | ||
1159 | public function tearDown() { | |
1160 | global $USER, $SITE; | |
1161 | if (isset($this->accesslibprevuser)) { | |
1162 | $USER = $this->accesslibprevuser; | |
1163 | } | |
1164 | if (isset($this->accesslibprevsite)) { | |
1165 | $SITE = $this->accesslibprevsite; | |
1166 | } | |
1167 | ||
1168 | ||
1169 | parent::tearDown(); | |
1170 | } | |
1171 | } | |
1172 |