See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 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_block; 18 19 use core_block_external; 20 use externallib_advanced_testcase; 21 22 defined('MOODLE_INTERNAL') || die(); 23 24 global $CFG; 25 26 require_once($CFG->dirroot . '/webservice/tests/helpers.php'); 27 require_once($CFG->dirroot . '/my/lib.php'); 28 29 /** 30 * External block functions unit tests 31 * 32 * @package core_block 33 * @category external 34 * @copyright 2015 Juan Leyva <juan@moodle.com> 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 * @since Moodle 3.0 37 */ 38 class externallib_test extends externallib_advanced_testcase { 39 40 /** 41 * Test get_course_blocks 42 */ 43 public function test_get_course_blocks() { 44 global $DB, $FULLME; 45 46 $this->resetAfterTest(true); 47 48 $user = $this->getDataGenerator()->create_user(); 49 $course = $this->getDataGenerator()->create_course(); 50 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 51 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 52 53 $page = new \moodle_page(); 54 $page->set_context(\context_course::instance($course->id)); 55 $page->set_pagelayout('course'); 56 $course->format = course_get_format($course)->get_format(); 57 $page->set_pagetype('course-view-' . $course->format); 58 $page->blocks->load_blocks(); 59 $newblock = 'calendar_upcoming'; 60 $page->blocks->add_block_at_end_of_default_region($newblock); 61 $this->setUser($user); 62 63 // Check for the new block. 64 $result = core_block_external::get_course_blocks($course->id); 65 // We need to execute the return values cleaning process to simulate the web service server. 66 $result = \external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result); 67 68 // Expect the new block. 69 $this->assertCount(1, $result['blocks']); 70 $this->assertEquals($newblock, $result['blocks'][0]['name']); 71 } 72 73 /** 74 * Test get_course_blocks on site home 75 */ 76 public function test_get_course_blocks_site_home() { 77 global $DB, $FULLME; 78 79 $this->resetAfterTest(true); 80 81 $user = $this->getDataGenerator()->create_user(); 82 83 $page = new \moodle_page(); 84 $page->set_context(\context_course::instance(SITEID)); 85 $page->set_pagelayout('frontpage'); 86 $page->set_pagetype('site-index'); 87 $page->blocks->load_blocks(); 88 $newblock = 'calendar_upcoming'; 89 $page->blocks->add_block_at_end_of_default_region($newblock); 90 $this->setUser($user); 91 92 // Check for the new block. 93 $result = core_block_external::get_course_blocks(SITEID); 94 // We need to execute the return values cleaning process to simulate the web service server. 95 $result = \external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result); 96 97 // Expect the new block. 98 $this->assertCount(1, $result['blocks']); 99 $this->assertEquals($newblock, $result['blocks'][0]['name']); 100 } 101 102 /** 103 * Test get_course_blocks 104 */ 105 public function test_get_course_blocks_overrides() { 106 global $DB, $CFG, $FULLME; 107 108 $this->resetAfterTest(true); 109 110 $CFG->defaultblocks_override = 'search_forums,course_list:calendar_upcoming,recent_activity'; 111 112 $user = $this->getDataGenerator()->create_user(); 113 $course = $this->getDataGenerator()->create_course(); 114 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 115 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 116 117 $this->setUser($user); 118 119 // Try default blocks. 120 $result = core_block_external::get_course_blocks($course->id); 121 // We need to execute the return values cleaning process to simulate the web service server. 122 $result = \external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result); 123 124 // Expect 4 default blocks. 125 $this->assertCount(4, $result['blocks']); 126 127 $expectedblocks = array('navigation', 'settings', 'search_forums', 'course_list', 128 'calendar_upcoming', 'recent_activity'); 129 foreach ($result['blocks'] as $block) { 130 if (!in_array($block['name'], $expectedblocks)) { 131 $this->fail("Unexpected block found: " . $block['name']); 132 } 133 } 134 135 } 136 137 /** 138 * Test get_course_blocks contents 139 */ 140 public function test_get_course_blocks_contents() { 141 global $DB, $FULLME; 142 143 $this->resetAfterTest(true); 144 145 $user = $this->getDataGenerator()->create_user(); 146 $course = $this->getDataGenerator()->create_course(); 147 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 148 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 149 $coursecontext = \context_course::instance($course->id); 150 151 // Create a HTML block. 152 $title = 'Some course info'; 153 $body = 'Some course info<br /><p>Some contents</p>'; 154 $bodyformat = FORMAT_MOODLE; 155 $page = new \moodle_page(); 156 $page->set_context($coursecontext); 157 $page->set_pagelayout('course'); 158 $course->format = course_get_format($course)->get_format(); 159 $page->set_pagetype('course-view-' . $course->format); 160 $page->blocks->load_blocks(); 161 $newblock = 'html'; 162 $page->blocks->add_block_at_end_of_default_region($newblock); 163 164 $this->setUser($user); 165 // Re-create the page. 166 $page = new \moodle_page(); 167 $page->set_context($coursecontext); 168 $page->set_pagelayout('course'); 169 $course->format = course_get_format($course)->get_format(); 170 $page->set_pagetype('course-view-' . $course->format); 171 $page->blocks->load_blocks(); 172 $blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region()); 173 $block = end($blocks); 174 $block = block_instance('html', $block->instance); 175 $nonscalar = [ 176 'something' => true, 177 ]; 178 $configdata = (object) [ 179 'title' => $title, 180 'text' => [ 181 'itemid' => 0, 182 'text' => $body, 183 'format' => $bodyformat, 184 ], 185 'nonscalar' => $nonscalar 186 ]; 187 $block->instance_config_save((object) $configdata); 188 $filename = 'img.png'; 189 $filerecord = array( 190 'contextid' => \context_block::instance($block->instance->id)->id, 191 'component' => 'block_html', 192 'filearea' => 'content', 193 'itemid' => 0, 194 'filepath' => '/', 195 'filename' => $filename, 196 ); 197 // Create an area to upload the file. 198 $fs = get_file_storage(); 199 // Create a file from the string that we made earlier. 200 $file = $fs->create_file_from_string($filerecord, 'some fake content (should be an image).'); 201 202 // Check for the new block. 203 $result = core_block_external::get_course_blocks($course->id, true); 204 // We need to execute the return values cleaning process to simulate the web service server. 205 $result = \external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result); 206 207 // Expect the new block. 208 $this->assertCount(1, $result['blocks']); 209 $this->assertEquals($title, $result['blocks'][0]['contents']['title']); 210 $this->assertEquals($body, $result['blocks'][0]['contents']['content']); 211 $this->assertEquals(FORMAT_HTML, $result['blocks'][0]['contents']['contentformat']); // Format change for external. 212 $this->assertEquals('', $result['blocks'][0]['contents']['footer']); 213 $this->assertCount(1, $result['blocks'][0]['contents']['files']); 214 $this->assertEquals($newblock, $result['blocks'][0]['name']); 215 $configcounts = 0; 216 foreach ($result['blocks'][0]['configs'] as $config) { 217 if ($config['type'] = 'plugin' && $config['name'] == 'allowcssclasses' && $config['value'] == json_encode('0')) { 218 $configcounts++; 219 } else if ($config['type'] = 'instance' && $config['name'] == 'text' && $config['value'] == json_encode($body)) { 220 $configcounts++; 221 } else if ($config['type'] = 'instance' && $config['name'] == 'title' && $config['value'] == json_encode($title)) { 222 $configcounts++; 223 } else if ($config['type'] = 'instance' && $config['name'] == 'format' && $config['value'] == json_encode('0')) { 224 $configcounts++; 225 } else if ($config['type'] = 'instance' && $config['name'] == 'nonscalar' && 226 $config['value'] == json_encode($nonscalar)) { 227 $configcounts++; 228 } 229 } 230 $this->assertEquals(5, $configcounts); 231 } 232 233 /** 234 * Test get_course_blocks contents with mathjax. 235 */ 236 public function test_get_course_blocks_contents_with_mathjax() { 237 global $DB, $CFG; 238 239 require_once($CFG->dirroot . '/lib/externallib.php'); 240 241 $this->resetAfterTest(true); 242 243 // Enable MathJax filter in content and headings. 244 $this->configure_filters([ 245 ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true], 246 ]); 247 248 // Create a few stuff to test with. 249 $user = $this->getDataGenerator()->create_user(); 250 $course = $this->getDataGenerator()->create_course(); 251 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 252 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 253 $coursecontext = \context_course::instance($course->id); 254 255 // Create a HTML block. 256 $title = 'My block $$(a+b)=2$$'; 257 $body = 'My block contents $$(a+b)=2$$'; 258 $bodyformat = FORMAT_MOODLE; 259 $page = new \moodle_page(); 260 $page->set_context($coursecontext); 261 $page->set_pagelayout('course'); 262 $course->format = course_get_format($course)->get_format(); 263 $page->set_pagetype('course-view-' . $course->format); 264 $page->blocks->load_blocks(); 265 $newblock = 'html'; 266 $page->blocks->add_block_at_end_of_default_region($newblock); 267 268 $this->setUser($user); 269 // Re-create the page. 270 $page = new \moodle_page(); 271 $page->set_context($coursecontext); 272 $page->set_pagelayout('course'); 273 $course->format = course_get_format($course)->get_format(); 274 $page->set_pagetype('course-view-' . $course->format); 275 $page->blocks->load_blocks(); 276 $blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region()); 277 $block = end($blocks); 278 $block = block_instance('html', $block->instance); 279 $nonscalar = [ 280 'something' => true, 281 ]; 282 $configdata = (object) [ 283 'title' => $title, 284 'text' => [ 285 'itemid' => 0, 286 'text' => $body, 287 'format' => $bodyformat, 288 ], 289 'nonscalar' => $nonscalar 290 ]; 291 $block->instance_config_save((object) $configdata); 292 293 // Check for the new block. 294 $result = core_block_external::get_course_blocks($course->id, true); 295 $result = \external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result); 296 297 // Format the original data. 298 $sitecontext = \context_system::instance(); 299 $title = external_format_string($title, $coursecontext->id); 300 list($body, $bodyformat) = external_format_text($body, $bodyformat, $coursecontext->id, 'block_html', 'content'); 301 302 // Check that the block data is formatted. 303 $this->assertCount(1, $result['blocks']); 304 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', 305 $result['blocks'][0]['contents']['title']); 306 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', 307 $result['blocks'][0]['contents']['content']); 308 $this->assertEquals($title, $result['blocks'][0]['contents']['title']); 309 $this->assertEquals($body, $result['blocks'][0]['contents']['content']); 310 } 311 312 /** 313 * Test user get default dashboard blocks. 314 */ 315 public function test_get_dashboard_blocks_default_dashboard() { 316 global $PAGE, $DB; 317 $this->resetAfterTest(true); 318 319 $user = $this->getDataGenerator()->create_user(); 320 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 321 322 // Force a setting change to check the returned blocks settings. 323 set_config('displaycategories', 0, 'block_myoverview'); 324 325 $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true)); 326 // Get the expected default blocks. 327 $alldefaultblocksordered = $DB->get_records_menu( 328 'block_instances', 329 array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id), 330 'defaultregion, defaultweight ASC', 331 'id, blockname' 332 ); 333 334 $this->setUser($user); 335 336 // Check for the default blocks. 337 $result = core_block_external::get_dashboard_blocks($user->id); 338 // We need to execute the return values cleaning process to simulate the web service server. 339 $result = \external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 340 // Expect all default blocks defined in blocks_add_default_system_blocks(). 341 $this->assertCount(count($alldefaultblocksordered), $result['blocks']); 342 $returnedblocks = array(); 343 foreach ($result['blocks'] as $block) { 344 // Check all the returned blocks are in the expected blocks array. 345 $this->assertContains($block['name'], $alldefaultblocksordered); 346 $returnedblocks[] = $block['name']; 347 // Check the configuration returned for this default block. 348 if ($block['name'] == 'myoverview') { 349 // Convert config to associative array to avoid DB sorting randomness. 350 $config = array_column($block['configs'], null, 'name'); 351 $this->assertArrayHasKey('displaycategories', $config); 352 $this->assertEquals(json_encode('0'), $config['displaycategories']['value']); 353 $this->assertEquals('plugin', $config['displaycategories']['type']); 354 } 355 } 356 357 // Check that we received the blocks in the expected order. 358 $this->assertEquals(array_values($alldefaultblocksordered), $returnedblocks); 359 } 360 361 /** 362 * Test user get default dashboard blocks including a sticky block. 363 */ 364 public function test_get_dashboard_blocks_default_dashboard_including_sticky_block() { 365 global $PAGE, $DB; 366 $this->resetAfterTest(true); 367 368 $user = $this->getDataGenerator()->create_user(); 369 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 370 371 $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true)); 372 // Get the expected default blocks. 373 $alldefaultblocks = $DB->get_records_menu( 374 'block_instances', array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id), 375 '', 376 'id, blockname' 377 ); 378 379 // Now, add a sticky block. 380 $page = new \moodle_page(); 381 $page->set_context(\context_system::instance()); 382 $page->set_pagetype('my-index'); 383 $page->set_url(new \moodle_url('/')); 384 $page->blocks->add_region('side-pre'); 385 $page->blocks->load_blocks(); 386 $page->blocks->add_block('myprofile', 'side-pre', 0, true, '*'); 387 388 $this->setUser($user); 389 390 // Check for the default blocks plus the sticky. 391 $result = core_block_external::get_dashboard_blocks($user->id); 392 // We need to execute the return values cleaning process to simulate the web service server. 393 $result = \external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 394 // Expect all default blocks defined in blocks_add_default_system_blocks() plus sticky one. 395 $this->assertCount(count($alldefaultblocks) + 1, $result['blocks']); 396 $found = false; 397 foreach ($result['blocks'] as $block) { 398 if ($block['name'] == 'myprofile') { 399 $this->assertEquals('side-pre', $block['region']); 400 $found = true; 401 continue; 402 } 403 // Check that the block is in the expected blocks array. 404 $this->assertContains($block['name'], $alldefaultblocks); 405 } 406 $this->assertTrue($found); 407 } 408 409 /** 410 * Test admin get user's custom dashboard blocks. 411 */ 412 public function test_get_dashboard_blocks_custom_user_dashboard() { 413 global $PAGE, $DB; 414 $this->resetAfterTest(true); 415 416 $user = $this->getDataGenerator()->create_user(); 417 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 418 419 $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true)); 420 // Get the expected default blocks. 421 $alldefaultblocks = $DB->get_records_menu( 422 'block_instances', 423 array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id), 424 '', 425 'id, blockname' 426 ); 427 428 // Add a custom block. 429 $page = new \moodle_page(); 430 $page->set_context(\context_user::instance($user->id)); 431 $page->set_pagelayout('mydashboard'); 432 $page->set_pagetype('my-index'); 433 $page->blocks->add_region('content'); 434 $currentpage = my_get_page($user->id, MY_PAGE_PRIVATE); 435 $page->set_subpage($currentpage->id); 436 $page->blocks->load_blocks(); 437 $page->blocks->add_block('myprofile', 'content', 0, false); 438 439 $this->setAdminUser(); 440 441 // Check for the new block as admin for a user. 442 $result = core_block_external::get_dashboard_blocks($user->id); 443 // We need to execute the return values cleaning process to simulate the web service server. 444 $result = \external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 445 // Expect all default blocks defined in blocks_add_default_system_blocks() plus the one we added. 446 $this->assertCount(count($alldefaultblocks) + 1, $result['blocks']); 447 $found = false; 448 foreach ($result['blocks'] as $block) { 449 if ($block['name'] == 'myprofile') { 450 $this->assertEquals('content', $block['region']); 451 $found = true; 452 continue; 453 } 454 // Check that the block is in the expected blocks array. 455 $this->assertContains($block['name'], $alldefaultblocks); 456 } 457 $this->assertTrue($found); 458 } 459 460 /** 461 * Test user tries to get other user blocks not having permission. 462 */ 463 public function test_get_dashboard_blocks_other_user_missing_permissions() { 464 $this->resetAfterTest(true); 465 466 $user1 = $this->getDataGenerator()->create_user(); 467 $user2 = $this->getDataGenerator()->create_user(); 468 469 $this->setUser($user1); 470 471 $this->expectException('moodle_exception'); 472 core_block_external::get_dashboard_blocks($user2->id); 473 } 474 475 /** 476 * Test user get default dashboard blocks for my courses page. 477 */ 478 public function test_get_dashboard_blocks_my_courses() { 479 global $PAGE, $DB; 480 $this->resetAfterTest(true); 481 482 $user = $this->getDataGenerator()->create_user(); 483 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 484 485 // Force a setting change to check the returned blocks settings. 486 set_config('displaycategories', 0, 'block_myoverview'); 487 488 $systempage = $DB->get_record('my_pages', ['userid' => null, 'name' => MY_PAGE_COURSES, 'private' => false]); 489 // Get the expected default blocks. 490 $alldefaultblocksordered = $DB->get_records_menu( 491 'block_instances', 492 ['pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id], 493 'defaultregion, defaultweight ASC', 494 'id, blockname' 495 ); 496 497 $this->setUser($user); 498 499 // Check for the default blocks. 500 $result = core_block_external::get_dashboard_blocks($user->id, false, MY_PAGE_COURSES); 501 // We need to execute the return values cleaning process to simulate the web service server. 502 $result = \external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 503 // Expect all default blocks defined in blocks_add_default_system_blocks(). 504 $this->assertCount(count($alldefaultblocksordered), $result['blocks']); 505 $returnedblocks = []; 506 foreach ($result['blocks'] as $block) { 507 // Check all the returned blocks are in the expected blocks array. 508 $this->assertContains($block['name'], $alldefaultblocksordered); 509 $returnedblocks[] = $block['name']; 510 // Check the configuration returned for this default block. 511 if ($block['name'] == 'myoverview') { 512 // Convert config to associative array to avoid DB sorting randomness. 513 $config = array_column($block['configs'], null, 'name'); 514 $this->assertArrayHasKey('displaycategories', $config); 515 $this->assertEquals(json_encode('0'), $config['displaycategories']['value']); 516 $this->assertEquals('plugin', $config['displaycategories']['type']); 517 } 518 } 519 520 // Check that we received the blocks in the expected order. 521 $this->assertEquals(array_values($alldefaultblocksordered), $returnedblocks); 522 } 523 524 /** 525 * Test user passing the wrong page type and getting an exception. 526 */ 527 public function test_get_dashboard_blocks_incorrect_page() { 528 global $PAGE; 529 $this->resetAfterTest(true); 530 531 $user = $this->getDataGenerator()->create_user(); 532 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 533 534 $this->setUser($user); 535 536 $this->expectException('moodle_exception'); 537 // Check for the default blocks with a fake page, no need to assign as it'll throw. 538 core_block_external::get_dashboard_blocks($user->id, false, 'fakepage'); 539 540 } 541 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body