Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for the base_block class. 19 * 20 * @package core_search 21 * @copyright 2017 The Open University 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 require_once (__DIR__ . '/fixtures/testable_core_search.php'); 28 require_once (__DIR__ . '/fixtures/mock_block_area.php'); 29 30 /** 31 * Unit tests for the base_block class. 32 * 33 * @package core_search 34 * @copyright 2017 The Open University 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 */ 37 class base_block_testcase extends advanced_testcase { 38 /** 39 * Tests getting the name out of the class name. 40 */ 41 public function test_get_block_name() { 42 $area = new \block_mockblock\search\area(); 43 $this->assertEquals('mockblock', $area->get_block_name()); 44 } 45 46 /** 47 * Tests getting the recordset. 48 */ 49 public function test_get_document_recordset() { 50 global $DB, $USER; 51 52 $this->resetAfterTest(); 53 $this->setAdminUser(); 54 55 // Create course and activity module. 56 $generator = $this->getDataGenerator(); 57 $course = $generator->create_course(); 58 $coursecontext = \context_course::instance($course->id); 59 $page = $generator->create_module('page', ['course' => $course->id]); 60 $pagecontext = \context_module::instance($page->cmid); 61 62 // Create another 2 courses (in same category and in a new category). 63 $cat1context = \context_coursecat::instance($course->category); 64 $course2 = $generator->create_course(); 65 $course2context = \context_course::instance($course2->id); 66 $cat2 = $generator->create_category(); 67 $cat2context = \context_coursecat::instance($cat2->id); 68 $course3 = $generator->create_course(['category' => $cat2->id]); 69 $course3context = \context_course::instance($course3->id); 70 71 // Add blocks by hacking table (because it's not a real block type). 72 73 // 1. Block on course page. 74 $configdata = base64_encode(serialize((object) ['example' => 'content'])); 75 $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id, 76 'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 77 'defaultweight' => 0, 'timecreated' => 1, 'timemodified' => 1, 78 'configdata' => $configdata]; 79 $block1id = $DB->insert_record('block_instances', $instance); 80 $block1context = \context_block::instance($block1id); 81 82 // 2. Block on activity page. 83 $instance->parentcontextid = $pagecontext->id; 84 $instance->pagetypepattern = 'mod-page-view'; 85 $instance->timemodified = 2; 86 $block2id = $DB->insert_record('block_instances', $instance); 87 \context_block::instance($block2id); 88 89 // 3. Block on site context. 90 $sitecourse = get_site(); 91 $sitecontext = \context_course::instance($sitecourse->id); 92 $instance->parentcontextid = $sitecontext->id; 93 $instance->pagetypepattern = 'site-index'; 94 $instance->timemodified = 3; 95 $block3id = $DB->insert_record('block_instances', $instance); 96 $block3context = \context_block::instance($block3id); 97 98 // 4. Block on course page but no data. 99 $instance->parentcontextid = $coursecontext->id; 100 $instance->pagetypepattern = 'course-view-*'; 101 unset($instance->configdata); 102 $instance->timemodified = 4; 103 $block4id = $DB->insert_record('block_instances', $instance); 104 \context_block::instance($block4id); 105 106 // 5. Block on course page but not this block. 107 $instance->blockname = 'mockotherblock'; 108 $instance->configdata = $configdata; 109 $instance->timemodified = 5; 110 $block5id = $DB->insert_record('block_instances', $instance); 111 \context_block::instance($block5id); 112 113 // 6. Block on course page with '*' page type. 114 $instance->blockname = 'mockblock'; 115 $instance->pagetypepattern = '*'; 116 $instance->timemodified = 6; 117 $block6id = $DB->insert_record('block_instances', $instance); 118 \context_block::instance($block6id); 119 120 // 7. Block on course page with 'course-*' page type. 121 $instance->pagetypepattern = 'course-*'; 122 $instance->timemodified = 7; 123 $block7id = $DB->insert_record('block_instances', $instance); 124 \context_block::instance($block7id); 125 126 // 8. Block on course 2. 127 $instance->parentcontextid = $course2context->id; 128 $instance->timemodified = 8; 129 $block8id = $DB->insert_record('block_instances', $instance); 130 \context_block::instance($block8id); 131 132 // 9. Block on course 3. 133 $instance->parentcontextid = $course3context->id; 134 $instance->timemodified = 9; 135 $block9id = $DB->insert_record('block_instances', $instance); 136 \context_block::instance($block9id); 137 138 // Get all the blocks. 139 $area = new block_mockblock\search\area(); 140 $results = self::recordset_to_indexed_array($area->get_document_recordset()); 141 142 // Only blocks 1, 3, 6, 7, 8, 9 should be returned. Check all the fields for the first two. 143 $this->assertCount(6, $results); 144 145 $this->assertEquals($block1id, $results[0]->id); 146 $this->assertEquals(1, $results[0]->timemodified); 147 $this->assertEquals(1, $results[0]->timecreated); 148 $this->assertEquals($configdata, $results[0]->configdata); 149 $this->assertEquals($course->id, $results[0]->courseid); 150 $this->assertEquals($block1context->id, $results[0]->contextid); 151 152 $this->assertEquals($block3id, $results[1]->id); 153 $this->assertEquals(3, $results[1]->timemodified); 154 $this->assertEquals(1, $results[1]->timecreated); 155 $this->assertEquals($configdata, $results[1]->configdata); 156 $this->assertEquals($sitecourse->id, $results[1]->courseid); 157 $this->assertEquals($block3context->id, $results[1]->contextid); 158 159 // For the later ones, just check it got the right ones! 160 $this->assertEquals($block6id, $results[2]->id); 161 $this->assertEquals($block7id, $results[3]->id); 162 $this->assertEquals($block8id, $results[4]->id); 163 $this->assertEquals($block9id, $results[5]->id); 164 165 // Repeat with a time restriction. 166 $results = self::recordset_to_indexed_array($area->get_document_recordset(2)); 167 168 // Only block 3, 6, 7, 8, and 9 are returned. 169 $this->assertEquals([$block3id, $block6id, $block7id, $block8id, $block9id], 170 self::records_to_ids($results)); 171 172 // Now use context restrictions. First, the whole site (no change). 173 $results = self::recordset_to_indexed_array($area->get_document_recordset( 174 0, context_system::instance())); 175 $this->assertEquals([$block1id, $block3id, $block6id, $block7id, $block8id, $block9id], 176 self::records_to_ids($results)); 177 178 // Course page only (leave out the one on site page and other courses). 179 $results = self::recordset_to_indexed_array($area->get_document_recordset( 180 0, $coursecontext)); 181 $this->assertEquals([$block1id, $block6id, $block7id], 182 self::records_to_ids($results)); 183 184 // Other course page only. 185 $results = self::recordset_to_indexed_array($area->get_document_recordset( 186 0, $course2context)); 187 $this->assertEquals([$block8id], self::records_to_ids($results)); 188 189 // Activity module only (no results). 190 $results = self::recordset_to_indexed_array($area->get_document_recordset( 191 0, $pagecontext)); 192 $this->assertCount(0, $results); 193 194 // Specific block context. 195 $results = self::recordset_to_indexed_array($area->get_document_recordset( 196 0, $block3context)); 197 $this->assertEquals([$block3id], self::records_to_ids($results)); 198 199 // User context (no results). 200 $usercontext = context_user::instance($USER->id); 201 $results = self::recordset_to_indexed_array($area->get_document_recordset( 202 0, $usercontext)); 203 $this->assertCount(0, $results); 204 205 // Category 1 context (courses 1 and 2). 206 $results = self::recordset_to_indexed_array($area->get_document_recordset( 207 0, $cat1context)); 208 $this->assertEquals([$block1id, $block6id, $block7id, $block8id], 209 self::records_to_ids($results)); 210 211 // Category 2 context (course 3). 212 $results = self::recordset_to_indexed_array($area->get_document_recordset( 213 0, $cat2context)); 214 $this->assertEquals([$block9id], self::records_to_ids($results)); 215 216 // Combine context restriction (category 1) with timemodified. 217 $results = self::recordset_to_indexed_array($area->get_document_recordset( 218 7, $cat1context)); 219 $this->assertEquals([$block7id, $block8id], self::records_to_ids($results)); 220 } 221 222 /** 223 * Utility function to convert recordset to array for testing. 224 * 225 * @param moodle_recordset $rs Recordset to convert 226 * @return array Array indexed by number (0, 1, 2, ...) 227 */ 228 protected static function recordset_to_indexed_array(moodle_recordset $rs) { 229 $results = []; 230 foreach ($rs as $rec) { 231 $results[] = $rec; 232 } 233 $rs->close(); 234 return $results; 235 } 236 237 /** 238 * Utility function to convert records to array of IDs. 239 * 240 * @param array $recs Records which should have an 'id' field 241 * @return array Array of ids 242 */ 243 protected static function records_to_ids(array $recs) { 244 $ids = []; 245 foreach ($recs as $rec) { 246 $ids[] = $rec->id; 247 } 248 return $ids; 249 } 250 251 /** 252 * Tests the get_doc_url function. 253 */ 254 public function test_get_doc_url() { 255 global $DB; 256 257 $this->resetAfterTest(); 258 259 // Create course and activity module. 260 $generator = $this->getDataGenerator(); 261 $course = $generator->create_course(); 262 $coursecontext = \context_course::instance($course->id); 263 $page = $generator->create_module('page', ['course' => $course->id]); 264 $pagecontext = \context_module::instance($page->cmid); 265 266 // Create block on course page. 267 $configdata = base64_encode(serialize(new \stdClass())); 268 $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id, 269 'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 'defaultweight' => 0, 270 'timecreated' => 1, 'timemodified' => 1, 'configdata' => $configdata]; 271 $blockid = $DB->insert_record('block_instances', $instance); 272 273 // Get document URL. 274 $area = new block_mockblock\search\area(); 275 $doc = $this->get_doc($course->id, $blockid); 276 $expected = new moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $blockid); 277 $this->assertEquals($expected, $area->get_doc_url($doc)); 278 $this->assertEquals($expected, $area->get_context_url($doc)); 279 280 // Repeat with block on site page. 281 $sitecourse = get_site(); 282 $sitecontext = \context_course::instance($sitecourse->id); 283 $instance->pagetypepattern = 'site-index'; 284 $instance->parentcontextid = $sitecontext->id; 285 $block2id = $DB->insert_record('block_instances', $instance); 286 287 // Get document URL. 288 $doc2 = $this->get_doc($course->id, $block2id); 289 $expected = new moodle_url('/', ['redirect' => 0], 'inst' . $block2id); 290 $this->assertEquals($expected, $area->get_doc_url($doc2)); 291 $this->assertEquals($expected, $area->get_context_url($doc2)); 292 293 // Repeat with block on module page (this cannot happen yet because the search query will 294 // only include course context blocks, but let's check it works for the future). 295 $instance->pagetypepattern = 'mod-page-view'; 296 $instance->parentcontextid = $pagecontext->id; 297 $block3id = $DB->insert_record('block_instances', $instance); 298 299 // Get and check document URL, ignoring debugging message for unsupported page type. 300 $debugmessage = 'Unexpected module-level page type for block ' . $block3id . 301 ': mod-page-view'; 302 $doc3 = $this->get_doc($course->id, $block3id); 303 $this->assertDebuggingCalledCount(2, [$debugmessage, $debugmessage]); 304 305 $expected = new moodle_url('/mod/page/view.php', ['id' => $page->cmid], 'inst' . $block3id); 306 $this->assertEquals($expected, $area->get_doc_url($doc3)); 307 $this->assertDebuggingCalled($debugmessage); 308 $this->assertEquals($expected, $area->get_context_url($doc3)); 309 $this->assertDebuggingCalled($debugmessage); 310 311 // Repeat with another block on course page but '*' pages. 312 $instance->pagetypepattern = '*'; 313 $instance->parentcontextid = $coursecontext->id; 314 $block4id = $DB->insert_record('block_instances', $instance); 315 316 // Get document URL. 317 $doc = $this->get_doc($course->id, $block4id); 318 $expected = new moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $block4id); 319 $this->assertEquals($expected, $area->get_doc_url($doc)); 320 $this->assertEquals($expected, $area->get_context_url($doc)); 321 322 // And same thing but 'course-*' pages. 323 $instance->pagetypepattern = 'course-*'; 324 $block5id = $DB->insert_record('block_instances', $instance); 325 326 // Get document URL. 327 $doc = $this->get_doc($course->id, $block5id); 328 $expected = new moodle_url('/course/view.php', ['id' => $course->id], 'inst' . $block5id); 329 $this->assertEquals($expected, $area->get_doc_url($doc)); 330 $this->assertEquals($expected, $area->get_context_url($doc)); 331 } 332 333 /** 334 * Tests the check_access function. 335 */ 336 public function test_check_access() { 337 global $DB; 338 339 $this->resetAfterTest(); 340 341 // Create course and activity module. 342 $generator = $this->getDataGenerator(); 343 $course = $generator->create_course(); 344 $coursecontext = \context_course::instance($course->id); 345 $page = $generator->create_module('page', ['course' => $course->id]); 346 $pagecontext = \context_module::instance($page->cmid); 347 348 // Create block on course page. 349 $configdata = base64_encode(serialize(new \stdClass())); 350 $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id, 351 'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 'defaultweight' => 0, 352 'timecreated' => 1, 'timemodified' => 1, 'configdata' => $configdata]; 353 $blockid = $DB->insert_record('block_instances', $instance); 354 355 // Check access for block that exists. 356 $area = new block_mockblock\search\area(); 357 $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid)); 358 359 // Check access for nonexistent block. 360 $this->assertEquals(\core_search\manager::ACCESS_DELETED, $area->check_access($blockid + 1)); 361 362 // Check if block is not in a course context any longer. 363 $DB->set_field('block_instances', 'parentcontextid', $pagecontext->id, ['id' => $blockid]); 364 \core_search\base_block::clear_static(); 365 $this->assertEquals(\core_search\manager::ACCESS_DELETED, $area->check_access($blockid)); 366 367 // Or what if it is in a course context but has supported vs. unsupported page type. 368 $DB->set_field('block_instances', 'parentcontextid', $coursecontext->id, ['id' => $blockid]); 369 370 $DB->set_field('block_instances', 'pagetypepattern', 'course-*', ['id' => $blockid]); 371 \core_search\base_block::clear_static(); 372 $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid)); 373 374 $DB->set_field('block_instances', 'pagetypepattern', '*', ['id' => $blockid]); 375 \core_search\base_block::clear_static(); 376 $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid)); 377 378 $DB->set_field('block_instances', 'pagetypepattern', 'course-view-frogs', ['id' => $blockid]); 379 \core_search\base_block::clear_static(); 380 $this->assertEquals(\core_search\manager::ACCESS_GRANTED, $area->check_access($blockid)); 381 382 $DB->set_field('block_instances', 'pagetypepattern', 'anythingelse', ['id' => $blockid]); 383 \core_search\base_block::clear_static(); 384 $this->assertEquals(\core_search\manager::ACCESS_DELETED, $area->check_access($blockid)); 385 } 386 387 /** 388 * Tests the block version of get_contexts_to_reindex, which is supposed to return all the 389 * block contexts in order of date added. 390 */ 391 public function test_get_contexts_to_reindex() { 392 global $DB; 393 394 $this->resetAfterTest(); 395 396 // Create course and activity module. 397 $generator = $this->getDataGenerator(); 398 $course = $generator->create_course(); 399 $coursecontext = \context_course::instance($course->id); 400 $page = $generator->create_module('page', ['course' => $course->id]); 401 $pagecontext = \context_module::instance($page->cmid); 402 403 // Create blocks on course page, with time modified non-sequential. 404 $configdata = base64_encode(serialize(new \stdClass())); 405 $instance = (object)['blockname' => 'mockblock', 'parentcontextid' => $coursecontext->id, 406 'showinsubcontexts' => 0, 'pagetypepattern' => 'course-view-*', 'defaultweight' => 0, 407 'timecreated' => 1, 'timemodified' => 100, 'configdata' => $configdata]; 408 $blockid1 = $DB->insert_record('block_instances', $instance); 409 $context1 = \context_block::instance($blockid1); 410 $instance->timemodified = 120; 411 $blockid2 = $DB->insert_record('block_instances', $instance); 412 $context2 = \context_block::instance($blockid2); 413 $instance->timemodified = 110; 414 $blockid3 = $DB->insert_record('block_instances', $instance); 415 $context3 = \context_block::instance($blockid3); 416 417 // Create another block on the activity page (not included). 418 $instance->parentcontextid = $pagecontext->id; 419 $blockid4 = $DB->insert_record('block_instances', $instance); 420 \context_block::instance($blockid4); 421 422 // Check list of contexts. 423 $area = new block_mockblock\search\area(); 424 $contexts = iterator_to_array($area->get_contexts_to_reindex(), false); 425 $expected = [ 426 $context2, 427 $context3, 428 $context1 429 ]; 430 $this->assertEquals($expected, $contexts); 431 } 432 433 /** 434 * Gets a search document object from the fake search area. 435 * 436 * @param int $courseid Course id in document 437 * @param int $blockinstanceid Block instance id in document 438 * @return \core_search\document Document object 439 */ 440 protected function get_doc($courseid, $blockinstanceid) { 441 $engine = testable_core_search::instance()->get_engine(); 442 $area = new block_mockblock\search\area(); 443 $docdata = ['id' => $blockinstanceid, 'courseid' => $courseid, 444 'areaid' => $area->get_area_id(), 'itemid' => 0]; 445 return $engine->to_document($area, $docdata); 446 } 447 448 /** 449 * Test document icon. 450 */ 451 public function test_get_doc_icon() { 452 $baseblock = $this->getMockBuilder('\core_search\base_block') 453 ->disableOriginalConstructor() 454 ->getMockForAbstractClass(); 455 456 $document = $this->getMockBuilder('\core_search\document') 457 ->disableOriginalConstructor() 458 ->getMock(); 459 460 $result = $baseblock->get_doc_icon($document); 461 462 $this->assertEquals('e/anchor', $result->get_name()); 463 $this->assertEquals('moodle', $result->get_component()); 464 } 465 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body