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