Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402]
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 = \core_external\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 = \core_external\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 = \core_external\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 = \core_external\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 $this->resetAfterTest(true); 240 241 // Enable MathJax filter in content and headings. 242 $this->configure_filters([ 243 ['name' => 'mathjaxloader', 'state' => TEXTFILTER_ON, 'move' => -1, 'applytostrings' => true], 244 ]); 245 246 // Create a few stuff to test with. 247 $user = $this->getDataGenerator()->create_user(); 248 $course = $this->getDataGenerator()->create_course(); 249 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 250 $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); 251 $coursecontext = \context_course::instance($course->id); 252 253 // Create a HTML block. 254 $title = 'My block $$(a+b)=2$$'; 255 $body = 'My block contents $$(a+b)=2$$'; 256 $bodyformat = FORMAT_MOODLE; 257 $page = new \moodle_page(); 258 $page->set_context($coursecontext); 259 $page->set_pagelayout('course'); 260 $course->format = course_get_format($course)->get_format(); 261 $page->set_pagetype('course-view-' . $course->format); 262 $page->blocks->load_blocks(); 263 $newblock = 'html'; 264 $page->blocks->add_block_at_end_of_default_region($newblock); 265 266 $this->setUser($user); 267 // Re-create the page. 268 $page = new \moodle_page(); 269 $page->set_context($coursecontext); 270 $page->set_pagelayout('course'); 271 $course->format = course_get_format($course)->get_format(); 272 $page->set_pagetype('course-view-' . $course->format); 273 $page->blocks->load_blocks(); 274 $blocks = $page->blocks->get_blocks_for_region($page->blocks->get_default_region()); 275 $block = end($blocks); 276 $block = block_instance('html', $block->instance); 277 $nonscalar = [ 278 'something' => true, 279 ]; 280 $configdata = (object) [ 281 'title' => $title, 282 'text' => [ 283 'itemid' => 0, 284 'text' => $body, 285 'format' => $bodyformat, 286 ], 287 'nonscalar' => $nonscalar 288 ]; 289 $block->instance_config_save((object) $configdata); 290 291 // Check for the new block. 292 $result = core_block_external::get_course_blocks($course->id, true); 293 $result = \core_external\external_api::clean_returnvalue(core_block_external::get_course_blocks_returns(), $result); 294 295 // Format the original data. 296 $sitecontext = \context_system::instance(); 297 $title = \core_external\util::format_string($title, $coursecontext->id); 298 list($body, $bodyformat) = \core_external\util::format_text($body, $bodyformat, $coursecontext, 'block_html', 'content'); 299 300 // Check that the block data is formatted. 301 $this->assertCount(1, $result['blocks']); 302 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', 303 $result['blocks'][0]['contents']['title']); 304 $this->assertStringContainsString('<span class="filter_mathjaxloader_equation">', 305 $result['blocks'][0]['contents']['content']); 306 $this->assertEquals($title, $result['blocks'][0]['contents']['title']); 307 $this->assertEquals($body, $result['blocks'][0]['contents']['content']); 308 } 309 310 /** 311 * Test user get default dashboard blocks. 312 */ 313 public function test_get_dashboard_blocks_default_dashboard() { 314 global $PAGE, $DB; 315 $this->resetAfterTest(true); 316 317 $user = $this->getDataGenerator()->create_user(); 318 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 319 320 // Force a setting change to check the returned blocks settings. 321 set_config('displaycategories', 0, 'block_myoverview'); 322 323 $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true)); 324 // Get the expected default blocks. 325 $alldefaultblocksordered = $DB->get_records_menu( 326 'block_instances', 327 array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id), 328 'defaultregion, defaultweight ASC', 329 'id, blockname' 330 ); 331 332 $this->setUser($user); 333 334 // Check for the default blocks. 335 $result = core_block_external::get_dashboard_blocks($user->id); 336 // We need to execute the return values cleaning process to simulate the web service server. 337 $result = \core_external\external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 338 // Expect all default blocks defined in blocks_add_default_system_blocks(). 339 $this->assertCount(count($alldefaultblocksordered), $result['blocks']); 340 $returnedblocks = array(); 341 foreach ($result['blocks'] as $block) { 342 // Check all the returned blocks are in the expected blocks array. 343 $this->assertContains($block['name'], $alldefaultblocksordered); 344 $returnedblocks[] = $block['name']; 345 // Check the configuration returned for this default block. 346 if ($block['name'] == 'myoverview') { 347 // Convert config to associative array to avoid DB sorting randomness. 348 $config = array_column($block['configs'], null, 'name'); 349 $this->assertArrayHasKey('displaycategories', $config); 350 $this->assertEquals(json_encode('0'), $config['displaycategories']['value']); 351 $this->assertEquals('plugin', $config['displaycategories']['type']); 352 } 353 } 354 355 // Check that we received the blocks in the expected order. 356 $this->assertEquals(array_values($alldefaultblocksordered), $returnedblocks); 357 } 358 359 /** 360 * Test user get default dashboard blocks including a sticky block. 361 */ 362 public function test_get_dashboard_blocks_default_dashboard_including_sticky_block() { 363 global $PAGE, $DB; 364 $this->resetAfterTest(true); 365 366 $user = $this->getDataGenerator()->create_user(); 367 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 368 369 $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true)); 370 // Get the expected default blocks. 371 $alldefaultblocks = $DB->get_records_menu( 372 'block_instances', array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id), 373 '', 374 'id, blockname' 375 ); 376 377 // Now, add a sticky block. 378 $page = new \moodle_page(); 379 $page->set_context(\context_system::instance()); 380 $page->set_pagetype('my-index'); 381 $page->set_url(new \moodle_url('/')); 382 $page->blocks->add_region('side-pre'); 383 $page->blocks->load_blocks(); 384 $page->blocks->add_block('myprofile', 'side-pre', 0, true, '*'); 385 386 $this->setUser($user); 387 388 // Check for the default blocks plus the sticky. 389 $result = core_block_external::get_dashboard_blocks($user->id); 390 // We need to execute the return values cleaning process to simulate the web service server. 391 $result = \core_external\external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 392 // Expect all default blocks defined in blocks_add_default_system_blocks() plus sticky one. 393 $this->assertCount(count($alldefaultblocks) + 1, $result['blocks']); 394 $found = false; 395 foreach ($result['blocks'] as $block) { 396 if ($block['name'] == 'myprofile') { 397 $this->assertEquals('side-pre', $block['region']); 398 $found = true; 399 continue; 400 } 401 // Check that the block is in the expected blocks array. 402 $this->assertContains($block['name'], $alldefaultblocks); 403 } 404 $this->assertTrue($found); 405 } 406 407 /** 408 * Test admin get user's custom dashboard blocks. 409 */ 410 public function test_get_dashboard_blocks_custom_user_dashboard() { 411 global $PAGE, $DB; 412 $this->resetAfterTest(true); 413 414 $user = $this->getDataGenerator()->create_user(); 415 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 416 417 $systempage = $DB->get_record('my_pages', array('userid' => null, 'name' => MY_PAGE_DEFAULT, 'private' => true)); 418 // Get the expected default blocks. 419 $alldefaultblocks = $DB->get_records_menu( 420 'block_instances', 421 array('pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id), 422 '', 423 'id, blockname' 424 ); 425 426 // Add a custom block. 427 $page = new \moodle_page(); 428 $page->set_context(\context_user::instance($user->id)); 429 $page->set_pagelayout('mydashboard'); 430 $page->set_pagetype('my-index'); 431 $page->blocks->add_region('content'); 432 $currentpage = my_get_page($user->id, MY_PAGE_PRIVATE); 433 $page->set_subpage($currentpage->id); 434 $page->blocks->load_blocks(); 435 $page->blocks->add_block('myprofile', 'content', 0, false); 436 437 $this->setAdminUser(); 438 439 // Check for the new block as admin for a user. 440 $result = core_block_external::get_dashboard_blocks($user->id); 441 // We need to execute the return values cleaning process to simulate the web service server. 442 $result = \core_external\external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 443 // Expect all default blocks defined in blocks_add_default_system_blocks() plus the one we added. 444 $this->assertCount(count($alldefaultblocks) + 1, $result['blocks']); 445 $found = false; 446 foreach ($result['blocks'] as $block) { 447 if ($block['name'] == 'myprofile') { 448 $this->assertEquals('content', $block['region']); 449 $found = true; 450 continue; 451 } 452 // Check that the block is in the expected blocks array. 453 $this->assertContains($block['name'], $alldefaultblocks); 454 } 455 $this->assertTrue($found); 456 } 457 458 /** 459 * Test user tries to get other user blocks not having permission. 460 */ 461 public function test_get_dashboard_blocks_other_user_missing_permissions() { 462 $this->resetAfterTest(true); 463 464 $user1 = $this->getDataGenerator()->create_user(); 465 $user2 = $this->getDataGenerator()->create_user(); 466 467 $this->setUser($user1); 468 469 $this->expectException('moodle_exception'); 470 core_block_external::get_dashboard_blocks($user2->id); 471 } 472 473 /** 474 * Test user get default dashboard blocks for my courses page. 475 */ 476 public function test_get_dashboard_blocks_my_courses() { 477 global $PAGE, $DB; 478 $this->resetAfterTest(true); 479 480 $user = $this->getDataGenerator()->create_user(); 481 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 482 483 // Force a setting change to check the returned blocks settings. 484 set_config('displaycategories', 0, 'block_myoverview'); 485 486 $systempage = $DB->get_record('my_pages', ['userid' => null, 'name' => MY_PAGE_COURSES, 'private' => false]); 487 // Get the expected default blocks. 488 $alldefaultblocksordered = $DB->get_records_menu( 489 'block_instances', 490 ['pagetypepattern' => 'my-index', 'subpagepattern' => $systempage->id], 491 'defaultregion, defaultweight ASC', 492 'id, blockname' 493 ); 494 495 $this->setUser($user); 496 497 // Check for the default blocks. 498 $result = core_block_external::get_dashboard_blocks($user->id, false, MY_PAGE_COURSES); 499 // We need to execute the return values cleaning process to simulate the web service server. 500 $result = \core_external\external_api::clean_returnvalue(core_block_external::get_dashboard_blocks_returns(), $result); 501 // Expect all default blocks defined in blocks_add_default_system_blocks(). 502 $this->assertCount(count($alldefaultblocksordered), $result['blocks']); 503 $returnedblocks = []; 504 foreach ($result['blocks'] as $block) { 505 // Check all the returned blocks are in the expected blocks array. 506 $this->assertContains($block['name'], $alldefaultblocksordered); 507 $returnedblocks[] = $block['name']; 508 // Check the configuration returned for this default block. 509 if ($block['name'] == 'myoverview') { 510 // Convert config to associative array to avoid DB sorting randomness. 511 $config = array_column($block['configs'], null, 'name'); 512 $this->assertArrayHasKey('displaycategories', $config); 513 $this->assertEquals(json_encode('0'), $config['displaycategories']['value']); 514 $this->assertEquals('plugin', $config['displaycategories']['type']); 515 } 516 } 517 518 // Check that we received the blocks in the expected order. 519 $this->assertEquals(array_values($alldefaultblocksordered), $returnedblocks); 520 } 521 522 /** 523 * Test user passing the wrong page type and getting an exception. 524 */ 525 public function test_get_dashboard_blocks_incorrect_page() { 526 global $PAGE; 527 $this->resetAfterTest(true); 528 529 $user = $this->getDataGenerator()->create_user(); 530 $PAGE->set_url('/my/index.php'); // Need this because some internal API calls require the $PAGE url to be set. 531 532 $this->setUser($user); 533 534 $this->expectException('moodle_exception'); 535 // Check for the default blocks with a fake page, no need to assign as it'll throw. 536 core_block_external::get_dashboard_blocks($user->id, false, 'fakepage'); 537 538 } 539 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body