PageRenderTime 70ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 2ms

/course/tests/courselib_test.php

http://github.com/moodle/moodle
PHP | 7022 lines | 5081 code | 872 blank | 1069 comment | 65 complexity | a297622f3cca4ec62c336ac19a97aab9 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  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. * Course related unit tests
  18. *
  19. * @package core
  20. * @category phpunit
  21. * @copyright 2012 Petr Skoda {@link http://skodak.org}
  22. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23. */
  24. defined('MOODLE_INTERNAL') || die();
  25. global $CFG;
  26. require_once($CFG->dirroot . '/course/lib.php');
  27. require_once($CFG->dirroot . '/course/tests/fixtures/course_capability_assignment.php');
  28. require_once($CFG->dirroot . '/enrol/imsenterprise/tests/imsenterprise_test.php');
  29. class core_course_courselib_testcase extends advanced_testcase {
  30. /**
  31. * Set forum specific test values for calling create_module().
  32. *
  33. * @param object $moduleinfo - the moduleinfo to add some specific values - passed in reference.
  34. */
  35. private function forum_create_set_values(&$moduleinfo) {
  36. // Completion specific to forum - optional.
  37. $moduleinfo->completionposts = 3;
  38. $moduleinfo->completiondiscussions = 1;
  39. $moduleinfo->completionreplies = 2;
  40. // Specific values to the Forum module.
  41. $moduleinfo->forcesubscribe = FORUM_INITIALSUBSCRIBE;
  42. $moduleinfo->type = 'single';
  43. $moduleinfo->trackingtype = FORUM_TRACKING_FORCED;
  44. $moduleinfo->maxbytes = 10240;
  45. $moduleinfo->maxattachments = 2;
  46. // Post threshold for blocking - specific to forum.
  47. $moduleinfo->blockperiod = 60*60*24;
  48. $moduleinfo->blockafter = 10;
  49. $moduleinfo->warnafter = 5;
  50. // Grading of whole forum settings.
  51. $moduleinfo->grade_forum = 0;
  52. }
  53. /**
  54. * Execute test asserts on the saved DB data by create_module($forum).
  55. *
  56. * @param object $moduleinfo - the specific forum values that were used to create a forum.
  57. * @param object $dbmodinstance - the DB values of the created forum.
  58. */
  59. private function forum_create_run_asserts($moduleinfo, $dbmodinstance) {
  60. // Compare values specific to forums.
  61. $this->assertEquals($moduleinfo->forcesubscribe, $dbmodinstance->forcesubscribe);
  62. $this->assertEquals($moduleinfo->type, $dbmodinstance->type);
  63. $this->assertEquals($moduleinfo->assessed, $dbmodinstance->assessed);
  64. $this->assertEquals($moduleinfo->completionposts, $dbmodinstance->completionposts);
  65. $this->assertEquals($moduleinfo->completiondiscussions, $dbmodinstance->completiondiscussions);
  66. $this->assertEquals($moduleinfo->completionreplies, $dbmodinstance->completionreplies);
  67. $this->assertEquals($moduleinfo->scale, $dbmodinstance->scale);
  68. $this->assertEquals($moduleinfo->assesstimestart, $dbmodinstance->assesstimestart);
  69. $this->assertEquals($moduleinfo->assesstimefinish, $dbmodinstance->assesstimefinish);
  70. $this->assertEquals($moduleinfo->rsstype, $dbmodinstance->rsstype);
  71. $this->assertEquals($moduleinfo->rssarticles, $dbmodinstance->rssarticles);
  72. $this->assertEquals($moduleinfo->trackingtype, $dbmodinstance->trackingtype);
  73. $this->assertEquals($moduleinfo->maxbytes, $dbmodinstance->maxbytes);
  74. $this->assertEquals($moduleinfo->maxattachments, $dbmodinstance->maxattachments);
  75. $this->assertEquals($moduleinfo->blockperiod, $dbmodinstance->blockperiod);
  76. $this->assertEquals($moduleinfo->blockafter, $dbmodinstance->blockafter);
  77. $this->assertEquals($moduleinfo->warnafter, $dbmodinstance->warnafter);
  78. }
  79. /**
  80. * Set assign module specific test values for calling create_module().
  81. *
  82. * @param object $moduleinfo - the moduleinfo to add some specific values - passed in reference.
  83. */
  84. private function assign_create_set_values(&$moduleinfo) {
  85. // Specific values to the Assign module.
  86. $moduleinfo->alwaysshowdescription = true;
  87. $moduleinfo->submissiondrafts = true;
  88. $moduleinfo->requiresubmissionstatement = true;
  89. $moduleinfo->sendnotifications = true;
  90. $moduleinfo->sendlatenotifications = true;
  91. $moduleinfo->duedate = time() + (7 * 24 * 3600);
  92. $moduleinfo->cutoffdate = time() + (7 * 24 * 3600);
  93. $moduleinfo->gradingduedate = time() + (7 * 24 * 3600);
  94. $moduleinfo->allowsubmissionsfromdate = time();
  95. $moduleinfo->teamsubmission = true;
  96. $moduleinfo->requireallteammemberssubmit = true;
  97. $moduleinfo->teamsubmissiongroupingid = true;
  98. $moduleinfo->blindmarking = true;
  99. $moduleinfo->markingworkflow = true;
  100. $moduleinfo->markingallocation = true;
  101. $moduleinfo->assignsubmission_onlinetext_enabled = true;
  102. $moduleinfo->assignsubmission_file_enabled = true;
  103. $moduleinfo->assignsubmission_file_maxfiles = 1;
  104. $moduleinfo->assignsubmission_file_maxsizebytes = 1000000;
  105. $moduleinfo->assignsubmission_comments_enabled = true;
  106. $moduleinfo->assignfeedback_comments_enabled = true;
  107. $moduleinfo->assignfeedback_offline_enabled = true;
  108. $moduleinfo->assignfeedback_file_enabled = true;
  109. // Advanced grading.
  110. $gradingmethods = grading_manager::available_methods();
  111. $moduleinfo->advancedgradingmethod_submissions = current(array_keys($gradingmethods));
  112. }
  113. /**
  114. * Execute test asserts on the saved DB data by create_module($assign).
  115. *
  116. * @param object $moduleinfo - the specific assign module values that were used to create an assign module.
  117. * @param object $dbmodinstance - the DB values of the created assign module.
  118. */
  119. private function assign_create_run_asserts($moduleinfo, $dbmodinstance) {
  120. global $DB;
  121. $this->assertEquals($moduleinfo->alwaysshowdescription, $dbmodinstance->alwaysshowdescription);
  122. $this->assertEquals($moduleinfo->submissiondrafts, $dbmodinstance->submissiondrafts);
  123. $this->assertEquals($moduleinfo->requiresubmissionstatement, $dbmodinstance->requiresubmissionstatement);
  124. $this->assertEquals($moduleinfo->sendnotifications, $dbmodinstance->sendnotifications);
  125. $this->assertEquals($moduleinfo->duedate, $dbmodinstance->duedate);
  126. $this->assertEquals($moduleinfo->cutoffdate, $dbmodinstance->cutoffdate);
  127. $this->assertEquals($moduleinfo->allowsubmissionsfromdate, $dbmodinstance->allowsubmissionsfromdate);
  128. $this->assertEquals($moduleinfo->teamsubmission, $dbmodinstance->teamsubmission);
  129. $this->assertEquals($moduleinfo->requireallteammemberssubmit, $dbmodinstance->requireallteammemberssubmit);
  130. $this->assertEquals($moduleinfo->teamsubmissiongroupingid, $dbmodinstance->teamsubmissiongroupingid);
  131. $this->assertEquals($moduleinfo->blindmarking, $dbmodinstance->blindmarking);
  132. $this->assertEquals($moduleinfo->markingworkflow, $dbmodinstance->markingworkflow);
  133. $this->assertEquals($moduleinfo->markingallocation, $dbmodinstance->markingallocation);
  134. // The goal not being to fully test assign_add_instance() we'll stop here for the assign tests - to avoid too many DB queries.
  135. // Advanced grading.
  136. $cm = get_coursemodule_from_instance('assign', $dbmodinstance->id);
  137. $contextmodule = context_module::instance($cm->id);
  138. $advancedgradingmethod = $DB->get_record('grading_areas',
  139. array('contextid' => $contextmodule->id,
  140. 'activemethod' => $moduleinfo->advancedgradingmethod_submissions));
  141. $this->assertEquals($moduleinfo->advancedgradingmethod_submissions, $advancedgradingmethod);
  142. }
  143. /**
  144. * Run some asserts test for a specific module for the function create_module().
  145. *
  146. * The function has been created (and is called) for $this->test_create_module().
  147. * Note that the call to MODULE_create_set_values and MODULE_create_run_asserts are done after the common set values/run asserts.
  148. * So if you want, you can overwrite the default values/asserts in the respective functions.
  149. * @param string $modulename Name of the module ('forum', 'assign', 'book'...).
  150. */
  151. private function create_specific_module_test($modulename) {
  152. global $DB, $CFG;
  153. $this->resetAfterTest(true);
  154. $this->setAdminUser();
  155. // Warnings: you'll need to change this line if ever you come to test a module not following Moodle standard.
  156. require_once($CFG->dirroot.'/mod/'. $modulename .'/lib.php');
  157. // Enable avaibility.
  158. // If not enabled all conditional fields will be ignored.
  159. set_config('enableavailability', 1);
  160. // Enable course completion.
  161. // If not enabled all completion settings will be ignored.
  162. set_config('enablecompletion', COMPLETION_ENABLED);
  163. // Enable forum RSS feeds.
  164. set_config('enablerssfeeds', 1);
  165. set_config('forum_enablerssfeeds', 1);
  166. $course = $this->getDataGenerator()->create_course(array('numsections'=>1, 'enablecompletion' => COMPLETION_ENABLED),
  167. array('createsections'=>true));
  168. $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $course->id));
  169. // Create assign module instance for test.
  170. $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  171. $params['course'] = $course->id;
  172. $instance = $generator->create_instance($params);
  173. $assigncm = get_coursemodule_from_instance('assign', $instance->id);
  174. // Module test values.
  175. $moduleinfo = new stdClass();
  176. // Always mandatory generic values to any module.
  177. $moduleinfo->modulename = $modulename;
  178. $moduleinfo->section = 1; // This is the section number in the course. Not the section id in the database.
  179. $moduleinfo->course = $course->id;
  180. $moduleinfo->groupingid = $grouping->id;
  181. $moduleinfo->visible = true;
  182. $moduleinfo->visibleoncoursepage = true;
  183. // Sometimes optional generic values for some modules.
  184. $moduleinfo->name = 'My test module';
  185. $moduleinfo->showdescription = 1; // standard boolean
  186. require_once($CFG->libdir . '/gradelib.php');
  187. $gradecats = grade_get_categories_menu($moduleinfo->course, false);
  188. $gradecatid = current(array_keys($gradecats)); // Retrieve the first key of $gradecats
  189. $moduleinfo->gradecat = $gradecatid;
  190. $moduleinfo->groupmode = VISIBLEGROUPS;
  191. $moduleinfo->cmidnumber = 'idnumber_XXX';
  192. // Completion common to all module.
  193. $moduleinfo->completion = COMPLETION_TRACKING_AUTOMATIC;
  194. $moduleinfo->completionview = COMPLETION_VIEW_REQUIRED;
  195. $moduleinfo->completiongradeitemnumber = 1;
  196. $moduleinfo->completionexpected = time() + (7 * 24 * 3600);
  197. // Conditional activity.
  198. $moduleinfo->availability = '{"op":"&","showc":[true,true],"c":[' .
  199. '{"type":"date","d":">=","t":' . time() . '},' .
  200. '{"type":"date","d":"<","t":' . (time() + (7 * 24 * 3600)) . '}' .
  201. ']}';
  202. $coursegradeitem = grade_item::fetch_course_item($moduleinfo->course); //the activity will become available only when the user reach some grade into the course itself.
  203. $moduleinfo->conditiongradegroup = array(array('conditiongradeitemid' => $coursegradeitem->id, 'conditiongrademin' => 10, 'conditiongrademax' => 80));
  204. $moduleinfo->conditionfieldgroup = array(array('conditionfield' => 'email', 'conditionfieldoperator' => \availability_profile\condition::OP_CONTAINS, 'conditionfieldvalue' => '@'));
  205. $moduleinfo->conditioncompletiongroup = array(array('conditionsourcecmid' => $assigncm->id, 'conditionrequiredcompletion' => COMPLETION_COMPLETE)); // "conditionsourcecmid == 0" => none
  206. // Grading and Advanced grading.
  207. require_once($CFG->dirroot . '/rating/lib.php');
  208. $moduleinfo->assessed = RATING_AGGREGATE_AVERAGE;
  209. $moduleinfo->scale = 10; // Note: it could be minus (for specific course scale). It is a signed number.
  210. $moduleinfo->assesstimestart = time();
  211. $moduleinfo->assesstimefinish = time() + (7 * 24 * 3600);
  212. // RSS.
  213. $moduleinfo->rsstype = 2;
  214. $moduleinfo->rssarticles = 10;
  215. // Optional intro editor (depends of module).
  216. $draftid_editor = 0;
  217. file_prepare_draft_area($draftid_editor, null, null, null, null);
  218. $moduleinfo->introeditor = array('text' => 'This is a module', 'format' => FORMAT_HTML, 'itemid' => $draftid_editor);
  219. // Following is the advanced grading method area called 'submissions' for the 'assign' module.
  220. if (plugin_supports('mod', $modulename, FEATURE_GRADE_HAS_GRADE, false) && !plugin_supports('mod', $modulename, FEATURE_RATE, false)) {
  221. $moduleinfo->grade = 100;
  222. }
  223. // Plagiarism form values.
  224. // No plagiarism plugin installed by default. Use this space to make your own test.
  225. // Values specific to the module.
  226. $modulesetvalues = $modulename.'_create_set_values';
  227. $this->$modulesetvalues($moduleinfo);
  228. // Create the module.
  229. $result = create_module($moduleinfo);
  230. // Retrieve the module info.
  231. $dbmodinstance = $DB->get_record($moduleinfo->modulename, array('id' => $result->instance));
  232. $dbcm = get_coursemodule_from_instance($moduleinfo->modulename, $result->instance);
  233. // We passed the course section number to create_courses but $dbcm contain the section id.
  234. // We need to retrieve the db course section number.
  235. $section = $DB->get_record('course_sections', array('course' => $dbcm->course, 'id' => $dbcm->section));
  236. // Retrieve the grade item.
  237. $gradeitem = $DB->get_record('grade_items', array('courseid' => $moduleinfo->course,
  238. 'iteminstance' => $dbmodinstance->id, 'itemmodule' => $moduleinfo->modulename));
  239. // Compare the values common to all module instances.
  240. $this->assertEquals($moduleinfo->modulename, $dbcm->modname);
  241. $this->assertEquals($moduleinfo->section, $section->section);
  242. $this->assertEquals($moduleinfo->course, $dbcm->course);
  243. $this->assertEquals($moduleinfo->groupingid, $dbcm->groupingid);
  244. $this->assertEquals($moduleinfo->visible, $dbcm->visible);
  245. $this->assertEquals($moduleinfo->completion, $dbcm->completion);
  246. $this->assertEquals($moduleinfo->completionview, $dbcm->completionview);
  247. $this->assertEquals($moduleinfo->completiongradeitemnumber, $dbcm->completiongradeitemnumber);
  248. $this->assertEquals($moduleinfo->completionexpected, $dbcm->completionexpected);
  249. $this->assertEquals($moduleinfo->availability, $dbcm->availability);
  250. $this->assertEquals($moduleinfo->showdescription, $dbcm->showdescription);
  251. $this->assertEquals($moduleinfo->groupmode, $dbcm->groupmode);
  252. $this->assertEquals($moduleinfo->cmidnumber, $dbcm->idnumber);
  253. $this->assertEquals($moduleinfo->gradecat, $gradeitem->categoryid);
  254. // Optional grade testing.
  255. if (plugin_supports('mod', $modulename, FEATURE_GRADE_HAS_GRADE, false) && !plugin_supports('mod', $modulename, FEATURE_RATE, false)) {
  256. $this->assertEquals($moduleinfo->grade, $dbmodinstance->grade);
  257. }
  258. // Some optional (but quite common) to some module.
  259. $this->assertEquals($moduleinfo->name, $dbmodinstance->name);
  260. $this->assertEquals($moduleinfo->intro, $dbmodinstance->intro);
  261. $this->assertEquals($moduleinfo->introformat, $dbmodinstance->introformat);
  262. // Test specific to the module.
  263. $modulerunasserts = $modulename.'_create_run_asserts';
  264. $this->$modulerunasserts($moduleinfo, $dbmodinstance);
  265. return $moduleinfo;
  266. }
  267. /**
  268. * Create module associated blog and tags.
  269. *
  270. * @param object $course Course.
  271. * @param object $modulecontext The context of the module.
  272. */
  273. private function create_module_asscociated_blog($course, $modulecontext) {
  274. global $DB, $CFG;
  275. // Create default group.
  276. $group = new stdClass();
  277. $group->courseid = $course->id;
  278. $group->name = 'Group';
  279. $group->id = $DB->insert_record('groups', $group);
  280. // Create default user.
  281. $user = $this->getDataGenerator()->create_user(array(
  282. 'username' => 'testuser',
  283. 'firstname' => 'Firsname',
  284. 'lastname' => 'Lastname'
  285. ));
  286. // Create default post.
  287. $post = new stdClass();
  288. $post->userid = $user->id;
  289. $post->groupid = $group->id;
  290. $post->content = 'test post content text';
  291. $post->module = 'blog';
  292. $post->id = $DB->insert_record('post', $post);
  293. // Create default tag.
  294. $tag = $this->getDataGenerator()->create_tag(array('userid' => $user->id,
  295. 'rawname' => 'Testtagname', 'isstandard' => 1));
  296. // Apply the tag to the blog.
  297. $DB->insert_record('tag_instance', array('tagid' => $tag->id, 'itemtype' => 'user',
  298. 'component' => 'core', 'itemid' => $post->id, 'ordering' => 0));
  299. require_once($CFG->dirroot . '/blog/locallib.php');
  300. $blog = new blog_entry($post->id);
  301. $blog->add_association($modulecontext->id);
  302. return $blog;
  303. }
  304. /**
  305. * Test create_module() for multiple modules defined in the $modules array (first declaration of the function).
  306. */
  307. public function test_create_module() {
  308. // Add the module name you want to test here.
  309. // Create the match MODULENAME_create_set_values() and MODULENAME_create_run_asserts().
  310. $modules = array('forum', 'assign');
  311. // Run all tests.
  312. foreach ($modules as $modulename) {
  313. $this->create_specific_module_test($modulename);
  314. }
  315. }
  316. /**
  317. * Test update_module() for multiple modules defined in the $modules array (first declaration of the function).
  318. */
  319. public function test_update_module() {
  320. // Add the module name you want to test here.
  321. // Create the match MODULENAME_update_set_values() and MODULENAME_update_run_asserts().
  322. $modules = array('forum');
  323. // Run all tests.
  324. foreach ($modules as $modulename) {
  325. $this->update_specific_module_test($modulename);
  326. }
  327. }
  328. /**
  329. * Set forum specific test values for calling update_module().
  330. *
  331. * @param object $moduleinfo - the moduleinfo to add some specific values - passed in reference.
  332. */
  333. private function forum_update_set_values(&$moduleinfo) {
  334. // Completion specific to forum - optional.
  335. $moduleinfo->completionposts = 3;
  336. $moduleinfo->completiondiscussions = 1;
  337. $moduleinfo->completionreplies = 2;
  338. // Specific values to the Forum module.
  339. $moduleinfo->forcesubscribe = FORUM_INITIALSUBSCRIBE;
  340. $moduleinfo->type = 'single';
  341. $moduleinfo->trackingtype = FORUM_TRACKING_FORCED;
  342. $moduleinfo->maxbytes = 10240;
  343. $moduleinfo->maxattachments = 2;
  344. // Post threshold for blocking - specific to forum.
  345. $moduleinfo->blockperiod = 60*60*24;
  346. $moduleinfo->blockafter = 10;
  347. $moduleinfo->warnafter = 5;
  348. // Grading of whole forum settings.
  349. $moduleinfo->grade_forum = 0;
  350. }
  351. /**
  352. * Execute test asserts on the saved DB data by update_module($forum).
  353. *
  354. * @param object $moduleinfo - the specific forum values that were used to update a forum.
  355. * @param object $dbmodinstance - the DB values of the updated forum.
  356. */
  357. private function forum_update_run_asserts($moduleinfo, $dbmodinstance) {
  358. // Compare values specific to forums.
  359. $this->assertEquals($moduleinfo->forcesubscribe, $dbmodinstance->forcesubscribe);
  360. $this->assertEquals($moduleinfo->type, $dbmodinstance->type);
  361. $this->assertEquals($moduleinfo->assessed, $dbmodinstance->assessed);
  362. $this->assertEquals($moduleinfo->completionposts, $dbmodinstance->completionposts);
  363. $this->assertEquals($moduleinfo->completiondiscussions, $dbmodinstance->completiondiscussions);
  364. $this->assertEquals($moduleinfo->completionreplies, $dbmodinstance->completionreplies);
  365. $this->assertEquals($moduleinfo->scale, $dbmodinstance->scale);
  366. $this->assertEquals($moduleinfo->assesstimestart, $dbmodinstance->assesstimestart);
  367. $this->assertEquals($moduleinfo->assesstimefinish, $dbmodinstance->assesstimefinish);
  368. $this->assertEquals($moduleinfo->rsstype, $dbmodinstance->rsstype);
  369. $this->assertEquals($moduleinfo->rssarticles, $dbmodinstance->rssarticles);
  370. $this->assertEquals($moduleinfo->trackingtype, $dbmodinstance->trackingtype);
  371. $this->assertEquals($moduleinfo->maxbytes, $dbmodinstance->maxbytes);
  372. $this->assertEquals($moduleinfo->maxattachments, $dbmodinstance->maxattachments);
  373. $this->assertEquals($moduleinfo->blockperiod, $dbmodinstance->blockperiod);
  374. $this->assertEquals($moduleinfo->blockafter, $dbmodinstance->blockafter);
  375. $this->assertEquals($moduleinfo->warnafter, $dbmodinstance->warnafter);
  376. }
  377. /**
  378. * Test a specific type of module.
  379. *
  380. * @param string $modulename - the module name to test
  381. */
  382. private function update_specific_module_test($modulename) {
  383. global $DB, $CFG;
  384. $this->resetAfterTest(true);
  385. $this->setAdminUser();
  386. // Warnings: you'll need to change this line if ever you come to test a module not following Moodle standard.
  387. require_once($CFG->dirroot.'/mod/'. $modulename .'/lib.php');
  388. // Enable avaibility.
  389. // If not enabled all conditional fields will be ignored.
  390. set_config('enableavailability', 1);
  391. // Enable course completion.
  392. // If not enabled all completion settings will be ignored.
  393. set_config('enablecompletion', COMPLETION_ENABLED);
  394. // Enable forum RSS feeds.
  395. set_config('enablerssfeeds', 1);
  396. set_config('forum_enablerssfeeds', 1);
  397. $course = $this->getDataGenerator()->create_course(array('numsections'=>1, 'enablecompletion' => COMPLETION_ENABLED),
  398. array('createsections'=>true));
  399. $grouping = $this->getDataGenerator()->create_grouping(array('courseid' => $course->id));
  400. // Create assign module instance for testing gradeitem.
  401. $generator = $this->getDataGenerator()->get_plugin_generator('mod_assign');
  402. $params['course'] = $course->id;
  403. $instance = $generator->create_instance($params);
  404. $assigncm = get_coursemodule_from_instance('assign', $instance->id);
  405. // Create the test forum to update.
  406. $initvalues = new stdClass();
  407. $initvalues->introformat = FORMAT_HTML;
  408. $initvalues->course = $course->id;
  409. $forum = self::getDataGenerator()->create_module('forum', $initvalues);
  410. // Retrieve course module.
  411. $cm = get_coursemodule_from_instance('forum', $forum->id);
  412. // Module test values.
  413. $moduleinfo = new stdClass();
  414. // Always mandatory generic values to any module.
  415. $moduleinfo->coursemodule = $cm->id;
  416. $moduleinfo->modulename = $modulename;
  417. $moduleinfo->course = $course->id;
  418. $moduleinfo->groupingid = $grouping->id;
  419. $moduleinfo->visible = true;
  420. $moduleinfo->visibleoncoursepage = true;
  421. // Sometimes optional generic values for some modules.
  422. $moduleinfo->name = 'My test module';
  423. $moduleinfo->showdescription = 1; // standard boolean
  424. require_once($CFG->libdir . '/gradelib.php');
  425. $gradecats = grade_get_categories_menu($moduleinfo->course, false);
  426. $gradecatid = current(array_keys($gradecats)); // Retrieve the first key of $gradecats
  427. $moduleinfo->gradecat = $gradecatid;
  428. $moduleinfo->groupmode = VISIBLEGROUPS;
  429. $moduleinfo->cmidnumber = 'idnumber_XXX';
  430. // Completion common to all module.
  431. $moduleinfo->completion = COMPLETION_TRACKING_AUTOMATIC;
  432. $moduleinfo->completionview = COMPLETION_VIEW_REQUIRED;
  433. $moduleinfo->completiongradeitemnumber = 1;
  434. $moduleinfo->completionexpected = time() + (7 * 24 * 3600);
  435. $moduleinfo->completionunlocked = 1;
  436. // Conditional activity.
  437. $coursegradeitem = grade_item::fetch_course_item($moduleinfo->course); //the activity will become available only when the user reach some grade into the course itself.
  438. $moduleinfo->availability = json_encode(\core_availability\tree::get_root_json(
  439. array(\availability_date\condition::get_json('>=', time()),
  440. \availability_date\condition::get_json('<', time() + (7 * 24 * 3600)),
  441. \availability_grade\condition::get_json($coursegradeitem->id, 10, 80),
  442. \availability_profile\condition::get_json(false, 'email', 'contains', '@'),
  443. \availability_completion\condition::get_json($assigncm->id, COMPLETION_COMPLETE)), '&'));
  444. // Grading and Advanced grading.
  445. require_once($CFG->dirroot . '/rating/lib.php');
  446. $moduleinfo->assessed = RATING_AGGREGATE_AVERAGE;
  447. $moduleinfo->scale = 10; // Note: it could be minus (for specific course scale). It is a signed number.
  448. $moduleinfo->assesstimestart = time();
  449. $moduleinfo->assesstimefinish = time() + (7 * 24 * 3600);
  450. // RSS.
  451. $moduleinfo->rsstype = 2;
  452. $moduleinfo->rssarticles = 10;
  453. // Optional intro editor (depends of module).
  454. $draftid_editor = 0;
  455. file_prepare_draft_area($draftid_editor, null, null, null, null);
  456. $moduleinfo->introeditor = array('text' => 'This is a module', 'format' => FORMAT_HTML, 'itemid' => $draftid_editor);
  457. // Following is the advanced grading method area called 'submissions' for the 'assign' module.
  458. if (plugin_supports('mod', $modulename, FEATURE_GRADE_HAS_GRADE, false) && !plugin_supports('mod', $modulename, FEATURE_RATE, false)) {
  459. $moduleinfo->grade = 100;
  460. }
  461. // Plagiarism form values.
  462. // No plagiarism plugin installed by default. Use this space to make your own test.
  463. // Values specific to the module.
  464. $modulesetvalues = $modulename.'_update_set_values';
  465. $this->$modulesetvalues($moduleinfo);
  466. // Create the module.
  467. $result = update_module($moduleinfo);
  468. // Retrieve the module info.
  469. $dbmodinstance = $DB->get_record($moduleinfo->modulename, array('id' => $result->instance));
  470. $dbcm = get_coursemodule_from_instance($moduleinfo->modulename, $result->instance);
  471. // Retrieve the grade item.
  472. $gradeitem = $DB->get_record('grade_items', array('courseid' => $moduleinfo->course,
  473. 'iteminstance' => $dbmodinstance->id, 'itemmodule' => $moduleinfo->modulename));
  474. // Compare the values common to all module instances.
  475. $this->assertEquals($moduleinfo->modulename, $dbcm->modname);
  476. $this->assertEquals($moduleinfo->course, $dbcm->course);
  477. $this->assertEquals($moduleinfo->groupingid, $dbcm->groupingid);
  478. $this->assertEquals($moduleinfo->visible, $dbcm->visible);
  479. $this->assertEquals($moduleinfo->completion, $dbcm->completion);
  480. $this->assertEquals($moduleinfo->completionview, $dbcm->completionview);
  481. $this->assertEquals($moduleinfo->completiongradeitemnumber, $dbcm->completiongradeitemnumber);
  482. $this->assertEquals($moduleinfo->completionexpected, $dbcm->completionexpected);
  483. $this->assertEquals($moduleinfo->availability, $dbcm->availability);
  484. $this->assertEquals($moduleinfo->showdescription, $dbcm->showdescription);
  485. $this->assertEquals($moduleinfo->groupmode, $dbcm->groupmode);
  486. $this->assertEquals($moduleinfo->cmidnumber, $dbcm->idnumber);
  487. $this->assertEquals($moduleinfo->gradecat, $gradeitem->categoryid);
  488. // Optional grade testing.
  489. if (plugin_supports('mod', $modulename, FEATURE_GRADE_HAS_GRADE, false) && !plugin_supports('mod', $modulename, FEATURE_RATE, false)) {
  490. $this->assertEquals($moduleinfo->grade, $dbmodinstance->grade);
  491. }
  492. // Some optional (but quite common) to some module.
  493. $this->assertEquals($moduleinfo->name, $dbmodinstance->name);
  494. $this->assertEquals($moduleinfo->intro, $dbmodinstance->intro);
  495. $this->assertEquals($moduleinfo->introformat, $dbmodinstance->introformat);
  496. // Test specific to the module.
  497. $modulerunasserts = $modulename.'_update_run_asserts';
  498. $this->$modulerunasserts($moduleinfo, $dbmodinstance);
  499. return $moduleinfo;
  500. }
  501. /**
  502. * Data provider for course_delete module
  503. *
  504. * @return array An array of arrays contain test data
  505. */
  506. public function provider_course_delete_module() {
  507. $data = array();
  508. $data['assign'] = array('assign', array('duedate' => time()));
  509. $data['quiz'] = array('quiz', array('duedate' => time()));
  510. return $data;
  511. }
  512. /**
  513. * Test the create_course function
  514. */
  515. public function test_create_course() {
  516. global $DB;
  517. $this->resetAfterTest(true);
  518. $defaultcategory = $DB->get_field_select('course_categories', "MIN(id)", "parent=0");
  519. $course = new stdClass();
  520. $course->fullname = 'Apu loves Unit Təsts';
  521. $course->shortname = 'Spread the lŭve';
  522. $course->idnumber = '123';
  523. $course->summary = 'Awesome!';
  524. $course->summaryformat = FORMAT_PLAIN;
  525. $course->format = 'topics';
  526. $course->newsitems = 0;
  527. $course->category = $defaultcategory;
  528. $original = (array) $course;
  529. $created = create_course($course);
  530. $context = context_course::instance($created->id);
  531. // Compare original and created.
  532. $this->assertEquals($original, array_intersect_key((array) $created, $original));
  533. // Ensure default section is created.
  534. $sectioncreated = $DB->record_exists('course_sections', array('course' => $created->id, 'section' => 0));
  535. $this->assertTrue($sectioncreated);
  536. // Ensure that the shortname isn't duplicated.
  537. try {
  538. $created = create_course($course);
  539. $this->fail('Exception expected');
  540. } catch (moodle_exception $e) {
  541. $this->assertSame(get_string('shortnametaken', 'error', $course->shortname), $e->getMessage());
  542. }
  543. // Ensure that the idnumber isn't duplicated.
  544. $course->shortname .= '1';
  545. try {
  546. $created = create_course($course);
  547. $this->fail('Exception expected');
  548. } catch (moodle_exception $e) {
  549. $this->assertSame(get_string('courseidnumbertaken', 'error', $course->idnumber), $e->getMessage());
  550. }
  551. }
  552. public function test_create_course_with_generator() {
  553. global $DB;
  554. $this->resetAfterTest(true);
  555. $course = $this->getDataGenerator()->create_course();
  556. // Ensure default section is created.
  557. $sectioncreated = $DB->record_exists('course_sections', array('course' => $course->id, 'section' => 0));
  558. $this->assertTrue($sectioncreated);
  559. }
  560. public function test_create_course_sections() {
  561. global $DB;
  562. $this->resetAfterTest(true);
  563. $numsections = 5;
  564. $course = $this->getDataGenerator()->create_course(
  565. array('shortname' => 'GrowingCourse',
  566. 'fullname' => 'Growing Course',
  567. 'numsections' => $numsections),
  568. array('createsections' => true));
  569. // Ensure all 6 (0-5) sections were created and course content cache works properly
  570. $sectionscreated = array_keys(get_fast_modinfo($course)->get_section_info_all());
  571. $this->assertEquals(range(0, $numsections), $sectionscreated);
  572. // this will do nothing, section already exists
  573. $this->assertFalse(course_create_sections_if_missing($course, $numsections));
  574. // this will create new section
  575. $this->assertTrue(course_create_sections_if_missing($course, $numsections + 1));
  576. // Ensure all 7 (0-6) sections were created and modinfo/sectioninfo cache works properly
  577. $sectionscreated = array_keys(get_fast_modinfo($course)->get_section_info_all());
  578. $this->assertEquals(range(0, $numsections + 1), $sectionscreated);
  579. }
  580. public function test_update_course() {
  581. global $DB;
  582. $this->resetAfterTest();
  583. $defaultcategory = $DB->get_field_select('course_categories', 'MIN(id)', 'parent = 0');
  584. $course = new stdClass();
  585. $course->fullname = 'Apu loves Unit Təsts';
  586. $course->shortname = 'test1';
  587. $course->idnumber = '1';
  588. $course->summary = 'Awesome!';
  589. $course->summaryformat = FORMAT_PLAIN;
  590. $course->format = 'topics';
  591. $course->newsitems = 0;
  592. $course->numsections = 5;
  593. $course->category = $defaultcategory;
  594. $created = create_course($course);
  595. // Ensure the checks only work on idnumber/shortname that are not already ours.
  596. update_course($created);
  597. $course->shortname = 'test2';
  598. $course->idnumber = '2';
  599. $created2 = create_course($course);
  600. // Test duplicate idnumber.
  601. $created2->idnumber = '1';
  602. try {
  603. update_course($created2);
  604. $this->fail('Expected exception when trying to update a course with duplicate idnumber');
  605. } catch (moodle_exception $e) {
  606. $this->assertEquals(get_string('courseidnumbertaken', 'error', $created2->idnumber), $e->getMessage());
  607. }
  608. // Test duplicate shortname.
  609. $created2->idnumber = '2';
  610. $created2->shortname = 'test1';
  611. try {
  612. update_course($created2);
  613. $this->fail('Expected exception when trying to update a course with a duplicate shortname');
  614. } catch (moodle_exception $e) {
  615. $this->assertEquals(get_string('shortnametaken', 'error', $created2->shortname), $e->getMessage());
  616. }
  617. }
  618. public function test_update_course_section_time_modified() {
  619. global $DB;
  620. $this->resetAfterTest();
  621. // Create the course with sections.
  622. $course = $this->getDataGenerator()->create_course(array('numsections' => 10), array('createsections' => true));
  623. $sections = $DB->get_records('course_sections', array('course' => $course->id));
  624. // Get the last section's time modified value.
  625. $section = array_pop($sections);
  626. $oldtimemodified = $section->timemodified;
  627. // Update the section.
  628. $this->waitForSecond(); // Ensuring that the section update occurs at a different timestamp.
  629. course_update_section($course, $section, array());
  630. // Check that the time has changed.
  631. $section = $DB->get_record('course_sections', array('id' => $section->id));
  632. $newtimemodified = $section->timemodified;
  633. $this->assertGreaterThan($oldtimemodified, $newtimemodified);
  634. }
  635. /**
  636. * Relative dates mode settings provider for course creation.
  637. */
  638. public function create_course_relative_dates_provider() {
  639. return [
  640. [0, 0, 0],
  641. [0, 1, 0],
  642. [1, 0, 0],
  643. [1, 1, 1],
  644. ];
  645. }
  646. /**
  647. * Test create_course by attempting to change the relative dates mode.
  648. *
  649. * @dataProvider create_course_relative_dates_provider
  650. * @param int $setting The value for the 'enablecourserelativedates' admin setting.
  651. * @param int $mode The value for the course's 'relativedatesmode' field.
  652. * @param int $expectedvalue The expected value of the 'relativedatesmode' field after course creation.
  653. */
  654. public function test_relative_dates_mode_for_course_creation($setting, $mode, $expectedvalue) {
  655. global $DB;
  656. $this->resetAfterTest();
  657. set_config('enablecourserelativedates', $setting);
  658. // Generate a course with relative dates mode set to $mode.
  659. $course = $this->getDataGenerator()->create_course(['relativedatesmode' => $mode]);
  660. // Verify that the relative dates match what's expected.
  661. $relativedatesmode = $DB->get_field('course', 'relativedatesmode', ['id' => $course->id]);
  662. $this->assertEquals($expectedvalue, $relativedatesmode);
  663. }
  664. /**
  665. * Test update_course by attempting to change the relative dates mode.
  666. */
  667. public function test_relative_dates_mode_for_course_update() {
  668. global $DB;
  669. $this->resetAfterTest();
  670. set_config('enablecourserelativedates', 1);
  671. // Generate a course with relative dates mode set to 1.
  672. $course = $this->getDataGenerator()->create_course(['relativedatesmode' => 1]);
  673. // Attempt to update the course with a changed relativedatesmode.
  674. $course->relativedatesmode = 0;
  675. update_course($course);
  676. // Verify that the relative dates mode has not changed.
  677. $relativedatesmode = $DB->get_field('course', 'relativedatesmode', ['id' => $course->id]);
  678. $this->assertEquals(1, $relativedatesmode);
  679. }
  680. public function test_course_add_cm_to_section() {
  681. global $DB;
  682. $this->resetAfterTest(true);
  683. // Create course with 1 section.
  684. $course = $this->getDataGenerator()->create_course(
  685. array('shortname' => 'GrowingCourse',
  686. 'fullname' => 'Growing Course',
  687. 'numsections' => 1),
  688. array('createsections' => true));
  689. // Trash modinfo.
  690. rebuild_course_cache($course->id, true);
  691. // Create some cms for testing.
  692. $cmids = array();
  693. for ($i=0; $i<4; $i++) {
  694. $cmids[$i] = $DB->insert_record('course_modules', array('course' => $course->id));
  695. }
  696. // Add it to section that exists.
  697. course_add_cm_to_section($course, $cmids[0], 1);
  698. // Check it got added to sequence.
  699. $sequence = $DB->get_field('course_sections', 'sequence', array('course' => $course->id, 'section' => 1));
  700. $this->assertEquals($cmids[0], $sequence);
  701. // Add a second, this time using courseid variant of parameters.
  702. $coursecacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id));
  703. course_add_cm_to_section($course->id, $cmids[1], 1);
  704. $sequence = $DB->get_field('course_sections', 'sequence', array('course' => $course->id, 'section' => 1));
  705. $this->assertEquals($cmids[0] . ',' . $cmids[1], $sequence);
  706. // Check that modinfo cache was reset but not rebuilt (important for performance if calling repeatedly).
  707. $this->assertGreaterThan($coursecacherev, $DB->get_field('course', 'cacherev', array('id' => $course->id)));
  708. $this->assertEmpty(cache::make('core', 'coursemodinfo')->get($course->id));
  709. // Add one to section that doesn't exist (this might rebuild modinfo).
  710. course_add_cm_to_section($course, $cmids[2], 2);
  711. $this->assertEquals(3, $DB->count_records('course_sections', array('course' => $course->id)));
  712. $sequence = $DB->get_field('course_sections', 'sequence', array('course' => $course->id, 'section' => 2));
  713. $this->assertEquals($cmids[2], $sequence);
  714. // Add using the 'before' option.
  715. course_add_cm_to_section($course, $cmids[3], 2, $cmids[2]);
  716. $this->assertEquals(3, $DB->count_records('course_sections', array('course' => $course->id)));
  717. $sequence = $DB->get_field('course_sections', 'sequence', array('course' => $course->id, 'section' => 2));
  718. $this->assertEquals($cmids[3] . ',' . $cmids[2], $sequence);
  719. }
  720. public function test_reorder_sections() {
  721. global $DB;
  722. $this->resetAfterTest(true);
  723. $this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
  724. $course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
  725. $oldsections = array();
  726. $sections = array();
  727. foreach ($DB->get_records('course_sections', array('course'=>$course->id), 'id') as $section) {
  728. $oldsections[$section->section] = $section->id;
  729. $sections[$section->id] = $section->section;
  730. }
  731. ksort($oldsections);
  732. $neworder = reorder_sections($sections, 2, 4);
  733. $neworder = array_keys($neworder);
  734. $this->assertEquals($oldsections[0], $neworder[0]);
  735. $this->assertEquals($oldsections[1], $neworder[1]);
  736. $this->assertEquals($oldsections[2], $neworder[4]);
  737. $this->assertEquals($oldsections[3], $neworder[2]);
  738. $this->assertEquals($oldsections[4], $neworder[3]);
  739. $this->assertEquals($oldsections[5], $neworder[5]);
  740. $this->assertEquals($oldsections[6], $neworder[6]);
  741. $neworder = reorder_sections($sections, 4, 2);
  742. $neworder = array_keys($neworder);
  743. $this->assertEquals($oldsections[0], $neworder[0]);
  744. $this->assertEquals($oldsections[1], $neworder[1]);
  745. $this->assertEquals($oldsections[2], $neworder[3]);
  746. $this->assertEquals($oldsections[3], $neworder[4]);
  747. $this->assertEquals($oldsections[4], $neworder[2]);
  748. $this->assertEquals($oldsections[5], $neworder[5]);
  749. $this->assertEquals($oldsections[6], $neworder[6]);
  750. $neworder = reorder_sections(1, 2, 4);
  751. $this->assertFalse($neworder);
  752. }
  753. public function test_move_section_down() {
  754. global $DB;
  755. $this->resetAfterTest(true);
  756. $this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
  757. $course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
  758. $oldsections = array();
  759. foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
  760. $oldsections[$section->section] = $section->id;
  761. }
  762. ksort($oldsections);
  763. // Test move section down..
  764. move_section_to($course, 2, 4);
  765. $sections = array();
  766. foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
  767. $sections[$section->section] = $section->id;
  768. }
  769. ksort($sections);
  770. $this->assertEquals($oldsections[0], $sections[0]);
  771. $this->assertEquals($oldsections[1], $sections[1]);
  772. $this->assertEquals($oldsections[2], $sections[4]);
  773. $this->assertEquals($oldsections[3], $sections[2]);
  774. $this->assertEquals($oldsections[4], $sections[3]);
  775. $this->assertEquals($oldsections[5], $sections[5]);
  776. $this->assertEquals($oldsections[6], $sections[6]);
  777. }
  778. public function test_move_section_up() {
  779. global $DB;
  780. $this->resetAfterTest(true);
  781. $this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
  782. $course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
  783. $oldsections = array();
  784. foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
  785. $oldsections[$section->section] = $section->id;
  786. }
  787. ksort($oldsections);
  788. // Test move section up..
  789. move_section_to($course, 6, 4);
  790. $sections = array();
  791. foreach ($DB->get_records('course_sections', array('course'=>$course->id)) as $section) {
  792. $sections[$section->section] = $section->id;
  793. }
  794. ksort($sections);
  795. $this->assertEquals($oldsections[0], $sections[0]);
  796. $this->assertEquals($oldsections[1], $sections[1]);
  797. $this->assertEquals($oldsections[2], $sections[2]);
  798. $this->assertEquals($oldsections[3], $sections[3]);
  799. $this->assertEquals($oldsections[4], $sections[5]);
  800. $this->assertEquals($oldsections[5], $sections[6]);
  801. $this->assertEquals($oldsections[6], $sections[4]);
  802. }
  803. public function test_move_section_marker() {
  804. global $DB;
  805. $this->resetAfterTest(true);
  806. $this->getDataGenerator()->create_course(array('numsections'=>5), array('createsections'=>true));
  807. $course = $this->getDataGenerator()->create_course(array('numsections'=>10), array('createsections'=>true));
  808. // Set course marker to the section we are going to move..
  809. course_set_marker($course->id, 2);
  810. // Verify that the course marker is set correctly.
  811. $course = $DB->get_record('course', array('id' => $course->id));
  812. $this->assertEquals(2, $course->marker);
  813. // Test move the marked section down..
  814. move_section_to($course, 2, 4);
  815. // Verify that the course marker has been moved along with the section..
  816. $course = $DB->get_record('course', array('id' => $course->id));
  817. $this->assertEquals(4, $course->marker);
  818. // Test move the marked section up..
  819. move_section_to($course, 4, 3);
  820. // Verify that the course marker has been moved along with the section..
  821. $course = $DB->get_record('course', array('id' => $course->id));
  822. $this->assertEquals(3, $course->marker);
  823. // Test moving a non-marked section above the marked section..
  824. move_section_to($course, 4, 2);
  825. // Verify that the course marker has been moved down to accomodate..
  826. $course = $DB->get_record('course', array('id' => $course->id));
  827. $this->assertEquals(4, $course->marker);
  828. // Test moving a non-marked section below the marked section..
  829. move_section_to($course, 3, 6);
  830. // Verify that the course marker has been up to accomodate..
  831. $course = $DB->get_record('course', array('id' => $course->id));
  832. $this->assertEquals(3, $course->marker);
  833. }
  834. public function test_course_can_delete_section() {
  835. global $DB;
  836. $this->resetAfterTest(true);
  837. $generator = $this->getDataGenerator();
  838. $courseweeks = $generator->create_course(
  839. array('numsections' => 5, 'format' => 'weeks'),
  840. array('createsections' => true));
  841. $assign1 = $generator->create_module('assign', array('course' => $courseweeks, 'section' => 1));
  842. $assign2 = $generator->create_module('assign', array('course' => $courseweeks, 'section' => 2));
  843. $coursetopics = $generator->create_course(
  844. array('numsections' => 5, 'format' => 'topics'),
  845. array('createsections' => true));
  846. $coursesingleactivity = $generator->create_course(
  847. array('format' => 'singleactivity'),
  848. array('createsections' => true));
  849. // Enrol student and teacher.
  850. $roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
  851. $student = $generator->create_user();
  852. $teacher = $generator->create_user();
  853. $generator->enrol_user($student->id, $courseweeks->id, $roleids['student']);
  854. $generator->enrol_user($teacher->id, $courseweeks->id, $roleids['editingteacher']);
  855. $generator->enrol_user($student->id, $coursetopics->id, $roleids['student']);
  856. $generator->enrol_user($teacher->id, $coursetopics->id, $roleids['editingteacher']);
  857. $generator->enrol_user($student->id, $coursesingleactivity->id, $roleids['student']);
  858. $generator->enrol_user($teacher->id, $coursesingleactivity->id, $roleids['editingteacher']);
  859. // Teacher should be able to delete sections (except for 0) in topics and weeks format.
  860. $this->setUser($teacher);
  861. // For topics and weeks formats will return false for section 0 and true for any other section.
  862. $this->assertFalse(course_can_delete_section($courseweeks, 0));
  863. $this->assertTrue(course_can_delete_section($courseweeks, 1));
  864. $this->assertFalse(course_can_delete_section($coursetopics, 0));
  865. $this->assertTrue(course_can_delete_section($coursetopics, 1));
  866. // For singleactivity course format no section can be deleted.
  867. $this->assertFalse(course_can_delete_section($coursesingleactivity, 0));
  868. $this->assertFalse(course_can_delete_section($coursesingleactivity, 1));
  869. // Now let's revoke a capability from teacher to manage activity in section 1.
  870. $modulecontext = context_module::instance($assign1->cmid);
  871. assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $roleids['editingteacher'],
  872. $modulecontext);
  873. $this->assertFalse(course_can_delete_section($courseweeks, 1));
  874. $this->assertTrue(course_can_delete_section($courseweeks, 2));
  875. // Student does not have permissions to delete sections.
  876. $this->setUser($student);
  877. $this->assertFalse(course_can_delete_section($courseweeks, 1));
  878. $this->assertFalse(course_can_delete_section($coursetopics, 1));
  879. $this->assertFalse(course_can_delete_section($coursesingleactivity, 1));
  880. }
  881. public function test_course_delete_section() {
  882. global $DB;
  883. $this->resetAfterTest(true);
  884. $generator = $this->getDataGenerator();
  885. $course = $generator->create_course(array('numsections' => 6, 'format' => 'topics'),
  886. array('createsections' => true));
  887. $assign0 = $generator->create_module('assign', array('course' => $c

Large files files are truncated, but you can click here to view the full file