1<?php 2// This file is part of Moodle - http://moodle.org/ 3// 4// Moodle is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 8// 9// Moodle is distributed in the hope that it will be useful, 10// but WITHOUT ANY WARRANTY; without even the implied warranty of 11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12// GNU General Public License for more details. 13// 14// You should have received a copy of the GNU General Public License 15// along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17/** 18 * Tests for customfields in courses 19 * 20 * @package core_course 21 * @copyright 2018 Marina Glancy 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25defined('MOODLE_INTERNAL') || die(); 26 27global $CFG; 28require_once($CFG->dirroot . '/backup/util/includes/backup_includes.php'); 29require_once($CFG->dirroot . '/backup/util/includes/restore_includes.php'); 30 31/** 32 * Tests for customfields in courses 33 * 34 * @package core_course 35 * @copyright 2018 Marina Glancy 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38class core_course_customfield_testcase extends advanced_testcase { 39 40 /** 41 * Set up 42 */ 43 protected function setUp(): void { 44 parent::setUp(); 45 $this->resetAfterTest(); 46 $this->setAdminUser(); 47 48 $dg = self::getDataGenerator(); 49 $catid = $dg->create_custom_field_category([])->get('id'); 50 $dg->create_custom_field(['categoryid' => $catid, 'type' => 'text', 'shortname' => 'f1']); 51 $dg->create_custom_field(['categoryid' => $catid, 'type' => 'checkbox', 'shortname' => 'f2']); 52 $dg->create_custom_field(['categoryid' => $catid, 'type' => 'date', 'shortname' => 'f3', 53 'configdata' => ['startyear' => 2000, 'endyear' => 3000, 'includetime' => 1]]); 54 $dg->create_custom_field(['categoryid' => $catid, 'type' => 'select', 'shortname' => 'f4', 55 'configdata' => ['options' => "a\nb\nc"]]); 56 $dg->create_custom_field(['categoryid' => $catid, 'type' => 'textarea', 'shortname' => 'f5']); 57 } 58 59 /** 60 * Test creating course with customfields and retrieving them 61 */ 62 public function test_create_course() { 63 global $DB; 64 $dg = $this->getDataGenerator(); 65 66 $now = time(); 67 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 68 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 69 'customfield_f1' => 'some text', 'customfield_f2' => 1, 70 'customfield_f3' => $now, 'customfield_f4' => 2, 71 'customfield_f5_editor' => ['text' => 'test', 'format' => FORMAT_HTML]]); 72 73 $data = \core_course\customfield\course_handler::create()->export_instance_data_object($c1->id); 74 75 $this->assertEquals('some text', $data->f1); 76 $this->assertEquals('Yes', $data->f2); 77 $this->assertEquals(userdate($now, get_string('strftimedaydatetime')), $data->f3); 78 $this->assertEquals('b', $data->f4); 79 $this->assertEquals('test', $data->f5); 80 81 $this->assertEquals(5, count($DB->get_records('customfield_data'))); 82 83 delete_course($c1->id, false); 84 85 $this->assertEquals(0, count($DB->get_records('customfield_data'))); 86 } 87 88 /** 89 * Backup a course and return its backup ID. 90 * 91 * @param int $courseid The course ID. 92 * @param int $userid The user doing the backup. 93 * @return string 94 */ 95 protected function backup_course($courseid, $userid = 2) { 96 $backuptempdir = make_backup_temp_directory(''); 97 $packer = get_file_packer('application/vnd.moodle.backup'); 98 99 $bc = new backup_controller(backup::TYPE_1COURSE, $courseid, backup::FORMAT_MOODLE, backup::INTERACTIVE_NO, 100 backup::MODE_GENERAL, $userid); 101 $bc->execute_plan(); 102 103 $results = $bc->get_results(); 104 $results['backup_destination']->extract_to_pathname($packer, "$backuptempdir/core_course_testcase"); 105 106 $bc->destroy(); 107 unset($bc); 108 return 'core_course_testcase'; 109 } 110 111 /** 112 * Restore a course. 113 * 114 * @param int $backupid The backup ID. 115 * @param int $courseid The course ID to restore in, or 0. 116 * @param int $userid The ID of the user performing the restore. 117 * @return stdClass The updated course object. 118 */ 119 protected function restore_course($backupid, $courseid, $userid) { 120 global $DB; 121 122 $target = backup::TARGET_CURRENT_ADDING; 123 if (!$courseid) { 124 $target = backup::TARGET_NEW_COURSE; 125 $categoryid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); 126 $courseid = restore_dbops::create_new_course('Tmp', 'tmp', $categoryid); 127 } 128 129 $rc = new restore_controller($backupid, $courseid, backup::INTERACTIVE_NO, backup::MODE_GENERAL, $userid, $target); 130 $target == backup::TARGET_NEW_COURSE ?: $rc->get_plan()->get_setting('overwrite_conf')->set_value(true); 131 $this->assertTrue($rc->execute_precheck()); 132 $rc->execute_plan(); 133 134 $course = $DB->get_record('course', array('id' => $rc->get_courseid())); 135 136 $rc->destroy(); 137 unset($rc); 138 return $course; 139 } 140 141 /** 142 * Test backup and restore of custom fields 143 */ 144 public function test_restore_customfields() { 145 global $USER; 146 $dg = $this->getDataGenerator(); 147 148 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 149 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 150 'customfield_f1' => 'some text', 'customfield_f2' => 1]); 151 $backupid = $this->backup_course($c1->id); 152 153 // The information is restored but adapted because names are already taken. 154 $c2 = $this->restore_course($backupid, 0, $USER->id); 155 156 $data = \core_course\customfield\course_handler::create()->export_instance_data_object($c1->id); 157 $this->assertEquals('some text', $data->f1); 158 $this->assertEquals('Yes', $data->f2); 159 } 160 161 /** 162 * Delete a category that has fields and the fields have data. 163 */ 164 public function test_delete_category() { 165 global $DB; 166 $dg = $this->getDataGenerator(); 167 168 $now = time(); 169 $c1 = $dg->create_course(['shortname' => 'SN', 'fullname' => 'FN', 170 'summary' => 'DESC', 'summaryformat' => FORMAT_MOODLE, 171 'customfield_f1' => 'some text', 'customfield_f2' => 1, 172 'customfield_f3' => $now, 'customfield_f4' => 2, 173 'customfield_f5_editor' => ['text' => 'test', 'format' => FORMAT_HTML]]); 174 175 // Find the category and delete it. 176 $cats = \core_course\customfield\course_handler::create()->get_categories_with_fields(); 177 $cat = reset($cats); 178 $cat->get_handler()->delete_category($cat); 179 180 // Course no longer has the customfield properties. 181 $course = course_get_format($c1->id)->get_course(); 182 $keys = array_keys((array)$course); 183 $this->assertEmpty(array_intersect($keys, ['customfield_f1', 'customfield_f2', 184 'customfield_f3', 'customfield_f4', 'customfield_f5'])); 185 186 // Nothing in customfield tables either. 187 $this->assertEquals(0, count($DB->get_records('customfield_field'))); 188 $this->assertEquals(0, count($DB->get_records('customfield_data'))); 189 } 190 191} 192