Differences Between: [Versions 310 and 311] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 lib.php 19 * 20 * @package mod_data 21 * @category phpunit 22 * @copyright 2013 Adrian Greeve 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 namespace mod_data; 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once($CFG->dirroot . '/mod/data/lib.php'); 31 32 /** 33 * Unit tests for lib.php 34 * 35 * @package mod_data 36 * @copyright 2013 Adrian Greeve 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class lib_test extends \advanced_testcase { 40 41 /** 42 * @var moodle_database 43 */ 44 protected $DB = null; 45 46 /** 47 * Tear Down to reset DB. 48 */ 49 public function tearDown(): void { 50 global $DB; 51 52 if (isset($this->DB)) { 53 $DB = $this->DB; 54 $this->DB = null; 55 } 56 } 57 58 /** 59 * Confirms that completionentries is working 60 * Sets it to 1, confirms that 61 * it is not complete. Inserts a record and 62 * confirms that it is complete. 63 */ 64 public function test_data_completion() { 65 global $DB, $CFG; 66 $this->resetAfterTest(); 67 $this->setAdminUser(); 68 $CFG->enablecompletion = 1; 69 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 70 $record = new \stdClass(); 71 $record->course = $course->id; 72 $record->name = "Mod data completion test"; 73 $record->intro = "Some intro of some sort"; 74 $record->completionentries = "1"; 75 /* completion=2 means Show activity commplete when condition is met and completionentries means 1 record is 76 * required for the activity to be considered complete 77 */ 78 $module = $this->getDataGenerator()->create_module('data', $record, array('completion' => 2, 'completionentries' => 1)); 79 80 $cm = get_coursemodule_from_instance('data', $module->id, $course->id); 81 $completion = new \completion_info($course); 82 $completiondata = $completion->get_data($cm, true, 0); 83 /* Confirm it is not complete as there are no entries */ 84 $this->assertNotEquals(1, $completiondata->completionstate); 85 86 $field = data_get_field_new('text', $module); 87 $fielddetail = new \stdClass(); 88 $fielddetail->d = $module->id; 89 $fielddetail->mode = 'add'; 90 $fielddetail->type = 'text'; 91 $fielddetail->sesskey = sesskey(); 92 $fielddetail->name = 'Name'; 93 $fielddetail->description = 'Some name'; 94 95 $field->define_field($fielddetail); 96 $field->insert_field(); 97 $recordid = data_add_record($module); 98 99 $datacontent = array(); 100 $datacontent['fieldid'] = $field->field->id; 101 $datacontent['recordid'] = $recordid; 102 $datacontent['content'] = 'Asterix'; 103 $contentid = $DB->insert_record('data_content', $datacontent); 104 105 $cm = get_coursemodule_from_instance('data', $module->id, $course->id); 106 $completion = new \completion_info($course); 107 $completiondata = $completion->get_data($cm); 108 /* Confirm it is complete because it has 1 entry */ 109 $this->assertEquals(1, $completiondata->completionstate); 110 } 111 112 public function test_data_delete_record() { 113 global $DB; 114 115 $this->resetAfterTest(); 116 117 // Create a record for deleting. 118 $this->setAdminUser(); 119 $course = $this->getDataGenerator()->create_course(); 120 $record = new \stdClass(); 121 $record->course = $course->id; 122 $record->name = "Mod data delete test"; 123 $record->intro = "Some intro of some sort"; 124 125 $module = $this->getDataGenerator()->create_module('data', $record); 126 127 $field = data_get_field_new('text', $module); 128 129 $fielddetail = new \stdClass(); 130 $fielddetail->d = $module->id; 131 $fielddetail->mode = 'add'; 132 $fielddetail->type = 'text'; 133 $fielddetail->sesskey = sesskey(); 134 $fielddetail->name = 'Name'; 135 $fielddetail->description = 'Some name'; 136 137 $field->define_field($fielddetail); 138 $field->insert_field(); 139 $recordid = data_add_record($module); 140 141 $datacontent = array(); 142 $datacontent['fieldid'] = $field->field->id; 143 $datacontent['recordid'] = $recordid; 144 $datacontent['content'] = 'Asterix'; 145 146 $contentid = $DB->insert_record('data_content', $datacontent); 147 $cm = get_coursemodule_from_instance('data', $module->id, $course->id); 148 149 // Check to make sure that we have a database record. 150 $data = $DB->get_records('data', array('id' => $module->id)); 151 $this->assertEquals(1, count($data)); 152 153 $datacontent = $DB->get_records('data_content', array('id' => $contentid)); 154 $this->assertEquals(1, count($datacontent)); 155 156 $datafields = $DB->get_records('data_fields', array('id' => $field->field->id)); 157 $this->assertEquals(1, count($datafields)); 158 159 $datarecords = $DB->get_records('data_records', array('id' => $recordid)); 160 $this->assertEquals(1, count($datarecords)); 161 162 // Test to see if a failed delete returns false. 163 $result = data_delete_record(8798, $module, $course->id, $cm->id); 164 $this->assertFalse($result); 165 166 // Delete the record. 167 $result = data_delete_record($recordid, $module, $course->id, $cm->id); 168 169 // Check that all of the record is gone. 170 $datacontent = $DB->get_records('data_content', array('id' => $contentid)); 171 $this->assertEquals(0, count($datacontent)); 172 173 $datarecords = $DB->get_records('data_records', array('id' => $recordid)); 174 $this->assertEquals(0, count($datarecords)); 175 176 // Make sure the function returns true on a successful deletion. 177 $this->assertTrue($result); 178 } 179 180 /** 181 * Test comment_created event. 182 */ 183 public function test_data_comment_created_event() { 184 global $CFG, $DB; 185 require_once($CFG->dirroot . '/comment/lib.php'); 186 187 $this->resetAfterTest(); 188 189 // Create a record for deleting. 190 $this->setAdminUser(); 191 $course = $this->getDataGenerator()->create_course(); 192 $record = new \stdClass(); 193 $record->course = $course->id; 194 $record->name = "Mod data delete test"; 195 $record->intro = "Some intro of some sort"; 196 $record->comments = 1; 197 198 $module = $this->getDataGenerator()->create_module('data', $record); 199 $field = data_get_field_new('text', $module); 200 201 $fielddetail = new \stdClass(); 202 $fielddetail->name = 'Name'; 203 $fielddetail->description = 'Some name'; 204 205 $field->define_field($fielddetail); 206 $field->insert_field(); 207 $recordid = data_add_record($module); 208 209 $datacontent = array(); 210 $datacontent['fieldid'] = $field->field->id; 211 $datacontent['recordid'] = $recordid; 212 $datacontent['content'] = 'Asterix'; 213 214 $contentid = $DB->insert_record('data_content', $datacontent); 215 $cm = get_coursemodule_from_instance('data', $module->id, $course->id); 216 217 $context = \context_module::instance($module->cmid); 218 $cmt = new \stdClass(); 219 $cmt->context = $context; 220 $cmt->course = $course; 221 $cmt->cm = $cm; 222 $cmt->area = 'database_entry'; 223 $cmt->itemid = $recordid; 224 $cmt->showcount = true; 225 $cmt->component = 'mod_data'; 226 $comment = new \comment($cmt); 227 228 // Triggering and capturing the event. 229 $sink = $this->redirectEvents(); 230 $comment->add('New comment'); 231 $events = $sink->get_events(); 232 $this->assertCount(1, $events); 233 $event = reset($events); 234 235 // Checking that the event contains the expected values. 236 $this->assertInstanceOf('\mod_data\event\comment_created', $event); 237 $this->assertEquals($context, $event->get_context()); 238 $url = new \moodle_url('/mod/data/view.php', array('id' => $cm->id)); 239 $this->assertEquals($url, $event->get_url()); 240 $this->assertEventContextNotUsed($event); 241 } 242 243 /** 244 * Test comment_deleted event. 245 */ 246 public function test_data_comment_deleted_event() { 247 global $CFG, $DB; 248 require_once($CFG->dirroot . '/comment/lib.php'); 249 250 $this->resetAfterTest(); 251 252 // Create a record for deleting. 253 $this->setAdminUser(); 254 $course = $this->getDataGenerator()->create_course(); 255 $record = new \stdClass(); 256 $record->course = $course->id; 257 $record->name = "Mod data delete test"; 258 $record->intro = "Some intro of some sort"; 259 $record->comments = 1; 260 261 $module = $this->getDataGenerator()->create_module('data', $record); 262 $field = data_get_field_new('text', $module); 263 264 $fielddetail = new \stdClass(); 265 $fielddetail->name = 'Name'; 266 $fielddetail->description = 'Some name'; 267 268 $field->define_field($fielddetail); 269 $field->insert_field(); 270 $recordid = data_add_record($module); 271 272 $datacontent = array(); 273 $datacontent['fieldid'] = $field->field->id; 274 $datacontent['recordid'] = $recordid; 275 $datacontent['content'] = 'Asterix'; 276 277 $contentid = $DB->insert_record('data_content', $datacontent); 278 $cm = get_coursemodule_from_instance('data', $module->id, $course->id); 279 280 $context = \context_module::instance($module->cmid); 281 $cmt = new \stdClass(); 282 $cmt->context = $context; 283 $cmt->course = $course; 284 $cmt->cm = $cm; 285 $cmt->area = 'database_entry'; 286 $cmt->itemid = $recordid; 287 $cmt->showcount = true; 288 $cmt->component = 'mod_data'; 289 $comment = new \comment($cmt); 290 $newcomment = $comment->add('New comment 1'); 291 292 // Triggering and capturing the event. 293 $sink = $this->redirectEvents(); 294 $comment->delete($newcomment->id); 295 $events = $sink->get_events(); 296 $this->assertCount(1, $events); 297 $event = reset($events); 298 299 // Checking that the event contains the expected values. 300 $this->assertInstanceOf('\mod_data\event\comment_deleted', $event); 301 $this->assertEquals($context, $event->get_context()); 302 $url = new \moodle_url('/mod/data/view.php', array('id' => $module->cmid)); 303 $this->assertEquals($url, $event->get_url()); 304 $this->assertEventContextNotUsed($event); 305 } 306 307 /** 308 * Checks that data_user_can_manage_entry will return true if the user 309 * has the mod/data:manageentries capability. 310 */ 311 public function test_data_user_can_manage_entry_return_true_with_capability() { 312 313 $this->resetAfterTest(); 314 $testdata = $this->create_user_test_data(); 315 316 $user = $testdata['user']; 317 $course = $testdata['course']; 318 $roleid = $testdata['roleid']; 319 $context = $testdata['context']; 320 $record = $testdata['record']; 321 $data = new \stdClass(); 322 323 $this->setUser($user); 324 325 assign_capability('mod/data:manageentries', CAP_ALLOW, $roleid, $context); 326 327 $this->assertTrue(data_user_can_manage_entry($record, $data, $context), 328 'data_user_can_manage_entry() returns true if the user has mod/data:manageentries capability'); 329 } 330 331 /** 332 * Checks that data_user_can_manage_entry will return false if the data 333 * is set to readonly. 334 */ 335 public function test_data_user_can_manage_entry_return_false_readonly() { 336 337 $this->resetAfterTest(); 338 $testdata = $this->create_user_test_data(); 339 340 $user = $testdata['user']; 341 $course = $testdata['course']; 342 $roleid = $testdata['roleid']; 343 $context = $testdata['context']; 344 $record = $testdata['record']; 345 346 $this->setUser($user); 347 348 // Need to make sure they don't have this capability in order to fall back to 349 // the other checks. 350 assign_capability('mod/data:manageentries', CAP_PROHIBIT, $roleid, $context); 351 352 // Causes readonly mode to be enabled. 353 $data = new \stdClass(); 354 $now = time(); 355 // Add a small margin around the periods to prevent errors with slow tests. 356 $data->timeviewfrom = $now - 1; 357 $data->timeviewto = $now + 5; 358 359 $this->assertFalse(data_user_can_manage_entry($record, $data, $context), 360 'data_user_can_manage_entry() returns false if the data is read only'); 361 } 362 363 /** 364 * Checks that data_user_can_manage_entry will return false if the record 365 * can't be found in the database. 366 */ 367 public function test_data_user_can_manage_entry_return_false_no_record() { 368 369 $this->resetAfterTest(); 370 $testdata = $this->create_user_test_data(); 371 372 $user = $testdata['user']; 373 $course = $testdata['course']; 374 $roleid = $testdata['roleid']; 375 $context = $testdata['context']; 376 $record = $testdata['record']; 377 $data = new \stdClass(); 378 // Causes readonly mode to be disabled. 379 $now = time(); 380 $data->timeviewfrom = $now + 100; 381 $data->timeviewto = $now - 100; 382 383 $this->setUser($user); 384 385 // Need to make sure they don't have this capability in order to fall back to 386 // the other checks. 387 assign_capability('mod/data:manageentries', CAP_PROHIBIT, $roleid, $context); 388 389 // Pass record id instead of object to force DB lookup. 390 $this->assertFalse(data_user_can_manage_entry(1, $data, $context), 391 'data_user_can_manage_entry() returns false if the record cannot be found'); 392 } 393 394 /** 395 * Checks that data_user_can_manage_entry will return false if the record 396 * isn't owned by the user. 397 */ 398 public function test_data_user_can_manage_entry_return_false_not_owned_record() { 399 400 $this->resetAfterTest(); 401 $testdata = $this->create_user_test_data(); 402 403 $user = $testdata['user']; 404 $course = $testdata['course']; 405 $roleid = $testdata['roleid']; 406 $context = $testdata['context']; 407 $record = $testdata['record']; 408 $data = new \stdClass(); 409 // Causes readonly mode to be disabled. 410 $now = time(); 411 $data->timeviewfrom = $now + 100; 412 $data->timeviewto = $now - 100; 413 // Make sure the record isn't owned by this user. 414 $record->userid = $user->id + 1; 415 416 $this->setUser($user); 417 418 // Need to make sure they don't have this capability in order to fall back to 419 // the other checks. 420 assign_capability('mod/data:manageentries', CAP_PROHIBIT, $roleid, $context); 421 422 $this->assertFalse(data_user_can_manage_entry($record, $data, $context), 423 'data_user_can_manage_entry() returns false if the record isnt owned by the user'); 424 } 425 426 /** 427 * Checks that data_user_can_manage_entry will return true if the data 428 * doesn't require approval. 429 */ 430 public function test_data_user_can_manage_entry_return_true_data_no_approval() { 431 432 $this->resetAfterTest(); 433 $testdata = $this->create_user_test_data(); 434 435 $user = $testdata['user']; 436 $course = $testdata['course']; 437 $roleid = $testdata['roleid']; 438 $context = $testdata['context']; 439 $record = $testdata['record']; 440 $data = new \stdClass(); 441 // Causes readonly mode to be disabled. 442 $now = time(); 443 $data->timeviewfrom = $now + 100; 444 $data->timeviewto = $now - 100; 445 // The record doesn't need approval. 446 $data->approval = false; 447 // Make sure the record is owned by this user. 448 $record->userid = $user->id; 449 450 $this->setUser($user); 451 452 // Need to make sure they don't have this capability in order to fall back to 453 // the other checks. 454 assign_capability('mod/data:manageentries', CAP_PROHIBIT, $roleid, $context); 455 456 $this->assertTrue(data_user_can_manage_entry($record, $data, $context), 457 'data_user_can_manage_entry() returns true if the record doesnt require approval'); 458 } 459 460 /** 461 * Checks that data_user_can_manage_entry will return true if the record 462 * isn't yet approved. 463 */ 464 public function test_data_user_can_manage_entry_return_true_record_unapproved() { 465 466 $this->resetAfterTest(); 467 $testdata = $this->create_user_test_data(); 468 469 $user = $testdata['user']; 470 $course = $testdata['course']; 471 $roleid = $testdata['roleid']; 472 $context = $testdata['context']; 473 $record = $testdata['record']; 474 $data = new \stdClass(); 475 // Causes readonly mode to be disabled. 476 $now = time(); 477 $data->timeviewfrom = $now + 100; 478 $data->timeviewto = $now - 100; 479 // The record needs approval. 480 $data->approval = true; 481 // Make sure the record is owned by this user. 482 $record->userid = $user->id; 483 // The record hasn't yet been approved. 484 $record->approved = false; 485 486 $this->setUser($user); 487 488 // Need to make sure they don't have this capability in order to fall back to 489 // the other checks. 490 assign_capability('mod/data:manageentries', CAP_PROHIBIT, $roleid, $context); 491 492 $this->assertTrue(data_user_can_manage_entry($record, $data, $context), 493 'data_user_can_manage_entry() returns true if the record is not yet approved'); 494 } 495 496 /** 497 * Checks that data_user_can_manage_entry will return the 'manageapproved' 498 * value if the record has already been approved. 499 */ 500 public function test_data_user_can_manage_entry_return_manageapproved() { 501 502 $this->resetAfterTest(); 503 $testdata = $this->create_user_test_data(); 504 505 $user = $testdata['user']; 506 $course = $testdata['course']; 507 $roleid = $testdata['roleid']; 508 $context = $testdata['context']; 509 $record = $testdata['record']; 510 $data = new \stdClass(); 511 // Causes readonly mode to be disabled. 512 $now = time(); 513 $data->timeviewfrom = $now + 100; 514 $data->timeviewto = $now - 100; 515 // The record needs approval. 516 $data->approval = true; 517 // Can the user managed approved records? 518 $data->manageapproved = false; 519 // Make sure the record is owned by this user. 520 $record->userid = $user->id; 521 // The record has been approved. 522 $record->approved = true; 523 524 $this->setUser($user); 525 526 // Need to make sure they don't have this capability in order to fall back to 527 // the other checks. 528 assign_capability('mod/data:manageentries', CAP_PROHIBIT, $roleid, $context); 529 530 $canmanageentry = data_user_can_manage_entry($record, $data, $context); 531 532 // Make sure the result of the check is what ever the manageapproved setting 533 // is set to. 534 $this->assertEquals($data->manageapproved, $canmanageentry, 535 'data_user_can_manage_entry() returns the manageapproved setting on approved records'); 536 } 537 538 /** 539 * Helper method to create a set of test data for data_user_can_manage tests 540 * 541 * @return array contains user, course, roleid, module, context and record 542 */ 543 private function create_user_test_data() { 544 $user = $this->getDataGenerator()->create_user(); 545 $course = $this->getDataGenerator()->create_course(); 546 $roleid = $this->getDataGenerator()->create_role(); 547 $record = new \stdClass(); 548 $record->name = "test name"; 549 $record->intro = "test intro"; 550 $record->comments = 1; 551 $record->course = $course->id; 552 $record->userid = $user->id; 553 554 $module = $this->getDataGenerator()->create_module('data', $record); 555 $cm = get_coursemodule_from_instance('data', $module->id, $course->id); 556 $context = \context_module::instance($module->cmid); 557 558 $this->getDataGenerator()->role_assign($roleid, $user->id, $context->id); 559 560 return array( 561 'user' => $user, 562 'course' => $course, 563 'roleid' => $roleid, 564 'module' => $module, 565 'context' => $context, 566 'record' => $record 567 ); 568 } 569 570 /** 571 * Tests for mod_data_rating_can_see_item_ratings(). 572 * 573 * @throws coding_exception 574 * @throws rating_exception 575 */ 576 public function test_mod_data_rating_can_see_item_ratings() { 577 global $DB; 578 579 $this->resetAfterTest(); 580 581 // Setup test data. 582 $course = new \stdClass(); 583 $course->groupmode = SEPARATEGROUPS; 584 $course->groupmodeforce = true; 585 $course = $this->getDataGenerator()->create_course($course); 586 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id)); 587 $cm = get_coursemodule_from_instance('data', $data->id); 588 $context = \context_module::instance($cm->id); 589 590 // Create users. 591 $user1 = $this->getDataGenerator()->create_user(); 592 $user2 = $this->getDataGenerator()->create_user(); 593 $user3 = $this->getDataGenerator()->create_user(); 594 $user4 = $this->getDataGenerator()->create_user(); 595 596 // Groups and stuff. 597 $role = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST); 598 $this->getDataGenerator()->enrol_user($user1->id, $course->id, $role->id); 599 $this->getDataGenerator()->enrol_user($user2->id, $course->id, $role->id); 600 $this->getDataGenerator()->enrol_user($user3->id, $course->id, $role->id); 601 $this->getDataGenerator()->enrol_user($user4->id, $course->id, $role->id); 602 603 $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 604 $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); 605 groups_add_member($group1, $user1); 606 groups_add_member($group1, $user2); 607 groups_add_member($group2, $user3); 608 groups_add_member($group2, $user4); 609 610 // Add data. 611 $field = data_get_field_new('text', $data); 612 613 $fielddetail = new \stdClass(); 614 $fielddetail->name = 'Name'; 615 $fielddetail->description = 'Some name'; 616 617 $field->define_field($fielddetail); 618 $field->insert_field(); 619 620 // Add a record with a group id of zero (all participants). 621 $recordid1 = data_add_record($data, 0); 622 623 $datacontent = array(); 624 $datacontent['fieldid'] = $field->field->id; 625 $datacontent['recordid'] = $recordid1; 626 $datacontent['content'] = 'Obelix'; 627 $DB->insert_record('data_content', $datacontent); 628 629 $recordid = data_add_record($data, $group1->id); 630 631 $datacontent = array(); 632 $datacontent['fieldid'] = $field->field->id; 633 $datacontent['recordid'] = $recordid; 634 $datacontent['content'] = 'Asterix'; 635 $DB->insert_record('data_content', $datacontent); 636 637 // Now try to access it as various users. 638 unassign_capability('moodle/site:accessallgroups', $role->id); 639 // Eveyone should have access to the record with the group id of zero. 640 $params1 = array('contextid' => 2, 641 'component' => 'mod_data', 642 'ratingarea' => 'entry', 643 'itemid' => $recordid1, 644 'scaleid' => 2); 645 646 $params = array('contextid' => 2, 647 'component' => 'mod_data', 648 'ratingarea' => 'entry', 649 'itemid' => $recordid, 650 'scaleid' => 2); 651 652 $this->setUser($user1); 653 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 654 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 655 $this->setUser($user2); 656 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 657 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 658 $this->setUser($user3); 659 $this->assertFalse(mod_data_rating_can_see_item_ratings($params)); 660 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 661 $this->setUser($user4); 662 $this->assertFalse(mod_data_rating_can_see_item_ratings($params)); 663 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 664 665 // Now try with accessallgroups cap and make sure everything is visible. 666 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role->id, $context->id); 667 $this->setUser($user1); 668 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 669 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 670 $this->setUser($user2); 671 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 672 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 673 $this->setUser($user3); 674 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 675 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 676 $this->setUser($user4); 677 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 678 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 679 680 // Change group mode and verify visibility. 681 $course->groupmode = VISIBLEGROUPS; 682 $DB->update_record('course', $course); 683 unassign_capability('moodle/site:accessallgroups', $role->id); 684 $this->setUser($user1); 685 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 686 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 687 $this->setUser($user2); 688 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 689 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 690 $this->setUser($user3); 691 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 692 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 693 $this->setUser($user4); 694 $this->assertTrue(mod_data_rating_can_see_item_ratings($params)); 695 $this->assertTrue(mod_data_rating_can_see_item_ratings($params1)); 696 697 } 698 699 /** 700 * Tests for mod_data_refresh_events. 701 */ 702 public function test_data_refresh_events() { 703 global $DB; 704 $this->resetAfterTest(); 705 $this->setAdminUser(); 706 707 $timeopen = time(); 708 $timeclose = time() + 86400; 709 710 $course = $this->getDataGenerator()->create_course(); 711 $generator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 712 $params['course'] = $course->id; 713 $params['timeavailablefrom'] = $timeopen; 714 $params['timeavailableto'] = $timeclose; 715 $data = $generator->create_instance($params); 716 717 // Normal case, with existing course. 718 $this->assertTrue(data_refresh_events($course->id)); 719 $eventparams = array('modulename' => 'data', 'instance' => $data->id, 'eventtype' => 'open'); 720 $openevent = $DB->get_record('event', $eventparams, '*', MUST_EXIST); 721 $this->assertEquals($openevent->timestart, $timeopen); 722 723 $eventparams = array('modulename' => 'data', 'instance' => $data->id, 'eventtype' => 'close'); 724 $closeevent = $DB->get_record('event', $eventparams, '*', MUST_EXIST); 725 $this->assertEquals($closeevent->timestart, $timeclose); 726 // In case the course ID is passed as a numeric string. 727 $this->assertTrue(data_refresh_events('' . $course->id)); 728 // Course ID not provided. 729 $this->assertTrue(data_refresh_events()); 730 $eventparams = array('modulename' => 'data'); 731 $events = $DB->get_records('event', $eventparams); 732 foreach ($events as $event) { 733 if ($event->modulename === 'data' && $event->instance === $data->id && $event->eventtype === 'open') { 734 $this->assertEquals($event->timestart, $timeopen); 735 } 736 if ($event->modulename === 'data' && $event->instance === $data->id && $event->eventtype === 'close') { 737 $this->assertEquals($event->timestart, $timeclose); 738 } 739 } 740 } 741 742 /** 743 * Data provider for tests of data_get_config. 744 * 745 * @return array 746 */ 747 public function data_get_config_provider() { 748 $initialdata = (object) [ 749 'template_foo' => true, 750 'template_bar' => false, 751 'template_baz' => null, 752 ]; 753 754 $database = (object) [ 755 'config' => json_encode($initialdata), 756 ]; 757 758 return [ 759 'Return full dataset (no key/default)' => [ 760 [$database], 761 $initialdata, 762 ], 763 'Return full dataset (no default)' => [ 764 [$database, null], 765 $initialdata, 766 ], 767 'Return full dataset' => [ 768 [$database, null, null], 769 $initialdata, 770 ], 771 'Return requested key only, value true, no default' => [ 772 [$database, 'template_foo'], 773 true, 774 ], 775 'Return requested key only, value false, no default' => [ 776 [$database, 'template_bar'], 777 false, 778 ], 779 'Return requested key only, value null, no default' => [ 780 [$database, 'template_baz'], 781 null, 782 ], 783 'Return unknown key, value null, no default' => [ 784 [$database, 'template_bum'], 785 null, 786 ], 787 'Return requested key only, value true, default null' => [ 788 [$database, 'template_foo', null], 789 true, 790 ], 791 'Return requested key only, value false, default null' => [ 792 [$database, 'template_bar', null], 793 false, 794 ], 795 'Return requested key only, value null, default null' => [ 796 [$database, 'template_baz', null], 797 null, 798 ], 799 'Return unknown key, value null, default null' => [ 800 [$database, 'template_bum', null], 801 null, 802 ], 803 'Return requested key only, value true, default 42' => [ 804 [$database, 'template_foo', 42], 805 true, 806 ], 807 'Return requested key only, value false, default 42' => [ 808 [$database, 'template_bar', 42], 809 false, 810 ], 811 'Return requested key only, value null, default 42' => [ 812 [$database, 'template_baz', 42], 813 null, 814 ], 815 'Return unknown key, value null, default 42' => [ 816 [$database, 'template_bum', 42], 817 42, 818 ], 819 ]; 820 } 821 822 /** 823 * Tests for data_get_config. 824 * 825 * @dataProvider data_get_config_provider 826 * @param array $funcargs The args to pass to data_get_config 827 * @param mixed $expectation The expected value 828 */ 829 public function test_data_get_config($funcargs, $expectation) { 830 $this->assertEquals($expectation, call_user_func_array('data_get_config', $funcargs)); 831 } 832 833 /** 834 * Data provider for tests of data_set_config. 835 * 836 * @return array 837 */ 838 public function data_set_config_provider() { 839 $basevalue = (object) ['id' => rand(1, 1000)]; 840 $config = [ 841 'template_foo' => true, 842 'template_bar' => false, 843 ]; 844 845 $withvalues = clone $basevalue; 846 $withvalues->config = json_encode((object) $config); 847 848 return [ 849 'Empty config, New value' => [ 850 $basevalue, 851 'etc', 852 'newvalue', 853 true, 854 json_encode((object) ['etc' => 'newvalue']) 855 ], 856 'Has config, New value' => [ 857 clone $withvalues, 858 'etc', 859 'newvalue', 860 true, 861 json_encode((object) array_merge($config, ['etc' => 'newvalue'])) 862 ], 863 'Has config, Update value, string' => [ 864 clone $withvalues, 865 'template_foo', 866 'newvalue', 867 true, 868 json_encode((object) array_merge($config, ['template_foo' => 'newvalue'])) 869 ], 870 'Has config, Update value, true' => [ 871 clone $withvalues, 872 'template_bar', 873 true, 874 true, 875 json_encode((object) array_merge($config, ['template_bar' => true])) 876 ], 877 'Has config, Update value, false' => [ 878 clone $withvalues, 879 'template_foo', 880 false, 881 true, 882 json_encode((object) array_merge($config, ['template_foo' => false])) 883 ], 884 'Has config, Update value, null' => [ 885 clone $withvalues, 886 'template_foo', 887 null, 888 true, 889 json_encode((object) array_merge($config, ['template_foo' => null])) 890 ], 891 'Has config, No update, value true' => [ 892 clone $withvalues, 893 'template_foo', 894 true, 895 false, 896 $withvalues->config, 897 ], 898 ]; 899 } 900 901 /** 902 * Tests for data_set_config. 903 * 904 * @dataProvider data_set_config_provider 905 * @param object $database The example row for the entry 906 * @param string $key The config key to set 907 * @param mixed $value The value of the key 908 * @param bool $expectupdate Whether we expected an update 909 * @param mixed $newconfigvalue The expected value 910 */ 911 public function test_data_set_config($database, $key, $value, $expectupdate, $newconfigvalue) { 912 global $DB; 913 914 // Mock the database. 915 // Note: Use the actual test class here rather than the abstract because are testing concrete methods. 916 $this->DB = $DB; 917 $DB = $this->getMockBuilder(get_class($DB)) 918 ->onlyMethods(['set_field']) 919 ->getMock(); 920 921 $DB->expects($this->exactly((int) $expectupdate)) 922 ->method('set_field') 923 ->with( 924 'data', 925 'config', 926 $newconfigvalue, 927 ['id' => $database->id] 928 ); 929 930 // Perform the update. 931 data_set_config($database, $key, $value); 932 933 // Ensure that the value was updated by reference in $database. 934 $config = json_decode($database->config); 935 $this->assertEquals($value, $config->$key); 936 } 937 938 /** 939 * Test data_view 940 * @return void 941 */ 942 public function test_data_view() { 943 global $CFG; 944 945 $CFG->enablecompletion = 1; 946 $this->resetAfterTest(); 947 948 $this->setAdminUser(); 949 // Setup test data. 950 $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1)); 951 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), 952 array('completion' => 2, 'completionview' => 1)); 953 $context = \context_module::instance($data->cmid); 954 $cm = get_coursemodule_from_instance('data', $data->id); 955 956 // Trigger and capture the event. 957 $sink = $this->redirectEvents(); 958 959 data_view($data, $course, $cm, $context); 960 961 $events = $sink->get_events(); 962 // 2 additional events thanks to completion. 963 $this->assertCount(3, $events); 964 $event = array_shift($events); 965 966 // Checking that the event contains the expected values. 967 $this->assertInstanceOf('\mod_data\event\course_module_viewed', $event); 968 $this->assertEquals($context, $event->get_context()); 969 $moodleurl = new \moodle_url('/mod/data/view.php', array('id' => $cm->id)); 970 $this->assertEquals($moodleurl, $event->get_url()); 971 $this->assertEventContextNotUsed($event); 972 $this->assertNotEmpty($event->get_name()); 973 974 // Check completion status. 975 $completion = new \completion_info($course); 976 $completiondata = $completion->get_data($cm); 977 $this->assertEquals(1, $completiondata->completionstate); 978 } 979 980 public function test_mod_data_get_tagged_records() { 981 $this->resetAfterTest(); 982 $this->setAdminUser(); 983 984 // Setup test data. 985 $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 986 $course1 = $this->getDataGenerator()->create_course(); 987 988 $fieldrecord = new \stdClass(); 989 $fieldrecord->name = 'field-1'; 990 $fieldrecord->type = 'text'; 991 992 $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course1->id, 'approval' => true)); 993 $field1 = $datagenerator->create_field($fieldrecord, $data1); 994 995 $datagenerator->create_entry($data1, [$field1->field->id => 'value11'], 0, ['Cats', 'Dogs']); 996 $datagenerator->create_entry($data1, [$field1->field->id => 'value12'], 0, ['Cats', 'mice']); 997 $datagenerator->create_entry($data1, [$field1->field->id => 'value13'], 0, ['Cats']); 998 $datagenerator->create_entry($data1, [$field1->field->id => 'value14'], 0); 999 1000 $tag = \core_tag_tag::get_by_name(0, 'Cats'); 1001 1002 // Admin can see everything. 1003 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1004 $this->assertStringContainsString('value11', $res->content); 1005 $this->assertStringContainsString('value12', $res->content); 1006 $this->assertStringContainsString('value13', $res->content); 1007 $this->assertStringNotContainsString('value14', $res->content); 1008 } 1009 1010 public function test_mod_data_get_tagged_records_approval() { 1011 global $DB; 1012 1013 $this->resetAfterTest(); 1014 $this->setAdminUser(); 1015 1016 // Setup test data. 1017 $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 1018 $course2 = $this->getDataGenerator()->create_course(); 1019 $course1 = $this->getDataGenerator()->create_course(); 1020 1021 $fieldrecord = new \stdClass(); 1022 $fieldrecord->name = 'field-1'; 1023 $fieldrecord->type = 'text'; 1024 1025 $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course1->id)); 1026 $field1 = $datagenerator->create_field($fieldrecord, $data1); 1027 $data2 = $this->getDataGenerator()->create_module('data', array('course' => $course2->id, 'approval' => true)); 1028 $field2 = $datagenerator->create_field($fieldrecord, $data2); 1029 1030 $record11 = $datagenerator->create_entry($data1, [$field1->field->id => 'value11'], 0, ['Cats', 'Dogs']); 1031 $record21 = $datagenerator->create_entry($data2, [$field2->field->id => 'value21'], 0, ['Cats'], ['approved' => false]); 1032 $tag = \core_tag_tag::get_by_name(0, 'Cats'); 1033 1034 // Admin can see everything. 1035 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1036 $this->assertStringContainsString('value11', $res->content); 1037 $this->assertStringContainsString('value21', $res->content); 1038 $this->assertEmpty($res->prevpageurl); 1039 $this->assertEmpty($res->nextpageurl); 1040 1041 // Create and enrol a user. 1042 $student = self::getDataGenerator()->create_user(); 1043 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1044 $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual'); 1045 $this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual'); 1046 $this->setUser($student); 1047 1048 // User can search data records inside a course. 1049 \core_tag_index_builder::reset_caches(); 1050 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1051 1052 $this->assertStringContainsString('value11', $res->content); 1053 $this->assertStringNotContainsString('value21', $res->content); 1054 1055 $recordtoupdate = new \stdClass(); 1056 $recordtoupdate->id = $record21; 1057 $recordtoupdate->approved = true; 1058 $DB->update_record('data_records', $recordtoupdate); 1059 1060 \core_tag_index_builder::reset_caches(); 1061 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1062 1063 $this->assertStringContainsString('value11', $res->content); 1064 $this->assertStringContainsString('value21', $res->content); 1065 } 1066 1067 public function test_mod_data_get_tagged_records_time() { 1068 global $DB; 1069 1070 $this->resetAfterTest(); 1071 $this->setAdminUser(); 1072 1073 // Setup test data. 1074 $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 1075 $course2 = $this->getDataGenerator()->create_course(); 1076 $course1 = $this->getDataGenerator()->create_course(); 1077 1078 $fieldrecord = new \stdClass(); 1079 $fieldrecord->name = 'field-1'; 1080 $fieldrecord->type = 'text'; 1081 1082 $timefrom = time() - YEARSECS; 1083 $timeto = time() - WEEKSECS; 1084 1085 $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course1->id, 'approval' => true)); 1086 $field1 = $datagenerator->create_field($fieldrecord, $data1); 1087 $data2 = $this->getDataGenerator()->create_module('data', array('course' => $course2->id, 1088 'timeviewfrom' => $timefrom, 1089 'timeviewto' => $timeto)); 1090 $field2 = $datagenerator->create_field($fieldrecord, $data2); 1091 $record11 = $datagenerator->create_entry($data1, [$field1->field->id => 'value11'], 0, ['Cats', 'Dogs']); 1092 $record21 = $datagenerator->create_entry($data2, [$field2->field->id => 'value21'], 0, ['Cats']); 1093 $tag = \core_tag_tag::get_by_name(0, 'Cats'); 1094 1095 // Admin can see everything. 1096 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1097 $this->assertStringContainsString('value11', $res->content); 1098 $this->assertStringContainsString('value21', $res->content); 1099 $this->assertEmpty($res->prevpageurl); 1100 $this->assertEmpty($res->nextpageurl); 1101 1102 // Create and enrol a user. 1103 $student = self::getDataGenerator()->create_user(); 1104 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1105 $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual'); 1106 $this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual'); 1107 $this->setUser($student); 1108 1109 // User can search data records inside a course. 1110 \core_tag_index_builder::reset_caches(); 1111 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1112 1113 $this->assertStringContainsString('value11', $res->content); 1114 $this->assertStringNotContainsString('value21', $res->content); 1115 1116 $data2->timeviewto = time() + YEARSECS; 1117 $DB->update_record('data', $data2); 1118 1119 \core_tag_index_builder::reset_caches(); 1120 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1121 1122 $this->assertStringContainsString('value11', $res->content); 1123 $this->assertStringContainsString('value21', $res->content); 1124 } 1125 1126 public function test_mod_data_get_tagged_records_course_enrolment() { 1127 global $DB; 1128 1129 $this->resetAfterTest(); 1130 $this->setAdminUser(); 1131 1132 // Setup test data. 1133 $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 1134 $course2 = $this->getDataGenerator()->create_course(); 1135 $course1 = $this->getDataGenerator()->create_course(); 1136 1137 $fieldrecord = new \stdClass(); 1138 $fieldrecord->name = 'field-1'; 1139 $fieldrecord->type = 'text'; 1140 1141 $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course1->id, 'approval' => true)); 1142 $field1 = $datagenerator->create_field($fieldrecord, $data1); 1143 $data2 = $this->getDataGenerator()->create_module('data', array('course' => $course2->id)); 1144 $field2 = $datagenerator->create_field($fieldrecord, $data2); 1145 1146 $record11 = $datagenerator->create_entry($data1, [$field1->field->id => 'value11'], 0, ['Cats', 'Dogs']); 1147 $record21 = $datagenerator->create_entry($data2, [$field2->field->id => 'value21'], 0, ['Cats']); 1148 $tag = \core_tag_tag::get_by_name(0, 'Cats'); 1149 1150 // Admin can see everything. 1151 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1152 $this->assertStringContainsString('value11', $res->content); 1153 $this->assertStringContainsString('value21', $res->content); 1154 $this->assertEmpty($res->prevpageurl); 1155 $this->assertEmpty($res->nextpageurl); 1156 1157 // Create and enrol a user. 1158 $student = self::getDataGenerator()->create_user(); 1159 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1160 $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual'); 1161 $this->setUser($student); 1162 \core_tag_index_builder::reset_caches(); 1163 1164 // User can search data records inside a course. 1165 $coursecontext = \context_course::instance($course1->id); 1166 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1167 1168 $this->assertStringContainsString('value11', $res->content); 1169 $this->assertStringNotContainsString('value21', $res->content); 1170 1171 $this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual'); 1172 1173 \core_tag_index_builder::reset_caches(); 1174 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1175 1176 $this->assertStringContainsString('value11', $res->content); 1177 $this->assertStringContainsString('value21', $res->content); 1178 } 1179 1180 public function test_mod_data_get_tagged_records_course_groups() { 1181 global $DB; 1182 1183 $this->resetAfterTest(); 1184 $this->setAdminUser(); 1185 1186 // Setup test data. 1187 $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 1188 $course2 = $this->getDataGenerator()->create_course(); 1189 $course1 = $this->getDataGenerator()->create_course(); 1190 1191 $groupa = $this->getDataGenerator()->create_group(array('courseid' => $course2->id, 'name' => 'groupA')); 1192 $groupb = $this->getDataGenerator()->create_group(array('courseid' => $course2->id, 'name' => 'groupB')); 1193 1194 $fieldrecord = new \stdClass(); 1195 $fieldrecord->name = 'field-1'; 1196 $fieldrecord->type = 'text'; 1197 1198 $data1 = $this->getDataGenerator()->create_module('data', array('course' => $course1->id, 'approval' => true)); 1199 $field1 = $datagenerator->create_field($fieldrecord, $data1); 1200 $data2 = $this->getDataGenerator()->create_module('data', array('course' => $course2->id)); 1201 $field2 = $datagenerator->create_field($fieldrecord, $data2); 1202 set_coursemodule_groupmode($data2->cmid, SEPARATEGROUPS); 1203 1204 $record11 = $datagenerator->create_entry($data1, [$field1->field->id => 'value11'], 1205 0, ['Cats', 'Dogs']); 1206 $record21 = $datagenerator->create_entry($data2, [$field2->field->id => 'value21'], 1207 $groupa->id, ['Cats']); 1208 $record22 = $datagenerator->create_entry($data2, [$field2->field->id => 'value22'], 1209 $groupb->id, ['Cats']); 1210 $tag = \core_tag_tag::get_by_name(0, 'Cats'); 1211 1212 // Admin can see everything. 1213 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1214 $this->assertStringContainsString('value11', $res->content); 1215 $this->assertStringContainsString('value21', $res->content); 1216 $this->assertStringContainsString('value22', $res->content); 1217 $this->assertEmpty($res->prevpageurl); 1218 $this->assertEmpty($res->nextpageurl); 1219 1220 // Create and enrol a user. 1221 $student = self::getDataGenerator()->create_user(); 1222 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1223 $this->getDataGenerator()->enrol_user($student->id, $course1->id, $studentrole->id, 'manual'); 1224 $this->getDataGenerator()->enrol_user($student->id, $course2->id, $studentrole->id, 'manual'); 1225 groups_add_member($groupa, $student); 1226 $this->setUser($student); 1227 \core_tag_index_builder::reset_caches(); 1228 1229 // User can search data records inside a course. 1230 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1231 1232 $this->assertStringContainsString('value11', $res->content); 1233 $this->assertStringContainsString('value21', $res->content); 1234 $this->assertStringNotContainsString('value22', $res->content); 1235 1236 groups_add_member($groupb, $student); 1237 \core_tag_index_builder::reset_caches(); 1238 $res = mod_data_get_tagged_records($tag, false, 0, 0, 1, 0); 1239 1240 $this->assertStringContainsString('value11', $res->content); 1241 $this->assertStringContainsString('value21', $res->content); 1242 $this->assertStringContainsString('value22', $res->content); 1243 } 1244 1245 /** 1246 * Test check_updates_since callback. 1247 */ 1248 public function test_check_updates_since() { 1249 global $DB; 1250 $this->resetAfterTest(); 1251 $this->setAdminUser(); 1252 $course = $this->getDataGenerator()->create_course(); 1253 // Create user. 1254 $student = self::getDataGenerator()->create_user(); 1255 // User enrolment. 1256 $studentrole = $DB->get_record('role', array('shortname' => 'student')); 1257 $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id, 'manual'); 1258 $this->setCurrentTimeStart(); 1259 $record = array( 1260 'course' => $course->id, 1261 ); 1262 $data = $this->getDataGenerator()->create_module('data', $record); 1263 $cm = get_coursemodule_from_instance('data', $data->id, $course->id); 1264 $cm = \cm_info::create($cm); 1265 $this->setUser($student); 1266 1267 // Check that upon creation, the updates are only about the new configuration created. 1268 $onehourago = time() - HOURSECS; 1269 $updates = data_check_updates_since($cm, $onehourago); 1270 foreach ($updates as $el => $val) { 1271 if ($el == 'configuration') { 1272 $this->assertTrue($val->updated); 1273 $this->assertTimeCurrent($val->timeupdated); 1274 } else { 1275 $this->assertFalse($val->updated); 1276 } 1277 } 1278 1279 // Add a couple of entries. 1280 $datagenerator = $this->getDataGenerator()->get_plugin_generator('mod_data'); 1281 $fieldtypes = array('checkbox', 'date'); 1282 1283 $count = 1; 1284 // Creating test Fields with default parameter values. 1285 foreach ($fieldtypes as $fieldtype) { 1286 // Creating variables dynamically. 1287 $fieldname = 'field-' . $count; 1288 $record = new \stdClass(); 1289 $record->name = $fieldname; 1290 $record->type = $fieldtype; 1291 $record->required = 1; 1292 1293 ${$fieldname} = $datagenerator->create_field($record, $data); 1294 $count++; 1295 } 1296 1297 $fields = $DB->get_records('data_fields', array('dataid' => $data->id), 'id'); 1298 1299 $contents = array(); 1300 $contents[] = array('opt1', 'opt2', 'opt3', 'opt4'); 1301 $contents[] = '01-01-2037'; // It should be lower than 2038, to avoid failing on 32-bit windows. 1302 $count = 0; 1303 $fieldcontents = array(); 1304 foreach ($fields as $fieldrecord) { 1305 $fieldcontents[$fieldrecord->id] = $contents[$count++]; 1306 } 1307 1308 $datarecor1did = $datagenerator->create_entry($data, $fieldcontents); 1309 $datarecor2did = $datagenerator->create_entry($data, $fieldcontents); 1310 $records = $DB->get_records('data_records', array('dataid' => $data->id)); 1311 $this->assertCount(2, $records); 1312 // Check we received the entries updated. 1313 $updates = data_check_updates_since($cm, $onehourago); 1314 $this->assertTrue($updates->entries->updated); 1315 $this->assertEqualsCanonicalizing([$datarecor1did, $datarecor2did], $updates->entries->itemids); 1316 } 1317 1318 public function test_data_core_calendar_provide_event_action_in_hidden_section() { 1319 global $CFG; 1320 1321 $this->resetAfterTest(); 1322 1323 $this->setAdminUser(); 1324 1325 // Create a course. 1326 $course = $this->getDataGenerator()->create_course(); 1327 1328 // Create a student. 1329 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 1330 1331 // Create a database activity. 1332 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1333 'timeavailablefrom' => time() - DAYSECS, 'timeavailableto' => time() + DAYSECS)); 1334 1335 // Create a calendar event. 1336 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1337 1338 // Set sections 0 as hidden. 1339 set_section_visible($course->id, 0, 0); 1340 1341 // Now, log out. 1342 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 1343 $this->setUser(); 1344 1345 // Create an action factory. 1346 $factory = new \core_calendar\action_factory(); 1347 1348 // Decorate action event for the student. 1349 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory, $student->id); 1350 1351 // Confirm the event is not shown at all. 1352 $this->assertNull($actionevent); 1353 } 1354 1355 public function test_data_core_calendar_provide_event_action_for_non_user() { 1356 global $CFG; 1357 1358 $this->resetAfterTest(); 1359 1360 $this->setAdminUser(); 1361 1362 // Create a course. 1363 $course = $this->getDataGenerator()->create_course(); 1364 1365 // Create a database activity. 1366 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1367 'timeavailablefrom' => time() - DAYSECS, 'timeavailableto' => time() + DAYSECS)); 1368 1369 // Create a calendar event. 1370 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1371 1372 // Now, log out. 1373 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 1374 $this->setUser(); 1375 1376 // Create an action factory. 1377 $factory = new \core_calendar\action_factory(); 1378 1379 // Decorate action event. 1380 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory); 1381 1382 // Confirm the event is not shown at all. 1383 $this->assertNull($actionevent); 1384 } 1385 1386 public function test_data_core_calendar_provide_event_action_open() { 1387 $this->resetAfterTest(); 1388 1389 $this->setAdminUser(); 1390 1391 // Create a course. 1392 $course = $this->getDataGenerator()->create_course(); 1393 1394 // Create a database activity. 1395 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1396 'timeavailablefrom' => time() - DAYSECS, 'timeavailableto' => time() + DAYSECS)); 1397 1398 // Create a calendar event. 1399 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1400 1401 // Create an action factory. 1402 $factory = new \core_calendar\action_factory(); 1403 1404 // Decorate action event. 1405 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory); 1406 1407 // Confirm the event was decorated. 1408 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 1409 $this->assertEquals(get_string('add', 'data'), $actionevent->get_name()); 1410 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 1411 $this->assertEquals(1, $actionevent->get_item_count()); 1412 $this->assertTrue($actionevent->is_actionable()); 1413 } 1414 1415 public function test_data_core_calendar_provide_event_action_open_for_user() { 1416 global $CFG; 1417 1418 $this->resetAfterTest(); 1419 1420 $this->setAdminUser(); 1421 1422 // Create a course. 1423 $course = $this->getDataGenerator()->create_course(); 1424 1425 // Create a student. 1426 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 1427 1428 // Create a database activity. 1429 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1430 'timeavailablefrom' => time() - DAYSECS, 'timeavailableto' => time() + DAYSECS)); 1431 1432 // Create a calendar event. 1433 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1434 1435 // Now log out. 1436 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 1437 $this->setUser(); 1438 1439 // Create an action factory. 1440 $factory = new \core_calendar\action_factory(); 1441 1442 // Decorate action event for the student. 1443 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory, $student->id); 1444 1445 // Confirm the event was decorated. 1446 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 1447 $this->assertEquals(get_string('add', 'data'), $actionevent->get_name()); 1448 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 1449 $this->assertEquals(1, $actionevent->get_item_count()); 1450 $this->assertTrue($actionevent->is_actionable()); 1451 } 1452 1453 public function test_data_core_calendar_provide_event_action_closed() { 1454 $this->resetAfterTest(); 1455 1456 $this->setAdminUser(); 1457 1458 // Create a course. 1459 $course = $this->getDataGenerator()->create_course(); 1460 1461 // Create a database activity. 1462 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1463 'timeavailableto' => time() - DAYSECS)); 1464 1465 // Create a calendar event. 1466 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1467 1468 // Create an action factory. 1469 $factory = new \core_calendar\action_factory(); 1470 1471 // Decorate action event. 1472 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory); 1473 1474 // No event on the dashboard if module is closed. 1475 $this->assertNull($actionevent); 1476 } 1477 1478 public function test_data_core_calendar_provide_event_action_closed_for_user() { 1479 $this->resetAfterTest(); 1480 1481 $this->setAdminUser(); 1482 1483 // Create a course. 1484 $course = $this->getDataGenerator()->create_course(); 1485 1486 // Create a student. 1487 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 1488 1489 // Create a database activity. 1490 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1491 'timeavailableto' => time() - DAYSECS)); 1492 1493 // Create a calendar event. 1494 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1495 1496 // Now log out. 1497 $this->setUser(); 1498 1499 // Create an action factory. 1500 $factory = new \core_calendar\action_factory(); 1501 1502 // Decorate action event for the student. 1503 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory, $student->id); 1504 1505 // No event on the dashboard if module is closed. 1506 $this->assertNull($actionevent); 1507 } 1508 1509 public function test_data_core_calendar_provide_event_action_open_in_future() { 1510 $this->resetAfterTest(); 1511 1512 $this->setAdminUser(); 1513 1514 // Create a course. 1515 $course = $this->getDataGenerator()->create_course(); 1516 1517 // Create a database activity. 1518 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1519 'timeavailablefrom' => time() + DAYSECS)); 1520 1521 // Create a calendar event. 1522 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1523 1524 // Create an action factory. 1525 $factory = new \core_calendar\action_factory(); 1526 1527 // Decorate action event. 1528 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory); 1529 1530 // Confirm the event was decorated. 1531 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 1532 $this->assertEquals(get_string('add', 'data'), $actionevent->get_name()); 1533 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 1534 $this->assertEquals(1, $actionevent->get_item_count()); 1535 $this->assertFalse($actionevent->is_actionable()); 1536 } 1537 1538 public function test_data_core_calendar_provide_event_action_open_in_future_for_user() { 1539 global $CFG; 1540 1541 $this->resetAfterTest(); 1542 1543 $this->setAdminUser(); 1544 1545 // Create a course. 1546 $course = $this->getDataGenerator()->create_course(); 1547 1548 // Create a student. 1549 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 1550 1551 // Create a database activity. 1552 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id, 1553 'timeavailablefrom' => time() + DAYSECS)); 1554 1555 // Create a calendar event. 1556 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1557 1558 // Now log out. 1559 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 1560 $this->setUser(); 1561 1562 // Create an action factory. 1563 $factory = new \core_calendar\action_factory(); 1564 1565 // Decorate action event for the student. 1566 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory, $student->id); 1567 1568 // Confirm the event was decorated. 1569 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 1570 $this->assertEquals(get_string('add', 'data'), $actionevent->get_name()); 1571 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 1572 $this->assertEquals(1, $actionevent->get_item_count()); 1573 $this->assertFalse($actionevent->is_actionable()); 1574 } 1575 1576 public function test_data_core_calendar_provide_event_action_no_time_specified() { 1577 $this->resetAfterTest(); 1578 1579 $this->setAdminUser(); 1580 1581 // Create a course. 1582 $course = $this->getDataGenerator()->create_course(); 1583 1584 // Create a database activity. 1585 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id)); 1586 1587 // Create a calendar event. 1588 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1589 1590 // Create an action factory. 1591 $factory = new \core_calendar\action_factory(); 1592 1593 // Decorate action event. 1594 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory); 1595 1596 // Confirm the event was decorated. 1597 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 1598 $this->assertEquals(get_string('add', 'data'), $actionevent->get_name()); 1599 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 1600 $this->assertEquals(1, $actionevent->get_item_count()); 1601 $this->assertTrue($actionevent->is_actionable()); 1602 } 1603 1604 public function test_data_core_calendar_provide_event_action_no_time_specified_for_user() { 1605 global $CFG; 1606 1607 $this->resetAfterTest(); 1608 1609 $this->setAdminUser(); 1610 1611 // Create a course. 1612 $course = $this->getDataGenerator()->create_course(); 1613 1614 // Create a student. 1615 $student = $this->getDataGenerator()->create_and_enrol($course, 'student'); 1616 1617 // Create a database activity. 1618 $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id)); 1619 1620 // Create a calendar event. 1621 $event = $this->create_action_event($course->id, $data->id, DATA_EVENT_TYPE_OPEN); 1622 1623 // Now log out. 1624 $CFG->forcelogin = true; // We don't want to be logged in as guest, as guest users might still have some capabilities. 1625 $this->setUser(); 1626 1627 // Create an action factory. 1628 $factory = new \core_calendar\action_factory(); 1629 1630 // Decorate action event for the student. 1631 $actionevent = mod_data_core_calendar_provide_event_action($event, $factory, $student->id); 1632 1633 // Confirm the event was decorated. 1634 $this->assertInstanceOf('\core_calendar\local\event\value_objects\action', $actionevent); 1635 $this->assertEquals(get_string('add', 'data'), $actionevent->get_name()); 1636 $this->assertInstanceOf('moodle_url', $actionevent->get_url()); 1637 $this->assertEquals(1, $actionevent->get_item_count()); 1638 $this->assertTrue($actionevent->is_actionable()); 1639 } 1640 1641 /** 1642 * Creates an action event. 1643 * 1644 * @param int $courseid 1645 * @param int $instanceid The data id. 1646 * @param string $eventtype The event type. eg. DATA_EVENT_TYPE_OPEN. 1647 * @param int|null $timestart The start timestamp for the event 1648 * @return bool|calendar_event 1649 */ 1650 private function create_action_event($courseid, $instanceid, $eventtype, $timestart = null) { 1651 $event = new \stdClass(); 1652 $event->name = 'Calendar event'; 1653 $event->modulename = 'data'; 1654 $event->courseid = $courseid; 1655 $event->instance = $instanceid; 1656 $event->type = CALENDAR_EVENT_TYPE_ACTION; 1657 $event->eventtype = $eventtype; 1658 if ($timestart) { 1659 $event->timestart = $timestart; 1660 } else { 1661 $event->timestart = time(); 1662 } 1663 1664 return \calendar_event::create($event); 1665 } 1666 1667 /** 1668 * Test the callback responsible for returning the completion rule descriptions. 1669 * This function should work given either an instance of the module (cm_info), such as when checking the active rules, 1670 * or if passed a stdClass of similar structure, such as when checking the the default completion settings for a mod type. 1671 */ 1672 public function test_mod_data_completion_get_active_rule_descriptions() { 1673 $this->resetAfterTest(); 1674 $this->setAdminUser(); 1675 1676 // Two activities, both with automatic completion. One has the 'completionentries' rule, one doesn't. 1677 $course = $this->getDataGenerator()->create_course(['enablecompletion' => 2]); 1678 $data1 = $this->getDataGenerator()->create_module('data', [ 1679 'course' => $course->id, 1680 'completion' => 2, 1681 'completionentries' => 3 1682 ]); 1683 $data2 = $this->getDataGenerator()->create_module('data', [ 1684 'course' => $course->id, 1685 'completion' => 2, 1686 'completionentries' => 0 1687 ]); 1688 $cm1 = \cm_info::create(get_coursemodule_from_instance('data', $data1->id)); 1689 $cm2 = \cm_info::create(get_coursemodule_from_instance('data', $data2->id)); 1690 1691 // Data for the stdClass input type. 1692 // This type of input would occur when checking the default completion rules for an activity type, where we don't have 1693 // any access to cm_info, rather the input is a stdClass containing completion and customdata attributes, just like cm_info. 1694 $moddefaults = new \stdClass(); 1695 $moddefaults->customdata = ['customcompletionrules' => ['completionentries' => 3]]; 1696 $moddefaults->completion = 2; 1697 1698 $activeruledescriptions = [get_string('completionentriesdesc', 'data', 3)]; 1699 $this->assertEquals(mod_data_get_completion_active_rule_descriptions($cm1), $activeruledescriptions); 1700 $this->assertEquals(mod_data_get_completion_active_rule_descriptions($cm2), []); 1701 $this->assertEquals(mod_data_get_completion_active_rule_descriptions($moddefaults), $activeruledescriptions); 1702 $this->assertEquals(mod_data_get_completion_active_rule_descriptions(new \stdClass()), []); 1703 } 1704 1705 /** 1706 * An unknown event type should not change the data instance. 1707 */ 1708 public function test_mod_data_core_calendar_event_timestart_updated_unknown_event() { 1709 global $CFG, $DB; 1710 require_once($CFG->dirroot . "/calendar/lib.php"); 1711 1712 $this->resetAfterTest(true); 1713 $this->setAdminUser(); 1714 $generator = $this->getDataGenerator(); 1715 $course = $generator->create_course(); 1716 $datagenerator = $generator->get_plugin_generator('mod_data'); 1717 $timeopen = time(); 1718 $timeclose = $timeopen + DAYSECS; 1719 $data = $datagenerator->create_instance(['course' => $course->id]); 1720 $data->timeavailablefrom = $timeopen; 1721 $data->timeavailableto = $timeclose; 1722 $DB->update_record('data', $data); 1723 1724 // Create a valid event. 1725 $event = new \calendar_event([ 1726 'name' => 'Test event', 1727 'description' => '', 1728 'format' => 1, 1729 'courseid' => $course->id, 1730 'groupid' => 0, 1731 'userid' => 2, 1732 'modulename' => 'data', 1733 'instance' => $data->id, 1734 'eventtype' => DATA_EVENT_TYPE_OPEN . "SOMETHING ELSE", 1735 'timestart' => 1, 1736 'timeduration' => 86400, 1737 'visible' => 1 1738 ]); 1739 1740 mod_data_core_calendar_event_timestart_updated($event, $data); 1741 $data = $DB->get_record('data', ['id' => $data->id]); 1742 $this->assertEquals($timeopen, $data->timeavailablefrom); 1743 $this->assertEquals($timeclose, $data->timeavailableto); 1744 } 1745 1746 /** 1747 * A DATA_EVENT_TYPE_OPEN event should update the timeavailablefrom property of the data activity. 1748 */ 1749 public function test_mod_data_core_calendar_event_timestart_updated_open_event() { 1750 global $CFG, $DB; 1751 require_once($CFG->dirroot . "/calendar/lib.php"); 1752 1753 $this->resetAfterTest(true); 1754 $this->setAdminUser(); 1755 $generator = $this->getDataGenerator(); 1756 $course = $generator->create_course(); 1757 $datagenerator = $generator->get_plugin_generator('mod_data'); 1758 $timeopen = time(); 1759 $timeclose = $timeopen + DAYSECS; 1760 $timemodified = 1; 1761 $newtimeopen = $timeopen - DAYSECS; 1762 $data = $datagenerator->create_instance(['course' => $course->id]); 1763 $data->timeavailablefrom = $timeopen; 1764 $data->timeavailableto = $timeclose; 1765 $data->timemodified = $timemodified; 1766 $DB->update_record('data', $data); 1767 1768 // Create a valid event. 1769 $event = new \calendar_event([ 1770 'name' => 'Test event', 1771 'description' => '', 1772 'format' => 1, 1773 'courseid' => $course->id, 1774 'groupid' => 0, 1775 'userid' => 2, 1776 'modulename' => 'data', 1777 'instance' => $data->id, 1778 'eventtype' => DATA_EVENT_TYPE_OPEN, 1779 'timestart' => $newtimeopen, 1780 'timeduration' => 86400, 1781 'visible' => 1 1782 ]); 1783 1784 // Trigger and capture the event when adding a contact. 1785 $sink = $this->redirectEvents(); 1786 mod_data_core_calendar_event_timestart_updated($event, $data); 1787 $triggeredevents = $sink->get_events(); 1788 $moduleupdatedevents = array_filter($triggeredevents, function($e) { 1789 return is_a($e, 'core\event\course_module_updated'); 1790 }); 1791 $data = $DB->get_record('data', ['id' => $data->id]); 1792 1793 // Ensure the timeavailablefrom property matches the event timestart. 1794 $this->assertEquals($newtimeopen, $data->timeavailablefrom); 1795 // Ensure the timeavailableto isn't changed. 1796 $this->assertEquals($timeclose, $data->timeavailableto); 1797 // Ensure the timemodified property has been changed. 1798 $this->assertNotEquals($timemodified, $data->timemodified); 1799 // Confirm that a module updated event is fired when the module is changed. 1800 $this->assertNotEmpty($moduleupdatedevents); 1801 } 1802 1803 /** 1804 * A DATA_EVENT_TYPE_CLOSE event should update the timeavailableto property of the data activity. 1805 */ 1806 public function test_mod_data_core_calendar_event_timestart_updated_close_event() { 1807 global $CFG, $DB; 1808 require_once($CFG->dirroot . "/calendar/lib.php"); 1809 1810 $this->resetAfterTest(true); 1811 $this->setAdminUser(); 1812 $generator = $this->getDataGenerator(); 1813 $course = $generator->create_course(); 1814 $datagenerator = $generator->get_plugin_generator('mod_data'); 1815 $timeopen = time(); 1816 $timeclose = $timeopen + DAYSECS; 1817 $timemodified = 1; 1818 $newtimeclose = $timeclose + DAYSECS; 1819 $data = $datagenerator->create_instance(['course' => $course->id]); 1820 $data->timeavailablefrom = $timeopen; 1821 $data->timeavailableto = $timeclose; 1822 $data->timemodified = $timemodified; 1823 $DB->update_record('data', $data); 1824 1825 // Create a valid event. 1826 $event = new \calendar_event([ 1827 'name' => 'Test event', 1828 'description' => '', 1829 'format' => 1, 1830 'courseid' => $course->id, 1831 'groupid' => 0, 1832 'userid' => 2, 1833 'modulename' => 'data', 1834 'instance' => $data->id, 1835 'eventtype' => DATA_EVENT_TYPE_CLOSE, 1836 'timestart' => $newtimeclose, 1837 'timeduration' => 86400, 1838 'visible' => 1 1839 ]); 1840 1841 // Trigger and capture the event when adding a contact. 1842 $sink = $this->redirectEvents(); 1843 mod_data_core_calendar_event_timestart_updated($event, $data); 1844 $triggeredevents = $sink->get_events(); 1845 $moduleupdatedevents = array_filter($triggeredevents, function($e) { 1846 return is_a($e, 'core\event\course_module_updated'); 1847 }); 1848 $data = $DB->get_record('data', ['id' => $data->id]); 1849 1850 // Ensure the timeavailableto property matches the event timestart. 1851 $this->assertEquals($newtimeclose, $data->timeavailableto); 1852 // Ensure the timeavailablefrom isn't changed. 1853 $this->assertEquals($timeopen, $data->timeavailablefrom); 1854 // Ensure the timemodified property has been changed. 1855 $this->assertNotEquals($timemodified, $data->timemodified); 1856 // Confirm that a module updated event is fired when the module is changed. 1857 $this->assertNotEmpty($moduleupdatedevents); 1858 } 1859 1860 /** 1861 * An unknown event type should not have any limits. 1862 */ 1863 public function test_mod_data_core_calendar_get_valid_event_timestart_range_unknown_event() { 1864 global $CFG; 1865 require_once($CFG->dirroot . "/calendar/lib.php"); 1866 1867 $this->resetAfterTest(true); 1868 $this->setAdminUser(); 1869 $generator = $this->getDataGenerator(); 1870 $course = $generator->create_course(); 1871 $timeopen = time(); 1872 $timeclose = $timeopen + DAYSECS; 1873 $data = new \stdClass(); 1874 $data->timeavailablefrom = $timeopen; 1875 $data->timeavailableto = $timeclose; 1876 1877 // Create a valid event. 1878 $event = new \calendar_event([ 1879 'name' => 'Test event', 1880 'description' => '', 1881 'format' => 1, 1882 'courseid' => $course->id, 1883 'groupid' => 0, 1884 'userid' => 2, 1885 'modulename' => 'data', 1886 'instance' => 1, 1887 'eventtype' => DATA_EVENT_TYPE_OPEN . "SOMETHING ELSE", 1888 'timestart' => 1, 1889 'timeduration' => 86400, 1890 'visible' => 1 1891 ]); 1892 1893 list ($min, $max) = mod_data_core_calendar_get_valid_event_timestart_range($event, $data); 1894 $this->assertNull($min); 1895 $this->assertNull($max); 1896 } 1897 1898 /** 1899 * The open event should be limited by the data's timeclose property, if it's set. 1900 */ 1901 public function test_mod_data_core_calendar_get_valid_event_timestart_range_open_event() { 1902 global $CFG; 1903 require_once($CFG->dirroot . "/calendar/lib.php"); 1904 1905 $this->resetAfterTest(true); 1906 $this->setAdminUser(); 1907 $generator = $this->getDataGenerator(); 1908 $course = $generator->create_course(); 1909 $timeopen = time(); 1910 $timeclose = $timeopen + DAYSECS; 1911 $data = new \stdClass(); 1912 $data->timeavailablefrom = $timeopen; 1913 $data->timeavailableto = $timeclose; 1914 1915 // Create a valid event. 1916 $event = new \calendar_event([ 1917 'name' => 'Test event', 1918 'description' => '', 1919 'format' => 1, 1920 'courseid' => $course->id, 1921 'groupid' => 0, 1922 'userid' => 2, 1923 'modulename' => 'data', 1924 'instance' => 1, 1925 'eventtype' => DATA_EVENT_TYPE_OPEN, 1926 'timestart' => 1, 1927 'timeduration' => 86400, 1928 'visible' => 1 1929 ]); 1930 1931 // The max limit should be bounded by the timeclose value. 1932 list ($min, $max) = mod_data_core_calendar_get_valid_event_timestart_range($event, $data); 1933 $this->assertNull($min); 1934 $this->assertEquals($timeclose, $max[0]); 1935 1936 // No timeclose value should result in no upper limit. 1937 $data->timeavailableto = 0; 1938 list ($min, $max) = mod_data_core_calendar_get_valid_event_timestart_range($event, $data); 1939 $this->assertNull($min); 1940 $this->assertNull($max); 1941 } 1942 1943 /** 1944 * The close event should be limited by the data's timeavailablefrom property, if it's set. 1945 */ 1946 public function test_mod_data_core_calendar_get_valid_event_timestart_range_close_event() { 1947 global $CFG; 1948 1949 require_once($CFG->dirroot . "/calendar/lib.php"); 1950 1951 $this->resetAfterTest(true); 1952 $this->setAdminUser(); 1953 $generator = $this->getDataGenerator(); 1954 $course = $generator->create_course(); 1955 $timeopen = time(); 1956 $timeclose = $timeopen + DAYSECS; 1957 $data = new \stdClass(); 1958 $data->timeavailablefrom = $timeopen; 1959 $data->timeavailableto = $timeclose; 1960 1961 // Create a valid event. 1962 $event = new \calendar_event([ 1963 'name' => 'Test event', 1964 'description' => '', 1965 'format' => 1, 1966 'courseid' => $course->id, 1967 'groupid' => 0, 1968 'userid' => 2, 1969 'modulename' => 'data', 1970 'instance' => 1, 1971 'eventtype' => DATA_EVENT_TYPE_CLOSE, 1972 'timestart' => 1, 1973 'timeduration' => 86400, 1974 'visible' => 1 1975 ]); 1976 1977 // The max limit should be bounded by the timeclose value. 1978 list ($min, $max) = mod_data_core_calendar_get_valid_event_timestart_range($event, $data); 1979 $this->assertEquals($timeopen, $min[0]); 1980 $this->assertNull($max); 1981 1982 // No timeavailableto value should result in no upper limit. 1983 $data->timeavailablefrom = 0; 1984 list ($min, $max) = mod_data_core_calendar_get_valid_event_timestart_range($event, $data); 1985 $this->assertNull($min); 1986 $this->assertNull($max); 1987 } 1988 1989 /** 1990 * A user who does not have capabilities to add events to the calendar should be able to create an database. 1991 */ 1992 public function test_creation_with_no_calendar_capabilities() { 1993 $this->resetAfterTest(); 1994 $course = self::getDataGenerator()->create_course(); 1995 $context = \context_course::instance($course->id); 1996 $user = self::getDataGenerator()->create_and_enrol($course, 'editingteacher'); 1997 $roleid = self::getDataGenerator()->create_role(); 1998 self::getDataGenerator()->role_assign($roleid, $user->id, $context->id); 1999 assign_capability('moodle/calendar:manageentries', CAP_PROHIBIT, $roleid, $context, true); 2000 $generator = self::getDataGenerator()->get_plugin_generator('mod_data'); 2001 // Create an instance as a user without the calendar capabilities. 2002 $this->setUser($user); 2003 $time = time(); 2004 $params = array( 2005 'course' => $course->id, 2006 'timeavailablefrom' => $time + 200, 2007 'timeavailableto' => $time + 2000, 2008 'timeviewfrom' => $time + 400, 2009 'timeviewto' => $time + 2000, 2010 ); 2011 $generator->create_instance($params); 2012 } 2013 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body