Merge branch 'MDL-32780-CLEAN' of git://github.com/netspotau/moodle-mod_assign
[moodle.git] / lib / phpunit / generatorlib.php
blob224334201d88373dc17779155a093c7551232bb0
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.
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/>.
17 /**
18 * PHPUnit data generator class
20 * @package core
21 * @category phpunit
22 * @copyright 2012 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
29 /**
30 * Data generator for unit tests
32 * @package core
33 * @category phpunit
34 * @copyright 2012 Petr Skoda {@link http://skodak.org}
35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 class phpunit_data_generator {
38 protected $usercounter = 0;
39 protected $categorycount = 0;
40 protected $coursecount = 0;
41 protected $scalecount = 0;
42 protected $groupcount = 0;
43 protected $groupingcount = 0;
45 /** @var array list of plugin generators */
46 protected $generators = array();
48 /** @var array lis of common last names */
49 public $lastnames = array(
50 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Miller', 'Davis', 'García', 'Rodríguez', 'Wilson',
51 'Müller', 'Schmidt', 'Schneider', 'Fischer', 'Meyer', 'Weber', 'Schulz', 'Wagner', 'Becker', 'Hoffmann',
52 'Novák', 'Svoboda', 'Novotný', 'Dvořák', 'Černý', 'Procházková', 'Kučerová', 'Veselá', 'Horáková', 'Němcová',
53 'Смирнов', 'Иванов', 'Кузнецов', 'Соколов', 'Попов', 'Лебедева', 'Козлова', 'Новикова', 'Морозова', 'Петрова',
54 '王', '李', '张', '刘', '陈', '楊', '黃', '趙', '吳', '周',
55 '佐藤', '鈴木', '高橋', '田中', '渡辺', '伊藤', '山本', '中村', '小林', '斎藤',
58 /** @var array lis of common first names */
59 public $firstnames = array(
60 'Jacob', 'Ethan', 'Michael', 'Jayden', 'William', 'Isabella', 'Sophia', 'Emma', 'Olivia', 'Ava',
61 'Lukas', 'Leon', 'Luca', 'Timm', 'Paul', 'Leonie', 'Leah', 'Lena', 'Hanna', 'Laura',
62 'Jakub', 'Jan', 'Tomáš', 'Lukáš', 'Matěj', 'Tereza', 'Eliška', 'Anna', 'Adéla', 'Karolína',
63 'Даниил', 'Максим', 'Артем', 'Иван', 'Александр', 'София', 'Анастасия', 'Дарья', 'Мария', 'Полина',
64 '伟', '伟', '芳', '伟', '秀英', '秀英', '娜', '秀英', '伟', '敏',
65 '翔', '大翔', '拓海', '翔太', '颯太', '陽菜', 'さくら', '美咲', '葵', '美羽',
68 public $loremipsum = <<<EOD
69 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nulla non arcu lacinia neque faucibus fringilla. Vivamus porttitor turpis ac leo. Integer in sapien. Nullam eget nisl. Aliquam erat volutpat. Cras elementum. Mauris suscipit, ligula sit amet pharetra semper, nibh ante cursus purus, vel sagittis velit mauris vel metus. Integer malesuada. Nullam lectus justo, vulputate eget mollis sed, tempor sed magna. Mauris elementum mauris vitae tortor. Aliquam erat volutpat.
70 Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Pellentesque ipsum. Cras pede libero, dapibus nec, pretium sit amet, tempor quis. Aliquam ante. Proin in tellus sit amet nibh dignissim sagittis. Vivamus porttitor turpis ac leo. Duis bibendum, lectus ut viverra rhoncus, dolor nunc faucibus libero, eget facilisis enim ipsum id lacus. In sem justo, commodo ut, suscipit at, pharetra vitae, orci. Aliquam erat volutpat. Nulla est.
71 Vivamus luctus egestas leo. Aenean fermentum risus id tortor. Mauris dictum facilisis augue. Aliquam erat volutpat. Aliquam ornare wisi eu metus. Aliquam id dolor. Duis condimentum augue id magna semper rutrum. Donec iaculis gravida nulla. Pellentesque ipsum. Etiam dictum tincidunt diam. Quisque tincidunt scelerisque libero. Etiam egestas wisi a erat.
72 Integer lacinia. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris tincidunt sem sed arcu. Nullam feugiat, turpis at pulvinar vulputate, erat libero tristique tellus, nec bibendum odio risus sit amet ante. Aliquam id dolor. Maecenas sollicitudin. Et harum quidem rerum facilis est et expedita distinctio. Mauris suscipit, ligula sit amet pharetra semper, nibh ante cursus purus, vel sagittis velit mauris vel metus. Nullam dapibus fermentum ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Pellentesque sapien. Duis risus. Mauris elementum mauris vitae tortor. Suspendisse nisl. Integer rutrum, orci vestibulum ullamcorper ultricies, lacus quam ultricies odio, vitae placerat pede sem sit amet enim.
73 In laoreet, magna id viverra tincidunt, sem odio bibendum justo, vel imperdiet sapien wisi sed libero. Proin pede metus, vulputate nec, fermentum fringilla, vehicula vitae, justo. Nullam justo enim, consectetuer nec, ullamcorper ac, vestibulum in, elit. Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur? Maecenas lorem. Etiam posuere lacus quis dolor. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Curabitur ligula sapien, pulvinar a vestibulum quis, facilisis vel sapien. Nam sed tellus id magna elementum tincidunt. Suspendisse nisl. Vivamus luctus egestas leo. Nulla non arcu lacinia neque faucibus fringilla. Etiam dui sem, fermentum vitae, sagittis id, malesuada in, quam. Etiam dictum tincidunt diam. Etiam commodo dui eget wisi. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Proin pede metus, vulputate nec, fermentum fringilla, vehicula vitae, justo. Duis ante orci, molestie vitae vehicula venenatis, tincidunt ac pede. Pellentesque sapien.
74 EOD;
76 /**
77 * To be called from data reset code only,
78 * do not use in tests.
79 * @return void
81 public function reset() {
82 $this->usercounter = 0;
83 $this->categorycount = 0;
84 $this->coursecount = 0;
85 $this->scalecount = 0;
87 foreach($this->generators as $generator) {
88 $generator->reset();
92 /**
93 * Return generator for given plugin
94 * @param string $component
95 * @return mixed plugin data generator
97 public function get_plugin_generator($component) {
98 list($type, $plugin) = normalize_component($component);
100 if ($type !== 'mod' and $type !== 'block') {
101 throw new coding_exception("Plugin type $type does not support generators yet");
104 $dir = get_plugin_directory($type, $plugin);
106 if (!isset($this->generators[$type.'_'.$plugin])) {
107 $lib = "$dir/tests/generator/lib.php";
108 if (!include_once($lib)) {
109 throw new coding_exception("Plugin $component does not support data generator, missing tests/generator/lib");
111 $classname = $type.'_'.$plugin.'_generator';
112 $this->generators[$type.'_'.$plugin] = new $classname($this);
115 return $this->generators[$type.'_'.$plugin];
119 * Create a test user
120 * @param array|stdClass $record
121 * @param array $options
122 * @return stdClass user record
124 public function create_user($record=null, array $options=null) {
125 global $DB, $CFG;
127 $this->usercounter++;
128 $i = $this->usercounter;
130 $record = (array)$record;
132 if (!isset($record['auth'])) {
133 $record['auth'] = 'manual';
136 if (!isset($record['firstname']) and !isset($record['lastname'])) {
137 $country = rand(0, 5);
138 $firstname = rand(0, 4);
139 $lastname = rand(0, 4);
140 $female = rand(0, 1);
141 $record['firstname'] = $this->firstnames[($country*10) + $firstname + ($female*5)];
142 $record['lastname'] = $this->lastnames[($country*10) + $lastname + ($female*5)];
144 } else if (!isset($record['firstname'])) {
145 $record['firstname'] = 'Firstname'.$i;
147 } else if (!isset($record['lastname'])) {
148 $record['lastname'] = 'Lastname'.$i;
151 if (!isset($record['idnumber'])) {
152 $record['idnumber'] = '';
155 if (!isset($record['mnethostid'])) {
156 $record['mnethostid'] = $CFG->mnet_localhost_id;
159 if (!isset($record['username'])) {
160 $record['username'] = textlib::strtolower($record['firstname']).textlib::strtolower($record['lastname']);
161 while ($DB->record_exists('user', array('username'=>$record['username'], 'mnethostid'=>$record['mnethostid']))) {
162 $record['username'] = $record['username'].'_'.$i;
166 if (!isset($record['password'])) {
167 $record['password'] = 'lala';
170 if (!isset($record['email'])) {
171 $record['email'] = $record['username'].'@example.com';
174 if (!isset($record['confirmed'])) {
175 $record['confirmed'] = 1;
178 if (!isset($record['lang'])) {
179 $record['lang'] = 'en';
182 if (!isset($record['maildisplay'])) {
183 $record['maildisplay'] = 1;
186 if (!isset($record['deleted'])) {
187 $record['deleted'] = 0;
190 $record['timecreated'] = time();
191 $record['timemodified'] = $record['timecreated'];
192 $record['lastip'] = '0.0.0.0';
194 $record['password'] = hash_internal_user_password($record['password']);
196 if ($record['deleted']) {
197 $delname = $record['email'].'.'.time();
198 while ($DB->record_exists('user', array('username'=>$delname))) {
199 $delname++;
201 $record['idnumber'] = '';
202 $record['email'] = md5($record['username']);
203 $record['username'] = $delname;
204 $record['picture'] = 0;
207 $userid = $DB->insert_record('user', $record);
209 if (!$record['deleted']) {
210 context_user::instance($userid);
213 return $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
217 * Create a test course category
218 * @param array|stdClass $record
219 * @param array $options
220 * @return stdClass course category record
222 function create_category($record=null, array $options=null) {
223 global $DB, $CFG;
224 require_once("$CFG->dirroot/course/lib.php");
226 $this->categorycount++;
227 $i = $this->categorycount;
229 $record = (array)$record;
231 if (!isset($record['name'])) {
232 $record['name'] = 'Course category '.$i;
235 if (!isset($record['idnumber'])) {
236 $record['idnumber'] = '';
239 if (!isset($record['description'])) {
240 $record['description'] = "Test course category $i\n$this->loremipsum";
243 if (!isset($record['descriptionformat'])) {
244 $record['description'] = FORMAT_MOODLE;
247 if (!isset($record['parent'])) {
248 $record['descriptionformat'] = 0;
251 if (empty($record['parent'])) {
252 $parent = new stdClass();
253 $parent->path = '';
254 $parent->depth = 0;
255 } else {
256 $parent = $DB->get_record('course_categories', array('id'=>$record['parent']), '*', MUST_EXIST);
258 $record['depth'] = $parent->depth+1;
260 $record['sortorder'] = 0;
261 $record['timemodified'] = time();
262 $record['timecreated'] = $record['timemodified'];
264 $catid = $DB->insert_record('course_categories', $record);
265 $path = $parent->path . '/' . $catid;
266 $DB->set_field('course_categories', 'path', $path, array('id'=>$catid));
267 context_coursecat::instance($catid);
269 fix_course_sortorder();
271 return $DB->get_record('course_categories', array('id'=>$catid), '*', MUST_EXIST);
275 * Create a test course
276 * @param array|stdClass $record
277 * @param array $options with keys:
278 * 'createsections'=>bool precreate all sections
279 * @return stdClass course record
281 function create_course($record=null, array $options=null) {
282 global $DB, $CFG;
283 require_once("$CFG->dirroot/course/lib.php");
285 $this->coursecount++;
286 $i = $this->coursecount;
288 $record = (array)$record;
290 if (!isset($record['fullname'])) {
291 $record['fullname'] = 'Test course '.$i;
294 if (!isset($record['shortname'])) {
295 $record['shortname'] = 'tc_'.$i;
298 if (!isset($record['idnumber'])) {
299 $record['idnumber'] = '';
302 if (!isset($record['format'])) {
303 $record['format'] = 'topics';
306 if (!isset($record['newsitems'])) {
307 $record['newsitems'] = 0;
310 if (!isset($record['numsections'])) {
311 $record['numsections'] = 5;
314 if (!isset($record['description'])) {
315 $record['description'] = "Test course $i\n$this->loremipsum";
318 if (!isset($record['descriptionformat'])) {
319 $record['description'] = FORMAT_MOODLE;
322 if (!isset($record['category'])) {
323 $record['category'] = $DB->get_field_select('course_categories', "MIN(id)", "parent=0");
326 $course = create_course((object)$record);
327 context_course::instance($course->id);
329 if (!empty($options['createsections'])) {
330 for($i=1; $i<$record['numsections']; $i++) {
331 self::create_course_section(array('course'=>$course->id, 'section'=>$i));
335 return $course;
339 * Create course section if does not exist yet
340 * @param mixed $record
341 * @param array|null $options
342 * @return stdClass
343 * @throws coding_exception
345 public function create_course_section($record = null, array $options = null) {
346 global $DB;
348 $record = (array)$record;
350 if (empty($record['course'])) {
351 throw new coding_exception('course must be present in phpunit_util::create_course_section() $record');
354 if (!isset($record['section'])) {
355 throw new coding_exception('section must be present in phpunit_util::create_course_section() $record');
358 if (!isset($record['name'])) {
359 $record['name'] = '';
362 if (!isset($record['summary'])) {
363 $record['summary'] = '';
366 if (!isset($record['summaryformat'])) {
367 $record['summaryformat'] = FORMAT_MOODLE;
370 if ($section = $DB->get_record('course_sections', array('course'=>$record['course'], 'section'=>$record['section']))) {
371 return $section;
374 $section = new stdClass();
375 $section->course = $record['course'];
376 $section->section = $record['section'];
377 $section->name = $record['name'];
378 $section->summary = $record['summary'];
379 $section->summaryformat = $record['summaryformat'];
380 $id = $DB->insert_record('course_sections', $section);
382 return $DB->get_record('course_sections', array('id'=>$id));
386 * Create a test block
387 * @param string $blockname
388 * @param array|stdClass $record
389 * @param array $options
390 * @return stdClass block instance record
392 public function create_block($blockname, $record=null, array $options=null) {
393 $generator = $this->get_plugin_generator('block_'.$blockname);
394 return $generator->create_instance($record, $options);
398 * Create a test module
399 * @param string $modulename
400 * @param array|stdClass $record
401 * @param array $options
402 * @return stdClass activity record
404 public function create_module($modulename, $record=null, array $options=null) {
405 $generator = $this->get_plugin_generator('mod_'.$modulename);
406 return $generator->create_instance($record, $options);
410 * Create a test group for the specified course
412 * $record should be either an array or a stdClass containing infomation about the group to create.
413 * At the very least it needs to contain courseid.
414 * Default values are added for name, description, and descriptionformat if they are not present.
416 * This function calls {@see groups_create_group()} to create the group within the database.
418 * @param array|stdClass $record
419 * @return stdClass group record
421 public function create_group($record) {
422 global $DB, $CFG;
424 require_once($CFG->dirroot . '/group/lib.php');
426 $this->groupcount++;
427 $i = $this->groupcount;
429 $record = (array)$record;
431 if (empty($record['courseid'])) {
432 throw new coding_exception('courseid must be present in phpunit_util::create_group() $record');
435 if (!isset($record['name'])) {
436 $record['name'] = 'group-' . $i;
439 if (!isset($record['description'])) {
440 $record['description'] = "Test Group $i\n{$this->loremipsum}";
443 if (!isset($record['descriptionformat'])) {
444 $record['descriptionformat'] = FORMAT_MOODLE;
447 $id = groups_create_group((object)$record);
449 return $DB->get_record('groups', array('id'=>$id));
453 * Create a test grouping for the specified course
455 * $record should be either an array or a stdClass containing infomation about the grouping to create.
456 * At the very least it needs to contain courseid.
457 * Default values are added for name, description, and descriptionformat if they are not present.
459 * This function calls {@see groups_create_grouping()} to create the grouping within the database.
461 * @param array|stdClass $record
462 * @return stdClass grouping record
464 public function create_grouping($record) {
465 global $DB, $CFG;
467 require_once($CFG->dirroot . '/group/lib.php');
469 $this->groupingcount++;
470 $i = $this->groupingcount;
472 $record = (array)$record;
474 if (empty($record['courseid'])) {
475 throw new coding_exception('courseid must be present in phpunit_util::create_grouping() $record');
478 if (!isset($record['name'])) {
479 $record['name'] = 'grouping-' . $i;
482 if (!isset($record['description'])) {
483 $record['description'] = "Test Grouping $i\n{$this->loremipsum}";
486 if (!isset($record['descriptionformat'])) {
487 $record['descriptionformat'] = FORMAT_MOODLE;
490 $id = groups_create_grouping((object)$record);
492 return $DB->get_record('groupings', array('id'=>$id));
496 * Create a test scale
497 * @param array|stdClass $record
498 * @param array $options
499 * @return stdClass block instance record
501 public function create_scale($record=null, array $options=null) {
502 global $DB;
504 $this->scalecount++;
505 $i = $this->scalecount;
507 $record = (array)$record;
509 if (!isset($record['name'])) {
510 $record['name'] = 'Test scale '.$i;
513 if (!isset($record['scale'])) {
514 $record['scale'] = 'A,B,C,D,F';
517 if (!isset($record['courseid'])) {
518 $record['courseid'] = 0;
521 if (!isset($record['userid'])) {
522 $record['userid'] = 0;
525 if (!isset($record['description'])) {
526 $record['description'] = 'Test scale description '.$i;
529 if (!isset($record['descriptionformat'])) {
530 $record['descriptionformat'] = FORMAT_MOODLE;
533 $record['timemodified'] = time();
535 if (isset($record['id'])) {
536 $DB->import_record('scale', $record);
537 $DB->get_manager()->reset_sequence('scale');
538 $id = $record['id'];
539 } else {
540 $id = $DB->insert_record('scale', $record);
543 return $DB->get_record('scale', array('id'=>$id), '*', MUST_EXIST);
549 * Module generator base class.
551 * Extend in mod/xxxx/tests/generator/lib.php as class mod_xxxx_generator.
553 * @package core
554 * @category phpunit
555 * @copyright 2012 Petr Skoda {@link http://skodak.org}
556 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
558 abstract class phpunit_module_generator {
559 /** @var phpunit_data_generator@var */
560 protected $datagenerator;
562 /** @var number of created instances */
563 protected $instancecount = 0;
565 public function __construct(phpunit_data_generator $datagenerator) {
566 $this->datagenerator = $datagenerator;
570 * To be called from data reset code only,
571 * do not use in tests.
572 * @return void
574 public function reset() {
575 $this->instancecount = 0;
579 * Returns module name
580 * @return string name of module that this class describes
581 * @throws coding_exception if class invalid
583 public function get_modulename() {
584 $matches = null;
585 if (!preg_match('/^mod_([a-z0-9]+)_generator$/', get_class($this), $matches)) {
586 throw new coding_exception('Invalid module generator class name: '.get_class($this));
589 if (empty($matches[1])) {
590 throw new coding_exception('Invalid module generator class name: '.get_class($this));
592 return $matches[1];
596 * Create course module and link it to course
597 * @param int $courseid
598 * @param array $options: section, visible
599 * @return int $cm instance id
601 protected function precreate_course_module($courseid, array $options) {
602 global $DB, $CFG;
603 require_once("$CFG->dirroot/course/lib.php");
605 $modulename = $this->get_modulename();
607 $cm = new stdClass();
608 $cm->course = $courseid;
609 $cm->module = $DB->get_field('modules', 'id', array('name'=>$modulename));
610 $cm->instance = 0;
611 $cm->section = isset($options['section']) ? $options['section'] : 0;
612 $cm->idnumber = isset($options['idnumber']) ? $options['idnumber'] : 0;
613 $cm->added = time();
615 $columns = $DB->get_columns('course_modules');
616 foreach ($options as $key=>$value) {
617 if ($key === 'id' or !isset($columns[$key])) {
618 continue;
620 if (property_exists($cm, $key)) {
621 continue;
623 $cm->$key = $value;
626 $cm->id = $DB->insert_record('course_modules', $cm);
627 $cm->coursemodule = $cm->id;
629 add_mod_to_section($cm);
631 return $cm->id;
635 * Called after *_add_instance()
636 * @param int $id
637 * @param int $cmid
638 * @return stdClass module instance
640 protected function post_add_instance($id, $cmid) {
641 global $DB;
643 $DB->set_field('course_modules', 'instance', $id, array('id'=>$cmid));
645 $instance = $DB->get_record($this->get_modulename(), array('id'=>$id), '*', MUST_EXIST);
647 $cm = get_coursemodule_from_id($this->get_modulename(), $cmid, $instance->course, true, MUST_EXIST);
648 context_module::instance($cm->id);
650 $instance->cmid = $cm->id;
652 return $instance;
656 * Create a test module
657 * @param array|stdClass $record
658 * @param array $options
659 * @return stdClass activity record
661 abstract public function create_instance($record = null, array $options = null);
666 * Block generator base class.
668 * Extend in blocks/xxxx/tests/generator/lib.php as class block_xxxx_generator.
670 * @package core
671 * @category phpunit
672 * @copyright 2012 Petr Skoda {@link http://skodak.org}
673 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
675 abstract class phpunit_block_generator {
676 /** @var phpunit_data_generator@var */
677 protected $datagenerator;
679 /** @var number of created instances */
680 protected $instancecount = 0;
682 public function __construct(phpunit_data_generator $datagenerator) {
683 $this->datagenerator = $datagenerator;
687 * To be called from data reset code only,
688 * do not use in tests.
689 * @return void
691 public function reset() {
692 $this->instancecount = 0;
696 * Returns block name
697 * @return string name of block that this class describes
698 * @throws coding_exception if class invalid
700 public function get_blockname() {
701 $matches = null;
702 if (!preg_match('/^block_([a-z0-9_]+)_generator$/', get_class($this), $matches)) {
703 throw new coding_exception('Invalid block generator class name: '.get_class($this));
706 if (empty($matches[1])) {
707 throw new coding_exception('Invalid block generator class name: '.get_class($this));
709 return $matches[1];
713 * Fill in record defaults
714 * @param stdClass $record
715 * @return stdClass
717 protected function prepare_record(stdClass $record) {
718 $record->blockname = $this->get_blockname();
719 if (!isset($record->parentcontextid)) {
720 $record->parentcontextid = context_system::instance()->id;
722 if (!isset($record->showinsubcontexts)) {
723 $record->showinsubcontexts = 1;
725 if (!isset($record->pagetypepattern)) {
726 $record->pagetypepattern = '';
728 if (!isset($record->subpagepattern)) {
729 $record->subpagepattern = null;
731 if (!isset($record->defaultregion)) {
732 $record->defaultregion = '';
734 if (!isset($record->defaultweight)) {
735 $record->defaultweight = '';
737 if (!isset($record->configdata)) {
738 $record->configdata = null;
740 return $record;
744 * Create a test block
745 * @param array|stdClass $record
746 * @param array $options
747 * @return stdClass activity record
749 abstract public function create_instance($record = null, array $options = null);