PageRenderTime 30ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 2ms

/course/tests/courselib_test.php

https://bitbucket.org/moodle/moodle
PHP | 7236 lines | 5235 code | 904 blank | 1097 comment | 67 complexity | ed1a88cd9991921cf45ed72a920840df MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1, BSD-3-Clause, MIT, GPL-3.0

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

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