Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 39 and 401]

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