. /** * Data generator. * * @package core * @category phpunit * @copyright 2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ /** * Data generator class for unit tests and other tools * that need to create fake test sites. * * @package core * @category phpunit * @copyright 2012 Petr Skoda {@link http://skodak.org} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class phpunit_data_generator { protected $usercounter = 0; protected $categorycount = 0; protected $cohortcount = 0; protected $coursecount = 0; protected $scalecount = 0; protected $groupcount = 0; protected $groupingcount = 0; /** @var array list of plugin generators */ protected $generators = array(); /** @var array lis of common last names */ public $lastnames = array( 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Miller', 'Davis', 'García', 'Rodríguez', 'Wilson', 'Müller', 'Schmidt', 'Schneider', 'Fischer', 'Meyer', 'Weber', 'Schulz', 'Wagner', 'Becker', 'Hoffmann', 'Novák', 'Svoboda', 'Novotný', 'Dvořák', 'Černý', 'Procházková', 'Kučerová', 'Veselá', 'Horáková', 'Němcová', 'Смирнов', 'Иванов', 'Кузнецов', 'Соколов', 'Попов', 'Лебедева', 'Козлова', 'Новикова', 'Морозова', 'Петрова', '王', '李', '张', '刘', '陈', '楊', '黃', '趙', '吳', '周', '佐藤', '鈴木', '高橋', '田中', '渡辺', '伊藤', '山本', '中村', '小林', '斎藤', ); /** @var array lis of common first names */ public $firstnames = array( 'Jacob', 'Ethan', 'Michael', 'Jayden', 'William', 'Isabella', 'Sophia', 'Emma', 'Olivia', 'Ava', 'Lukas', 'Leon', 'Luca', 'Timm', 'Paul', 'Leonie', 'Leah', 'Lena', 'Hanna', 'Laura', 'Jakub', 'Jan', 'Tomáš', 'Lukáš', 'Matěj', 'Tereza', 'Eliška', 'Anna', 'Adéla', 'Karolína', 'Даниил', 'Максим', 'Артем', 'Иван', 'Александр', 'София', 'Анастасия', 'Дарья', 'Мария', 'Полина', '伟', '伟', '芳', '伟', '秀英', '秀英', '娜', '秀英', '伟', '敏', '翔', '大翔', '拓海', '翔太', '颯太', '陽菜', 'さくら', '美咲', '葵', '美羽', ); public $loremipsum = <<usercounter = 0; $this->categorycount = 0; $this->coursecount = 0; $this->scalecount = 0; foreach($this->generators as $generator) { $generator->reset(); } } /** * Return generator for given plugin * @param string $component * @return mixed plugin data generator */ public function get_plugin_generator($component) { list($type, $plugin) = normalize_component($component); if ($type !== 'mod' and $type !== 'block') { throw new coding_exception("Plugin type $type does not support generators yet"); } $dir = get_plugin_directory($type, $plugin); if (!isset($this->generators[$type.'_'.$plugin])) { $lib = "$dir/tests/generator/lib.php"; if (!include_once($lib)) { throw new coding_exception("Plugin $component does not support data generator, missing tests/generator/lib"); } $classname = $type.'_'.$plugin.'_generator'; $this->generators[$type.'_'.$plugin] = new $classname($this); } return $this->generators[$type.'_'.$plugin]; } /** * Create a test user * @param array|stdClass $record * @param array $options * @return stdClass user record */ public function create_user($record=null, array $options=null) { global $DB, $CFG; $this->usercounter++; $i = $this->usercounter; $record = (array)$record; if (!isset($record['auth'])) { $record['auth'] = 'manual'; } if (!isset($record['firstname']) and !isset($record['lastname'])) { $country = rand(0, 5); $firstname = rand(0, 4); $lastname = rand(0, 4); $female = rand(0, 1); $record['firstname'] = $this->firstnames[($country*10) + $firstname + ($female*5)]; $record['lastname'] = $this->lastnames[($country*10) + $lastname + ($female*5)]; } else if (!isset($record['firstname'])) { $record['firstname'] = 'Firstname'.$i; } else if (!isset($record['lastname'])) { $record['lastname'] = 'Lastname'.$i; } if (!isset($record['idnumber'])) { $record['idnumber'] = ''; } if (!isset($record['mnethostid'])) { $record['mnethostid'] = $CFG->mnet_localhost_id; } if (!isset($record['username'])) { $record['username'] = 'username'.$i; $j = 2; while ($DB->record_exists('user', array('username'=>$record['username'], 'mnethostid'=>$record['mnethostid']))) { $record['username'] = 'username'.$i.'_'.$j; $j++; } } if (!isset($record['password'])) { $record['password'] = 'lala'; } if (!isset($record['email'])) { $record['email'] = $record['username'].'@example.com'; } if (!isset($record['confirmed'])) { $record['confirmed'] = 1; } if (!isset($record['lang'])) { $record['lang'] = 'en'; } if (!isset($record['maildisplay'])) { $record['maildisplay'] = 1; } if (!isset($record['deleted'])) { $record['deleted'] = 0; } $record['timecreated'] = time(); $record['timemodified'] = $record['timecreated']; $record['lastip'] = '0.0.0.0'; $record['password'] = hash_internal_user_password($record['password']); if ($record['deleted']) { $delname = $record['email'].'.'.time(); while ($DB->record_exists('user', array('username'=>$delname))) { $delname++; } $record['idnumber'] = ''; $record['email'] = md5($record['username']); $record['username'] = $delname; $record['picture'] = 0; } $userid = $DB->insert_record('user', $record); if (!$record['deleted']) { context_user::instance($userid); } return $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST); } /** * Create a test course category * @param array|stdClass $record * @param array $options * @return stdClass course category record */ public function create_category($record=null, array $options=null) { global $DB, $CFG; require_once("$CFG->dirroot/course/lib.php"); $this->categorycount++; $i = $this->categorycount; $record = (array)$record; if (!isset($record['name'])) { $record['name'] = 'Course category '.$i; } if (!isset($record['idnumber'])) { $record['idnumber'] = ''; } if (!isset($record['description'])) { $record['description'] = "Test course category $i\n$this->loremipsum"; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } if (!isset($record['parent'])) { $record['parent'] = 0; } if (empty($record['parent'])) { $parent = new stdClass(); $parent->path = ''; $parent->depth = 0; } else { $parent = $DB->get_record('course_categories', array('id'=>$record['parent']), '*', MUST_EXIST); } $record['depth'] = $parent->depth+1; $record['sortorder'] = 0; $record['timemodified'] = time(); $record['timecreated'] = $record['timemodified']; $catid = $DB->insert_record('course_categories', $record); $path = $parent->path . '/' . $catid; $DB->set_field('course_categories', 'path', $path, array('id'=>$catid)); context_coursecat::instance($catid); fix_course_sortorder(); return $DB->get_record('course_categories', array('id'=>$catid), '*', MUST_EXIST); } /** * Create test cohort. * @param array|stdClass $record * @param array $options * @return stdClass cohort record */ public function create_cohort($record=null, array $options=null) { global $DB, $CFG; require_once("$CFG->dirroot/cohort/lib.php"); $this->cohortcount++; $i = $this->cohortcount; $record = (array)$record; if (!isset($record['contextid'])) { $record['contextid'] = context_system::instance()->id; } if (!isset($record['name'])) { $record['name'] = 'Cohort '.$i; } if (!isset($record['idnumber'])) { $record['idnumber'] = ''; } if (!isset($record['description'])) { $record['description'] = "Test cohort $i\n$this->loremipsum"; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } if (!isset($record['component'])) { $record['component'] = ''; } $id = cohort_add_cohort((object)$record); return $DB->get_record('cohort', array('id'=>$id), '*', MUST_EXIST); } /** * Create a test course * @param array|stdClass $record * @param array $options with keys: * 'createsections'=>bool precreate all sections * @return stdClass course record */ public function create_course($record=null, array $options=null) { global $DB, $CFG; require_once("$CFG->dirroot/course/lib.php"); $this->coursecount++; $i = $this->coursecount; $record = (array)$record; if (!isset($record['fullname'])) { $record['fullname'] = 'Test course '.$i; } if (!isset($record['shortname'])) { $record['shortname'] = 'tc_'.$i; } if (!isset($record['idnumber'])) { $record['idnumber'] = ''; } if (!isset($record['format'])) { $record['format'] = 'topics'; } if (!isset($record['newsitems'])) { $record['newsitems'] = 0; } if (!isset($record['numsections'])) { $record['numsections'] = 5; } if (!isset($record['summary'])) { $record['summary'] = "Test course $i\n$this->loremipsum"; } if (!isset($record['summaryformat'])) { $record['summaryformat'] = FORMAT_MOODLE; } if (!isset($record['category'])) { $record['category'] = $DB->get_field_select('course_categories', "MIN(id)", "parent=0"); } $course = create_course((object)$record); context_course::instance($course->id); if (!empty($options['createsections'])) { for($i=1; $i<$record['numsections']; $i++) { self::create_course_section(array('course'=>$course->id, 'section'=>$i)); } } return $course; } /** * Create course section if does not exist yet * @param mixed $record * @param array|null $options * @return stdClass * @throws coding_exception */ public function create_course_section($record = null, array $options = null) { global $DB; $record = (array)$record; if (empty($record['course'])) { throw new coding_exception('course must be present in phpunit_util::create_course_section() $record'); } if (!isset($record['section'])) { throw new coding_exception('section must be present in phpunit_util::create_course_section() $record'); } if (!isset($record['name'])) { $record['name'] = ''; } if (!isset($record['summary'])) { $record['summary'] = ''; } if (!isset($record['summaryformat'])) { $record['summaryformat'] = FORMAT_MOODLE; } if ($section = $DB->get_record('course_sections', array('course'=>$record['course'], 'section'=>$record['section']))) { return $section; } $section = new stdClass(); $section->course = $record['course']; $section->section = $record['section']; $section->name = $record['name']; $section->summary = $record['summary']; $section->summaryformat = $record['summaryformat']; $id = $DB->insert_record('course_sections', $section); return $DB->get_record('course_sections', array('id'=>$id)); } /** * Create a test block * @param string $blockname * @param array|stdClass $record * @param array $options * @return stdClass block instance record */ public function create_block($blockname, $record=null, array $options=null) { $generator = $this->get_plugin_generator('block_'.$blockname); return $generator->create_instance($record, $options); } /** * Create a test module * @param string $modulename * @param array|stdClass $record * @param array $options * @return stdClass activity record */ public function create_module($modulename, $record=null, array $options=null) { $generator = $this->get_plugin_generator('mod_'.$modulename); return $generator->create_instance($record, $options); } /** * Create a test group for the specified course * * $record should be either an array or a stdClass containing infomation about the group to create. * At the very least it needs to contain courseid. * Default values are added for name, description, and descriptionformat if they are not present. * * This function calls {@see groups_create_group()} to create the group within the database. * * @param array|stdClass $record * @return stdClass group record */ public function create_group($record) { global $DB, $CFG; require_once($CFG->dirroot . '/group/lib.php'); $this->groupcount++; $i = $this->groupcount; $record = (array)$record; if (empty($record['courseid'])) { throw new coding_exception('courseid must be present in phpunit_util::create_group() $record'); } if (!isset($record['name'])) { $record['name'] = 'group-' . $i; } if (!isset($record['description'])) { $record['description'] = "Test Group $i\n{$this->loremipsum}"; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } $id = groups_create_group((object)$record); return $DB->get_record('groups', array('id'=>$id)); } /** * Create a test grouping for the specified course * * $record should be either an array or a stdClass containing infomation about the grouping to create. * At the very least it needs to contain courseid. * Default values are added for name, description, and descriptionformat if they are not present. * * This function calls {@see groups_create_grouping()} to create the grouping within the database. * * @param array|stdClass $record * @return stdClass grouping record */ public function create_grouping($record) { global $DB, $CFG; require_once($CFG->dirroot . '/group/lib.php'); $this->groupingcount++; $i = $this->groupingcount; $record = (array)$record; if (empty($record['courseid'])) { throw new coding_exception('courseid must be present in phpunit_util::create_grouping() $record'); } if (!isset($record['name'])) { $record['name'] = 'grouping-' . $i; } if (!isset($record['description'])) { $record['description'] = "Test Grouping $i\n{$this->loremipsum}"; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } $id = groups_create_grouping((object)$record); return $DB->get_record('groupings', array('id'=>$id)); } /** * Create a test scale * @param array|stdClass $record * @param array $options * @return stdClass block instance record */ public function create_scale($record=null, array $options=null) { global $DB; $this->scalecount++; $i = $this->scalecount; $record = (array)$record; if (!isset($record['name'])) { $record['name'] = 'Test scale '.$i; } if (!isset($record['scale'])) { $record['scale'] = 'A,B,C,D,F'; } if (!isset($record['courseid'])) { $record['courseid'] = 0; } if (!isset($record['userid'])) { $record['userid'] = 0; } if (!isset($record['description'])) { $record['description'] = 'Test scale description '.$i; } if (!isset($record['descriptionformat'])) { $record['descriptionformat'] = FORMAT_MOODLE; } $record['timemodified'] = time(); if (isset($record['id'])) { $DB->import_record('scale', $record); $DB->get_manager()->reset_sequence('scale'); $id = $record['id']; } else { $id = $DB->insert_record('scale', $record); } return $DB->get_record('scale', array('id'=>$id), '*', MUST_EXIST); } }