MDL-47080 theme: call format_string on site shortname
[moodle.git] / lib / testing / generator / data_generator.php
CommitLineData
7e7cfe7a
PS
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 * Data generator.
19 *
20 * @package core
6b219869 21 * @category test
7e7cfe7a
PS
22 * @copyright 2012 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
c29e3e24 26defined('MOODLE_INTERNAL') || die();
7e7cfe7a
PS
27
28/**
6b219869 29 * Data generator class for unit tests and other tools that need to create fake test sites.
7e7cfe7a
PS
30 *
31 * @package core
6b219869 32 * @category test
7e7cfe7a
PS
33 * @copyright 2012 Petr Skoda {@link http://skodak.org}
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
35 */
5c3c2c81 36class testing_data_generator {
7e7cfe7a
PS
37 protected $usercounter = 0;
38 protected $categorycount = 0;
4729332b 39 protected $cohortcount = 0;
7e7cfe7a
PS
40 protected $coursecount = 0;
41 protected $scalecount = 0;
42 protected $groupcount = 0;
43 protected $groupingcount = 0;
702851c0 44 protected $rolecount = 0;
e0c86198 45 protected $tagcount = 0;
7e7cfe7a
PS
46
47 /** @var array list of plugin generators */
48 protected $generators = array();
49
50 /** @var array lis of common last names */
51 public $lastnames = array(
52 'Smith', 'Johnson', 'Williams', 'Brown', 'Jones', 'Miller', 'Davis', 'García', 'Rodríguez', 'Wilson',
53 'Müller', 'Schmidt', 'Schneider', 'Fischer', 'Meyer', 'Weber', 'Schulz', 'Wagner', 'Becker', 'Hoffmann',
54 'Novák', 'Svoboda', 'Novotný', 'Dvořák', 'Černý', 'Procházková', 'Kučerová', 'Veselá', 'Horáková', 'Němcová',
55 'Смирнов', 'Иванов', 'Кузнецов', 'Соколов', 'Попов', 'Лебедева', 'Козлова', 'Новикова', 'Морозова', 'Петрова',
56 '王', '李', '张', '刘', '陈', '楊', '黃', '趙', '吳', '周',
57 '佐藤', '鈴木', '高橋', '田中', '渡辺', '伊藤', '山本', '中村', '小林', '斎藤',
58 );
59
60 /** @var array lis of common first names */
61 public $firstnames = array(
62 'Jacob', 'Ethan', 'Michael', 'Jayden', 'William', 'Isabella', 'Sophia', 'Emma', 'Olivia', 'Ava',
63 'Lukas', 'Leon', 'Luca', 'Timm', 'Paul', 'Leonie', 'Leah', 'Lena', 'Hanna', 'Laura',
64 'Jakub', 'Jan', 'Tomáš', 'Lukáš', 'Matěj', 'Tereza', 'Eliška', 'Anna', 'Adéla', 'Karolína',
65 'Даниил', 'Максим', 'Артем', 'Иван', 'Александр', 'София', 'Анастасия', 'Дарья', 'Мария', 'Полина',
66 '伟', '伟', '芳', '伟', '秀英', '秀英', '娜', '秀英', '伟', '敏',
67 '翔', '大翔', '拓海', '翔太', '颯太', '陽菜', 'さくら', '美咲', '葵', '美羽',
68 );
69
70 public $loremipsum = <<<EOD
71Lorem 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.
72Temporibus 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.
73Vivamus 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.
74Integer 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.
75In 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.
76EOD;
77
78 /**
79 * To be called from data reset code only,
80 * do not use in tests.
81 * @return void
82 */
83 public function reset() {
84 $this->usercounter = 0;
85 $this->categorycount = 0;
86 $this->coursecount = 0;
87 $this->scalecount = 0;
88
5c3c2c81 89 foreach ($this->generators as $generator) {
7e7cfe7a
PS
90 $generator->reset();
91 }
92 }
93
94 /**
ba203de1
TH
95 * Return generator for given plugin or component.
96 * @param string $component the component name, e.g. 'mod_forum' or 'core_question'.
97 * @return component_generator_base or rather an instance of the appropriate subclass.
7e7cfe7a
PS
98 */
99 public function get_plugin_generator($component) {
56da374e 100 list($type, $plugin) = core_component::normalize_component($component);
ba203de1
TH
101 $cleancomponent = $type . '_' . $plugin;
102 if ($cleancomponent != $component) {
103 debugging("Please specify the component you want a generator for as " .
104 "{$cleancomponent}, not {$component}.", DEBUG_DEVELOPER);
105 $component = $cleancomponent;
106 }
7e7cfe7a 107
ba203de1
TH
108 if (isset($this->generators[$component])) {
109 return $this->generators[$component];
7e7cfe7a
PS
110 }
111
b0d1d941 112 $dir = core_component::get_component_directory($component);
ba203de1
TH
113 $lib = $dir . '/tests/generator/lib.php';
114 if (!$dir || !is_readable($lib)) {
115 throw new coding_exception("Component {$component} does not support " .
116 "generators yet. Missing tests/generator/lib.php.");
117 }
7e7cfe7a 118
ba203de1
TH
119 include_once($lib);
120 $classname = $component . '_generator';
121
122 if (!class_exists($classname)) {
123 throw new coding_exception("Component {$component} does not support " .
124 "data generators yet. Class {$classname} not found.");
7e7cfe7a
PS
125 }
126
ba203de1
TH
127 $this->generators[$component] = new $classname($this);
128 return $this->generators[$component];
7e7cfe7a
PS
129 }
130
131 /**
132 * Create a test user
133 * @param array|stdClass $record
134 * @param array $options
135 * @return stdClass user record
136 */
137 public function create_user($record=null, array $options=null) {
138 global $DB, $CFG;
139
140 $this->usercounter++;
141 $i = $this->usercounter;
142
143 $record = (array)$record;
144
145 if (!isset($record['auth'])) {
146 $record['auth'] = 'manual';
147 }
148
149 if (!isset($record['firstname']) and !isset($record['lastname'])) {
150 $country = rand(0, 5);
151 $firstname = rand(0, 4);
152 $lastname = rand(0, 4);
153 $female = rand(0, 1);
154 $record['firstname'] = $this->firstnames[($country*10) + $firstname + ($female*5)];
155 $record['lastname'] = $this->lastnames[($country*10) + $lastname + ($female*5)];
156
157 } else if (!isset($record['firstname'])) {
158 $record['firstname'] = 'Firstname'.$i;
159
160 } else if (!isset($record['lastname'])) {
161 $record['lastname'] = 'Lastname'.$i;
162 }
163
a327f25e
AG
164 if (!isset($record['firstnamephonetic'])) {
165 $firstnamephonetic = rand(0, 59);
166 $record['firstnamephonetic'] = $this->firstnames[$firstnamephonetic];
167 }
168
169 if (!isset($record['lasttnamephonetic'])) {
170 $lastnamephonetic = rand(0, 59);
171 $record['lastnamephonetic'] = $this->lastnames[$lastnamephonetic];
172 }
173
174 if (!isset($record['middlename'])) {
175 $middlename = rand(0, 59);
176 $record['middlename'] = $this->firstnames[$middlename];
177 }
178
179 if (!isset($record['alternatename'])) {
180 $alternatename = rand(0, 59);
181 $record['alternatename'] = $this->firstnames[$alternatename];
182 }
183
7e7cfe7a
PS
184 if (!isset($record['idnumber'])) {
185 $record['idnumber'] = '';
186 }
187
188 if (!isset($record['mnethostid'])) {
189 $record['mnethostid'] = $CFG->mnet_localhost_id;
190 }
191
192 if (!isset($record['username'])) {
fe67134e
PS
193 $record['username'] = 'username'.$i;
194 $j = 2;
7e7cfe7a 195 while ($DB->record_exists('user', array('username'=>$record['username'], 'mnethostid'=>$record['mnethostid']))) {
fe67134e
PS
196 $record['username'] = 'username'.$i.'_'.$j;
197 $j++;
7e7cfe7a
PS
198 }
199 }
200
dbf60a04
PS
201 if (isset($record['password'])) {
202 $record['password'] = hash_internal_user_password($record['password']);
203 } else {
204 // The auth plugin may not fully support this,
205 // but it is still better/faster than hashing random stuff.
206 $record['password'] = AUTH_PASSWORD_NOT_CACHED;
7e7cfe7a
PS
207 }
208
209 if (!isset($record['email'])) {
210 $record['email'] = $record['username'].'@example.com';
211 }
212
213 if (!isset($record['confirmed'])) {
214 $record['confirmed'] = 1;
215 }
216
217 if (!isset($record['lang'])) {
218 $record['lang'] = 'en';
219 }
220
221 if (!isset($record['maildisplay'])) {
9f7379e9
MG
222 $record['maildisplay'] = $CFG->defaultpreference_maildisplay;
223 }
224
225 if (!isset($record['mailformat'])) {
226 $record['mailformat'] = $CFG->defaultpreference_mailformat;
227 }
228
229 if (!isset($record['maildigest'])) {
230 $record['maildigest'] = $CFG->defaultpreference_maildigest;
231 }
232
233 if (!isset($record['autosubscribe'])) {
234 $record['autosubscribe'] = $CFG->defaultpreference_autosubscribe;
235 }
236
237 if (!isset($record['trackforums'])) {
238 $record['trackforums'] = $CFG->defaultpreference_trackforums;
7e7cfe7a
PS
239 }
240
241 if (!isset($record['deleted'])) {
242 $record['deleted'] = 0;
243 }
244
2d35b7d3
GPL
245 if (!isset($record['timecreated'])) {
246 $record['timecreated'] = time();
247 }
248
7e7cfe7a
PS
249 $record['timemodified'] = $record['timecreated'];
250 $record['lastip'] = '0.0.0.0';
251
7e7cfe7a
PS
252 if ($record['deleted']) {
253 $delname = $record['email'].'.'.time();
254 while ($DB->record_exists('user', array('username'=>$delname))) {
255 $delname++;
256 }
257 $record['idnumber'] = '';
258 $record['email'] = md5($record['username']);
259 $record['username'] = $delname;
260 $record['picture'] = 0;
261 }
262
263 $userid = $DB->insert_record('user', $record);
264
265 if (!$record['deleted']) {
266 context_user::instance($userid);
267 }
268
269 return $DB->get_record('user', array('id'=>$userid), '*', MUST_EXIST);
270 }
271
272 /**
273 * Create a test course category
274 * @param array|stdClass $record
275 * @param array $options
b28bb7e8 276 * @return coursecat course category record
7e7cfe7a 277 */
4729332b 278 public function create_category($record=null, array $options=null) {
7e7cfe7a 279 global $DB, $CFG;
b28bb7e8 280 require_once("$CFG->libdir/coursecatlib.php");
7e7cfe7a
PS
281
282 $this->categorycount++;
283 $i = $this->categorycount;
284
285 $record = (array)$record;
286
287 if (!isset($record['name'])) {
288 $record['name'] = 'Course category '.$i;
289 }
290
7e7cfe7a
PS
291 if (!isset($record['description'])) {
292 $record['description'] = "Test course category $i\n$this->loremipsum";
293 }
294
b28bb7e8
MG
295 if (!isset($record['idnumber'])) {
296 $record['idnumber'] = '';
7e7cfe7a 297 }
7e7cfe7a 298
b28bb7e8 299 return coursecat::create($record);
7e7cfe7a
PS
300 }
301
4729332b
PS
302 /**
303 * Create test cohort.
304 * @param array|stdClass $record
305 * @param array $options
306 * @return stdClass cohort record
307 */
308 public function create_cohort($record=null, array $options=null) {
309 global $DB, $CFG;
310 require_once("$CFG->dirroot/cohort/lib.php");
311
312 $this->cohortcount++;
313 $i = $this->cohortcount;
314
315 $record = (array)$record;
316
317 if (!isset($record['contextid'])) {
318 $record['contextid'] = context_system::instance()->id;
319 }
320
321 if (!isset($record['name'])) {
322 $record['name'] = 'Cohort '.$i;
323 }
324
325 if (!isset($record['idnumber'])) {
326 $record['idnumber'] = '';
327 }
328
329 if (!isset($record['description'])) {
330 $record['description'] = "Test cohort $i\n$this->loremipsum";
331 }
332
333 if (!isset($record['descriptionformat'])) {
334 $record['descriptionformat'] = FORMAT_MOODLE;
335 }
336
337 if (!isset($record['component'])) {
338 $record['component'] = '';
339 }
340
341 $id = cohort_add_cohort((object)$record);
342
343 return $DB->get_record('cohort', array('id'=>$id), '*', MUST_EXIST);
344 }
345
7e7cfe7a
PS
346 /**
347 * Create a test course
348 * @param array|stdClass $record
349 * @param array $options with keys:
350 * 'createsections'=>bool precreate all sections
351 * @return stdClass course record
352 */
4729332b 353 public function create_course($record=null, array $options=null) {
7e7cfe7a
PS
354 global $DB, $CFG;
355 require_once("$CFG->dirroot/course/lib.php");
356
357 $this->coursecount++;
358 $i = $this->coursecount;
359
360 $record = (array)$record;
361
362 if (!isset($record['fullname'])) {
363 $record['fullname'] = 'Test course '.$i;
364 }
365
366 if (!isset($record['shortname'])) {
367 $record['shortname'] = 'tc_'.$i;
368 }
369
370 if (!isset($record['idnumber'])) {
371 $record['idnumber'] = '';
372 }
373
374 if (!isset($record['format'])) {
375 $record['format'] = 'topics';
376 }
377
378 if (!isset($record['newsitems'])) {
379 $record['newsitems'] = 0;
380 }
381
382 if (!isset($record['numsections'])) {
383 $record['numsections'] = 5;
384 }
385
4a38e659
PS
386 if (!isset($record['summary'])) {
387 $record['summary'] = "Test course $i\n$this->loremipsum";
7e7cfe7a
PS
388 }
389
4a38e659
PS
390 if (!isset($record['summaryformat'])) {
391 $record['summaryformat'] = FORMAT_MOODLE;
7e7cfe7a
PS
392 }
393
394 if (!isset($record['category'])) {
395 $record['category'] = $DB->get_field_select('course_categories', "MIN(id)", "parent=0");
396 }
397
398 $course = create_course((object)$record);
399 context_course::instance($course->id);
7e7cfe7a 400 if (!empty($options['createsections'])) {
384c3510
MG
401 if (isset($course->numsections)) {
402 course_create_sections_if_missing($course, range(0, $course->numsections));
403 } else {
404 course_create_sections_if_missing($course, 0);
7e7cfe7a
PS
405 }
406 }
407
408 return $course;
409 }
410
411 /**
412 * Create course section if does not exist yet
384c3510 413 * @param array|stdClass $record must contain 'course' and 'section' attributes
7e7cfe7a
PS
414 * @param array|null $options
415 * @return stdClass
416 * @throws coding_exception
417 */
418 public function create_course_section($record = null, array $options = null) {
419 global $DB;
420
421 $record = (array)$record;
422
423 if (empty($record['course'])) {
5c3c2c81 424 throw new coding_exception('course must be present in testing_data_generator::create_course_section() $record');
7e7cfe7a
PS
425 }
426
427 if (!isset($record['section'])) {
5c3c2c81 428 throw new coding_exception('section must be present in testing_data_generator::create_course_section() $record');
7e7cfe7a
PS
429 }
430
b46be6ad
MG
431 course_create_sections_if_missing($record['course'], $record['section']);
432 return get_fast_modinfo($record['course'])->get_section_info($record['section']);
7e7cfe7a
PS
433 }
434
435 /**
436 * Create a test block
437 * @param string $blockname
438 * @param array|stdClass $record
439 * @param array $options
440 * @return stdClass block instance record
441 */
442 public function create_block($blockname, $record=null, array $options=null) {
443 $generator = $this->get_plugin_generator('block_'.$blockname);
444 return $generator->create_instance($record, $options);
445 }
446
447 /**
448 * Create a test module
449 * @param string $modulename
450 * @param array|stdClass $record
451 * @param array $options
452 * @return stdClass activity record
453 */
454 public function create_module($modulename, $record=null, array $options=null) {
455 $generator = $this->get_plugin_generator('mod_'.$modulename);
456 return $generator->create_instance($record, $options);
457 }
458
459 /**
460 * Create a test group for the specified course
461 *
462 * $record should be either an array or a stdClass containing infomation about the group to create.
463 * At the very least it needs to contain courseid.
464 * Default values are added for name, description, and descriptionformat if they are not present.
465 *
6b219869
DM
466 * This function calls groups_create_group() to create the group within the database.
467 * @see groups_create_group
7e7cfe7a
PS
468 * @param array|stdClass $record
469 * @return stdClass group record
470 */
471 public function create_group($record) {
472 global $DB, $CFG;
473
474 require_once($CFG->dirroot . '/group/lib.php');
475
476 $this->groupcount++;
477 $i = $this->groupcount;
478
479 $record = (array)$record;
480
481 if (empty($record['courseid'])) {
5c3c2c81 482 throw new coding_exception('courseid must be present in testing_data_generator::create_group() $record');
7e7cfe7a
PS
483 }
484
485 if (!isset($record['name'])) {
486 $record['name'] = 'group-' . $i;
487 }
488
489 if (!isset($record['description'])) {
490 $record['description'] = "Test Group $i\n{$this->loremipsum}";
491 }
492
493 if (!isset($record['descriptionformat'])) {
494 $record['descriptionformat'] = FORMAT_MOODLE;
495 }
496
497 $id = groups_create_group((object)$record);
498
499 return $DB->get_record('groups', array('id'=>$id));
500 }
501
87bb583c
DM
502 /**
503 * Create a test group member
504 * @param array|stdClass $record
505 * @throws coding_exception
506 * @return boolean
507 */
508 public function create_group_member($record) {
509 global $DB, $CFG;
510
511 require_once($CFG->dirroot . '/group/lib.php');
512
513 $record = (array)$record;
514
515 if (empty($record['userid'])) {
516 throw new coding_exception('user must be present in testing_util::create_group_member() $record');
517 }
518
519 if (!isset($record['groupid'])) {
520 throw new coding_exception('group must be present in testing_util::create_group_member() $record');
521 }
522
523 if (!isset($record['component'])) {
524 $record['component'] = null;
525 }
526 if (!isset($record['itemid'])) {
527 $record['itemid'] = 0;
528 }
529
530 return groups_add_member($record['groupid'], $record['userid'], $record['component'], $record['itemid']);
531 }
532
7e7cfe7a
PS
533 /**
534 * Create a test grouping for the specified course
535 *
536 * $record should be either an array or a stdClass containing infomation about the grouping to create.
537 * At the very least it needs to contain courseid.
538 * Default values are added for name, description, and descriptionformat if they are not present.
539 *
6b219869
DM
540 * This function calls groups_create_grouping() to create the grouping within the database.
541 * @see groups_create_grouping
7e7cfe7a
PS
542 * @param array|stdClass $record
543 * @return stdClass grouping record
544 */
545 public function create_grouping($record) {
546 global $DB, $CFG;
547
548 require_once($CFG->dirroot . '/group/lib.php');
549
550 $this->groupingcount++;
551 $i = $this->groupingcount;
552
553 $record = (array)$record;
554
555 if (empty($record['courseid'])) {
5c3c2c81 556 throw new coding_exception('courseid must be present in testing_data_generator::create_grouping() $record');
7e7cfe7a
PS
557 }
558
559 if (!isset($record['name'])) {
560 $record['name'] = 'grouping-' . $i;
561 }
562
563 if (!isset($record['description'])) {
564 $record['description'] = "Test Grouping $i\n{$this->loremipsum}";
565 }
566
567 if (!isset($record['descriptionformat'])) {
568 $record['descriptionformat'] = FORMAT_MOODLE;
569 }
570
571 $id = groups_create_grouping((object)$record);
572
573 return $DB->get_record('groupings', array('id'=>$id));
574 }
575
87bb583c
DM
576 /**
577 * Create a test grouping group
578 * @param array|stdClass $record
579 * @throws coding_exception
580 * @return boolean
581 */
582 public function create_grouping_group($record) {
583 global $DB, $CFG;
584
585 require_once($CFG->dirroot . '/group/lib.php');
586
587 $record = (array)$record;
588
589 if (empty($record['groupingid'])) {
590 throw new coding_exception('grouping must be present in testing::create_grouping_group() $record');
591 }
592
593 if (!isset($record['groupid'])) {
594 throw new coding_exception('group must be present in testing_util::create_grouping_group() $record');
595 }
596
597 return groups_assign_grouping($record['groupingid'], $record['groupid']);
598 }
599
0852bbae
FM
600 /**
601 * Create an instance of a repository.
602 *
603 * @param string type of repository to create an instance for.
604 * @param array|stdClass $record data to use to up set the instance.
605 * @param array $options options
606 * @return stdClass repository instance record
5bcfd504 607 * @since Moodle 2.5.1
0852bbae
FM
608 */
609 public function create_repository($type, $record=null, array $options = null) {
0852bbae
FM
610 $generator = $this->get_plugin_generator('repository_'.$type);
611 return $generator->create_instance($record, $options);
612 }
613
614 /**
615 * Create an instance of a repository.
616 *
617 * @param string type of repository to create an instance for.
618 * @param array|stdClass $record data to use to up set the instance.
619 * @param array $options options
620 * @return repository_type object
5bcfd504 621 * @since Moodle 2.5.1
0852bbae
FM
622 */
623 public function create_repository_type($type, $record=null, array $options = null) {
0852bbae
FM
624 $generator = $this->get_plugin_generator('repository_'.$type);
625 return $generator->create_type($record, $options);
626 }
627
628
7e7cfe7a
PS
629 /**
630 * Create a test scale
631 * @param array|stdClass $record
632 * @param array $options
633 * @return stdClass block instance record
634 */
635 public function create_scale($record=null, array $options=null) {
636 global $DB;
637
638 $this->scalecount++;
639 $i = $this->scalecount;
640
641 $record = (array)$record;
642
643 if (!isset($record['name'])) {
644 $record['name'] = 'Test scale '.$i;
645 }
646
647 if (!isset($record['scale'])) {
648 $record['scale'] = 'A,B,C,D,F';
649 }
650
651 if (!isset($record['courseid'])) {
652 $record['courseid'] = 0;
653 }
654
655 if (!isset($record['userid'])) {
656 $record['userid'] = 0;
657 }
658
659 if (!isset($record['description'])) {
660 $record['description'] = 'Test scale description '.$i;
661 }
662
663 if (!isset($record['descriptionformat'])) {
664 $record['descriptionformat'] = FORMAT_MOODLE;
665 }
666
667 $record['timemodified'] = time();
668
669 if (isset($record['id'])) {
670 $DB->import_record('scale', $record);
671 $DB->get_manager()->reset_sequence('scale');
672 $id = $record['id'];
673 } else {
674 $id = $DB->insert_record('scale', $record);
675 }
676
677 return $DB->get_record('scale', array('id'=>$id), '*', MUST_EXIST);
678 }
4f5789ea 679
702851c0
DM
680 /**
681 * Creates a new role in the system.
682 *
683 * You can fill $record with the role 'name',
684 * 'shortname', 'description' and 'archetype'.
685 *
686 * If an archetype is specified it's capabilities,
687 * context where the role can be assigned and
688 * all other properties are copied from the archetype;
689 * if no archetype is specified it will create an
690 * empty role.
691 *
692 * @param array|stdClass $record
693 * @return int The new role id
694 */
695 public function create_role($record=null) {
696 global $DB;
697
698 $this->rolecount++;
699 $i = $this->rolecount;
700
701 $record = (array)$record;
702
703 if (empty($record['shortname'])) {
704 $record['shortname'] = 'role-' . $i;
705 }
706
707 if (empty($record['name'])) {
708 $record['name'] = 'Test role ' . $i;
709 }
710
711 if (empty($record['description'])) {
712 $record['description'] = 'Test role ' . $i . ' description';
713 }
714
715 if (empty($record['archetype'])) {
716 $record['archetype'] = '';
717 } else {
718 $archetypes = get_role_archetypes();
719 if (empty($archetypes[$record['archetype']])) {
720 throw new coding_exception('\'role\' requires the field \'archetype\' to specify a ' .
721 'valid archetype shortname (editingteacher, student...)');
722 }
723 }
724
725 // Creates the role.
726 if (!$newroleid = create_role($record['name'], $record['shortname'], $record['description'], $record['archetype'])) {
727 throw new coding_exception('There was an error creating \'' . $record['shortname'] . '\' role');
728 }
729
730 // If no archetype was specified we allow it to be added to all contexts,
731 // otherwise we allow it in the archetype contexts.
732 if (!$record['archetype']) {
733 $contextlevels = array_keys(context_helper::get_all_levels());
734 } else {
735 // Copying from the archetype default rol.
736 $archetyperoleid = $DB->get_field(
737 'role',
738 'id',
739 array('shortname' => $record['archetype'], 'archetype' => $record['archetype'])
740 );
741 $contextlevels = get_role_contextlevels($archetyperoleid);
742 }
743 set_role_contextlevels($newroleid, $contextlevels);
744
745 if ($record['archetype']) {
746
747 // We copy all the roles the archetype can assign, override and switch to.
748 if ($record['archetype']) {
749 $types = array('assign', 'override', 'switch');
750 foreach ($types as $type) {
751 $rolestocopy = get_default_role_archetype_allows($type, $record['archetype']);
752 foreach ($rolestocopy as $tocopy) {
753 $functionname = 'allow_' . $type;
754 $functionname($newroleid, $tocopy);
755 }
756 }
757 }
758
759 // Copying the archetype capabilities.
760 $sourcerole = $DB->get_record('role', array('id' => $archetyperoleid));
761 role_cap_duplicate($sourcerole, $newroleid);
762 }
763
764 return $newroleid;
765 }
766
e0c86198
MN
767 /**
768 * Create a tag.
769 *
770 * @param array|stdClass $record
771 * @return stdClass the tag record
772 */
773 public function create_tag($record = null) {
774 global $DB, $USER;
775
776 $this->tagcount++;
777 $i = $this->tagcount;
778
779 $record = (array) $record;
780
781 if (!isset($record['userid'])) {
782 $record['userid'] = $USER->id;
783 }
784
785 if (!isset($record['name'])) {
786 $record['name'] = 'Tag name ' . $i;
787 }
788
789 if (!isset($record['rawname'])) {
790 $record['rawname'] = 'Raw tag name ' . $i;
791 }
792
793 if (!isset($record['tagtype'])) {
794 $record['tagtype'] = 'default';
795 }
796
797 if (!isset($record['description'])) {
798 $record['description'] = 'Tag description';
799 }
800
801 if (!isset($record['descriptionformat'])) {
802 $record['descriptionformat'] = FORMAT_MOODLE;
803 }
804
805 if (!isset($record['flag'])) {
806 $record['flag'] = 0;
807 }
808
809 if (!isset($record['timemodified'])) {
810 $record['timemodified'] = time();
811 }
812
813 $id = $DB->insert_record('tag', $record);
814
815 return $DB->get_record('tag', array('id' => $id), '*', MUST_EXIST);
816 }
817
ba203de1
TH
818 /**
819 * Helper method which combines $defaults with the values specified in $record.
820 * If $record is an object, it is converted to an array.
821 * Then, for each key that is in $defaults, but not in $record, the value
822 * from $defaults is copied.
823 * @param array $defaults the default value for each field with
824 * @param array|stdClass $record
825 * @return array updated $record.
826 */
827 public function combine_defaults_and_record(array $defaults, $record) {
828 $record = (array) $record;
829
830 foreach ($defaults as $key => $defaults) {
831 if (!array_key_exists($key, $record)) {
832 $record[$key] = $defaults;
833 }
834 }
835 return $record;
836 }
837
4f5789ea
PS
838 /**
839 * Simplified enrolment of user to course using default options.
840 *
841 * It is strongly recommended to use only this method for 'manual' and 'self' plugins only!!!
842 *
843 * @param int $userid
844 * @param int $courseid
845 * @param int $roleid optional role id, use only with manual plugin
846 * @param string $enrol name of enrol plugin,
847 * there must be exactly one instance in course,
848 * it must support enrol_user() method.
1ecb8044
RT
849 * @param int $timestart (optional) 0 means unknown
850 * @param int $timeend (optional) 0 means forever
851 * @param int $status (optional) default to ENROL_USER_ACTIVE for new enrolments
4f5789ea
PS
852 * @return bool success
853 */
e6cc5347 854 public function enrol_user($userid, $courseid, $roleid = null, $enrol = 'manual', $timestart = 0, $timeend = 0, $status = null) {
4f5789ea
PS
855 global $DB;
856
857 if (!$plugin = enrol_get_plugin($enrol)) {
858 return false;
859 }
860
861 $instances = $DB->get_records('enrol', array('courseid'=>$courseid, 'enrol'=>$enrol));
862 if (count($instances) != 1) {
863 return false;
864 }
865 $instance = reset($instances);
866
867 if (is_null($roleid) and $instance->roleid) {
868 $roleid = $instance->roleid;
869 }
870
e6cc5347 871 $plugin->enrol_user($instance, $userid, $roleid, $timestart, $timeend, $status);
4f5789ea
PS
872 return true;
873 }
72ddc05f
DM
874
875 /**
876 * Assigns the specified role to a user in the context.
877 *
878 * @param int $roleid
879 * @param int $userid
880 * @param int $contextid Defaults to the system context
881 * @return int new/existing id of the assignment
882 */
883 public function role_assign($roleid, $userid, $contextid = false) {
884
885 // Default to the system context.
886 if (!$contextid) {
887 $context = context_system::instance();
888 $contextid = $context->id;
889 }
890
891 if (empty($roleid)) {
892 throw new coding_exception('roleid must be present in testing_data_generator::role_assign() arguments');
893 }
894
895 if (empty($userid)) {
896 throw new coding_exception('userid must be present in testing_data_generator::role_assign() arguments');
897 }
898
899 return role_assign($roleid, $userid, $contextid);
900 }
901
7e7cfe7a 902}