MDL-14679 fixed multiple old style insert_record calls, we throw exceptions now from DML
[moodle.git] / admin / generator.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * Random course generator. By Nicolas Connault and friends.
20  *
21  * To use go to .../admin/generator.php?web_interface=1 in your browser.
22  *
23  * @package generator
24  * @copyright 2009 Nicolas Connault
25  * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26  */
28 require_once(dirname(__FILE__).'/../config.php');
29 require_once($CFG->libdir . '/formslib.php');
30 require_once($CFG->dirroot .'/course/lib.php');
31 require_once($CFG->libdir .'/filelib.php');
33 define('GENERATOR_RANDOM', 0);
34 define('GENERATOR_SEQUENCE', 1);
36 /**
37  * Controller class for data generation
38  */
39 class generator {
40     public $modules_to_ignore = array('hotpot', 'lams', 'journal', 'scorm', 'exercise', 'dialogue');
41     public $modules_list = array('forum' => 'forum',
42                                  'assignment' => 'assignment',
43                                  'chat' => 'chat',
44                                  'data' => 'data',
45                                  'glossary' => 'glossary',
46                                  'quiz' => 'quiz',
47                                  'comments' => 'comments',
48                                  'feedback' => 'feedback',
49                                  'label' => 'label',
50                                  'lesson' => 'lesson',
51                                  'chat' => 'chat',
52                                  'choice' => 'choice',
53                                  'resource' => 'resource',
54                                  'survey' => 'survey',
55                                  'wiki' => 'wiki',
56                                  'workshop' => 'workshop');
58     public $resource_types = array('text', 'file', 'html', 'repository', 'directory', 'ims');
59     public $glossary_formats = array('continuous', 'encyclopedia', 'entrylist', 'faq', 'fullwithauthor', 'fullwithoutauthor', 'dictionary');
60     public $assignment_types = array('upload', 'uploadsingle', 'online', 'offline');
61     public $forum_types = array('general'); // others include 'single', 'eachuser', 'qanda'
63     public $resource_type_counter = 0;
64     public $assignment_type_counter = 0;
65     public $forum_type_counter = 0;
67     public $settings = array();
68     public $eolchar = '<br />';
69     public $do_generation = false;
70     public $starttime;
71     public $original_db;
73     public function __construct($settings = array(), $generate=false) {
74         global $CFG;
76         $this->starttime = time()+microtime();
78         $arguments = array(
79              array('short'=>'u', 'long'=>'username',
80                    'help' => 'Your moodle username', 'type'=>'STRING', 'default' => ''),
81              array('short'=>'pw', 'long'=>'password',
82                    'help' => 'Your moodle password', 'type'=>'STRING', 'default' => ''),
83              array('short'=>'P', 'long' => 'database_prefix',
84                    'help' => 'Database prefix to use: tables must already exist or the script will abort!',
85                    'type'=>'STRING', 'default' => $CFG->prefix),
86              array('short'=>'c', 'long' => 'pre_cleanup', 'help' => 'Delete previously generated data'),
87              array('short'=>'C', 'long' => 'post_cleanup',
88                    'help' => 'Deletes all generated data at the end of the script (for benchmarking of generation only)'),
89              array('short'=>'t', 'long' => 'time_limit',
90                    'help' => 'Optional time limit after which to abort the generation, 0 = no limit. Default=0',
91                    'type'=>'SECONDS', 'default' => 0),
92              array('short'=>'v', 'long' => 'verbose', 'help' => 'Display extra information about the data generation'),
93              array('short'=>'q', 'long' => 'quiet', 'help' => 'Inhibits all outputs'),
94              array('short'=>'i', 'long' => 'ignore_errors', 'help' => 'Continue script execution when errors occur'),
95              array('short'=>'N', 'long' => 'no_data', 'help' => 'Generate nothing (used for cleaning up only)'),
96              array('short'=>'T', 'long' => 'tiny',
97                    'help' => 'Generates a tiny data set (1 of each course, module, user and section)',
98                    'default' => 0),
99              array('short'=>'nc', 'long' => 'number_of_courses',
100                    'help' => 'The number of courses to generate. Default=1',
101                    'type'=>'NUMBER', 'default' => 1),
102              array('short'=>'ns', 'long' => 'number_of_students',
103                    'help' => 'The number of students to generate. Default=250',
104                    'type'=>'NUMBER', 'default' => 250),
105              array('short'=>'sc', 'long' => 'students_per_course',
106                    'help' => 'The number of students to enrol in each course. Default=20',
107                    'type'=>'NUMBER', 'default' => 20),
108              array('short'=>'nsec', 'long' => 'number_of_sections',
109                    'help' => 'The number of sections to generate in each course. Default=10',
110                    'type'=>'NUMBER', 'default' => 10),
111              array('short'=>'nmod', 'long' => 'number_of_modules',
112                    'help' => 'The number of modules to generate in each section. Default=10',
113                    'type'=>'NUMBER', 'default' => 10),
114              array('short'=>'mods', 'long' => 'modules_list',
115                    'help' => 'The list of modules you want to generate', 'default' => $this->modules_list,
116                    'type' => 'mod1,mod2...'),
117              array('short'=>'rt', 'long' => 'resource_type',
118                    'help' => 'The specific type of resource you want to generate. Defaults to all',
119                    'default' => $this->resource_types,
120                    'type' => 'SELECT'),
121              array('short'=>'at', 'long' => 'assignment_type',
122                    'help' => 'The specific type of assignment you want to generate. Defaults to all',
123                    'default' => $this->assignment_types,
124                    'type' => 'SELECT'),
125              array('short'=>'ft', 'long' => 'forum_type',
126                    'help' => 'The specific type of forum you want to generate. Defaults to all',
127                    'default' => $this->forum_types,
128                    'type' => 'SELECT'),
129              array('short'=>'gf', 'long' => 'glossary_format',
130                    'help' => 'The specific format of glossary you want to generate. Defaults to all',
131                    'default' => $this->glossary_formats,
132                    'type' => 'SELECT'),
133              array('short'=>'ag', 'long' => 'assignment_grades',
134                    'help' => 'Generate random grades for each student/assignment tuple', 'default' => true),
135              array('short'=>'qg', 'long' => 'quiz_grades',
136                    'help' => 'Generate random grades for each student/quiz tuple', 'default' => true),
137              array('short'=>'eg', 'long' => 'entries_per_glossary',
138                    'help' => 'The number of definitions to generate per glossary. Default=0',
139                    'type'=>'NUMBER', 'default' => 1),
140              array('short'=>'nq', 'long' => 'questions_per_course',
141                    'help' => 'The number of questions to generate per course. Default=20',
142                    'type'=>'NUMBER', 'default' => 20),
143              array('short'=>'qq', 'long' => 'questions_per_quiz',
144                    'help' => 'The number of questions to assign to each quiz. Default=5',
145                    'type'=>'NUMBER', 'default' => 5),
146              array('short'=>'df', 'long' => 'discussions_per_forum',
147                    'help' => 'The number of discussions to generate for each forum. Default=5',
148                    'type'=>'NUMBER', 'default' => 5),
149              array('short'=>'pd', 'long' => 'posts_per_discussion',
150                    'help' => 'The number of posts to generate for each forum discussion. Default=15',
151                    'type'=>'NUMBER', 'default' => 15),
152              array('short'=>'fd', 'long' => 'fields_per_database',
153                    'help' => 'The number of fields to generate for each database. Default=4',
154                    'type'=>'NUMBER', 'default' => 4),
155              array('short'=>'drs', 'long' => 'database_records_per_student',
156                    'help' => 'The number of records to generate for each student/database tuple. Default=1',
157                    'type'=>'NUMBER', 'default' => 1),
158              array('short'=>'mc', 'long' => 'messages_per_chat',
159                    'help' => 'The number of messages to generate for each chat module. Default=10',
160                    'type'=>'NUMBER', 'default' => 10),
161             );
163         foreach ($arguments as $args_array) {
164             $this->settings[$args_array['long']] = new generator_argument($args_array);
165         }
167         foreach ($settings as $setting => $value) {
168             $this->settings[$setting]->value = $value;
169         }
171         if ($generate) {
172             $this->generate_data();
173         }
174     }
176     public function connect() {
177         global $DB, $CFG;
178         $this->original_db = $DB;
180         $class = get_class($DB);
181         $DB = new $class();
182         $DB->connect($CFG->dbhost, $CFG->dbuser, $CFG->dbpass, $CFG->dbname, $this->get('database_prefix'));
183     }
185     public function dispose() {
186         global $DB;
187         $DB->dispose();
188         $DB = $this->original_db;
189     }
191     public function generate_users() {
192         global $DB, $CFG;
194         /**
195          * USER GENERATION
196          */
197         $this->verbose("Generating ".$this->get('number_of_students')." students...");
198         $lastnames = array('SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON',
199             'MOORE','TAYLOR','ANDERSON','THOMAS','JACKSON','WHITE','HARRIS','MARTIN','THOMPSON',
200             'GARCIA','MARTINEZ','ROBINSON','CLARK','RODRIGUEZ','LEWIS','LEE','WALKER','HALL',
201             'ALLEN','YOUNG','HERNANDEZ','KING','WRIGHT','LOPEZ','HILL','SCOTT','GREEN','ADAMS',
202             'BAKER','GONZALEZ','NELSON','CARTER','MITCHELL','PEREZ','ROBERTS','TURNER','PHILLIPS',
203             'CAMPBELL','PARKER','EVANS','EDWARDS','COLLINS','STEWART','SANCHEZ','MORRIS','ROGERS',
204             'REED','COOK','MORGAN','BELL','MURPHY','BAILEY','RIVERA','COOPER','RICHARDSON','COX',
205             'HOWARD','WARD','TORRES','PETERSON','GRAY','RAMIREZ','JAMES','WATSON','BROOKS','KELLY',
206             'SANDERS','PRICE','BENNETT','WOOD','BARNES','ROSS','HENDERSON','COLEMAN','JENKINS','PERRY',
207             'POWELL','LONG','PATTERSON','HUGHES','FLORES','WASHINGTON','BUTLER','SIMMONS','FOSTER',
208             'GONZALES','BRYANT','ALEXANDER','RUSSELL','GRIFFIN','DIAZ','HAYES','MYERS','FORD','HAMILTON',
209             'GRAHAM','SULLIVAN','WALLACE','WOODS','COLE','WEST','JORDAN','OWENS','REYNOLDS','FISHER',
210             'ELLIS','HARRISON','GIBSON','MCDONALD','CRUZ','MARSHALL','ORTIZ','GOMEZ','MURRAY','FREEMAN',
211             'WELLS','WEBB','SIMPSON','STEVENS','TUCKER','PORTER','HUNTER','HICKS','CRAWFORD','HENRY',
212             'BOYD','MASON','MORALES','KENNEDY','WARREN','DIXON','RAMOS','REYES','BURNS','GORDON','SHAW',
213             'HOLMES','RICE','ROBERTSON','HUNT','BLACK','DANIELS','PALMER','MILLS','NICHOLS','GRANT',
214             'KNIGHT','FERGUSON','ROSE','STONE','HAWKINS','DUNN','PERKINS','HUDSON','SPENCER','GARDNER',
215             'STEPHENS','PAYNE','PIERCE','BERRY','MATTHEWS','ARNOLD','WAGNER','WILLIS','RAY','WATKINS',
216             'OLSON','CARROLL','DUNCAN','SNYDER','HART','CUNNINGHAM','BRADLEY','LANE','ANDREWS','RUIZ',
217             'HARPER','FOX','RILEY','ARMSTRONG','CARPENTER','WEAVER','GREENE','LAWRENCE','ELLIOTT','CHAVEZ',
218             'SIMS','AUSTIN','PETERS','KELLEY','FRANKLIN','LAWSON','FIELDS','GUTIERREZ','RYAN','SCHMIDT',
219             'CARR','VASQUEZ','CASTILLO','WHEELER','CHAPMAN','OLIVER','MONTGOMERY','RICHARDS','WILLIAMSON',
220             'JOHNSTON','BANKS','MEYER','BISHOP','MCCOY','HOWELL','ALVAREZ','MORRISON','HANSEN','FERNANDEZ',
221             'GARZA','HARVEY','LITTLE','BURTON','STANLEY','NGUYEN','GEORGE','JACOBS','REID','KIM','FULLER',
222             'LYNCH','DEAN','GILBERT','GARRETT','ROMERO','WELCH','LARSON','FRAZIER','BURKE','HANSON','DAY',
223             'MENDOZA','MORENO','BOWMAN','MEDINA','FOWLER');
224         $firstnames = array( 'JAMES','JOHN','ROBERT','MARY','MICHAEL','WILLIAM','DAVID','RICHARD',
225             'CHARLES','JOSEPH','THOMAS','PATRICIA','LINDA','CHRISTOPHER','BARBARA','DANIEL','PAUL',
226             'MARK','ELIZABETH','JENNIFER','DONALD','GEORGE','MARIA','KENNETH','SUSAN','STEVEN','EDWARD',
227             'MARGARET','BRIAN','DOROTHY','RONALD','ANTHONY','LISA','KEVIN','NANCY','KAREN','BETTY',
228             'HELEN','JASON','MATTHEW','GARY','TIMOTHY','SANDRA','JOSE','LARRY','JEFFREY','DONNA',
229             'FRANK','CAROL','RUTH','SCOTT','ERIC','STEPHEN','ANDREW','SHARON','MICHELLE','LAURA',
230             'SARAH','KIMBERLY','DEBORAH','JESSICA','RAYMOND','SHIRLEY','CYNTHIA','ANGELA','MELISSA',
231             'BRENDA','AMY','GREGORY','ANNA','JOSHUA','JERRY','REBECCA','VIRGINIA','KATHLEEN','PAMELA',
232             'DENNIS','MARTHA','DEBRA','AMANDA','STEPHANIE','WALTER','PATRICK','CAROLYN','CHRISTINE',
233             'PETER','MARIE','JANET','CATHERINE','HAROLD','FRANCES','DOUGLAS','HENRY','ANN','JOYCE',
234             'DIANE','ALICE','JULIE','CARL','HEATHER');
235         $users_count = 0;
236         $users = array();
238         shuffle($lastnames);
239         shuffle($firstnames);
241         $next_user_id = $DB->get_field_sql("SELECT MAX(id) FROM {user}") + 1;
243         for ($i = 0; $i < $this->get('number_of_students'); $i++) {
245             $lastname = trim(ucfirst(strtolower($lastnames[rand(0, count($lastnames) - 1)])));
246             $firstname = $firstnames[rand(0, count($firstnames) - 1)];
248             $user = new stdClass();
249             $user->firstname = trim(ucfirst(strtolower($firstname)));
250             $user->username = strtolower(substr($firstname, 0, 7) . substr($lastname, 0, 7)) . $next_user_id++;
251             $user->lastname = $lastname;
252             $user->email = $user->username . '@example.com';
253             $user->mnethostid = 1;
254             $user->city = 'Test City';
255             $user->country = 'AU';
256             $user->password = md5('password');
257             $user->auth        = 'manual';
258             $user->confirmed   = 1;
259             $user->lang        = $CFG->lang;
260             $user->timemodified= time();
262             $user->id = $DB->insert_record("user", $user);
263             $users_count++;
264             $users[] = $user->id;
265             $next_user_id = $user->id + 1;
266             $this->verbose("Inserted $user->firstname $user->lastname into DB "
267                 ."(username=$user->username, password=password).");
268         }
270         if (!$this->get('quiet')) {
271             echo "$users_count users correctly inserted in the database.{$this->eolchar}";
272         }
273         return $users;
274     }
276     public function generate_data() {
277         if (!$this->do_generation) {
278             return false;
279         }
281         set_time_limit($this->get('time_limit'));
283         // Process tiny data set
284         $tiny = $this->get('tiny');
285         if (!empty($tiny)) {
286             $this->verbose("Generating a tiny data set: 1 student in 1 course with 1 module in 1 section...");
287             $this->set('number_of_courses',1);
288             $this->set('number_of_students',1);
289             $this->set('number_of_modules',1);
290             $this->set('number_of_sections',1);
291             $this->set('assignment_grades',false);
292             $this->set('quiz_grades',false);
293             $this->set('students_per_course',1);
294             $this->set('questions_per_course',1);
295             $this->set('questions_per_quiz',1);
296         }
298         if ($this->get('pre_cleanup')) {
299             $this->verbose("Deleting previous test data...");
300             $this->data_cleanup();
302             if (!$this->get('quiet')) {
303                 echo "Previous test data has been deleted.{$this->eolchar}";
304             }
305         }
308         if (!$this->get('no_data')) {
309             $users = $this->generate_users();
310             $courses = $this->generate_courses();
311             $modules = $this->generate_modules($courses);
312             $questions = $this->generate_questions($courses, $modules);
313             $course_users = $this->generate_role_assignments($users, $courses);
314             $this->generate_forum_posts($course_users, $modules);
315             $this->generate_grades($course_users, $courses, $modules);
316             $this->generate_module_content($course_users, $courses, $modules);
317         }
319         if ($this->get('post_cleanup')) {
320             if (!$this->get('quiet')) {
321                 echo "Removing generated data..." . $this->eolchar;
322             }
323             $this->data_cleanup();
324             if (!$this->get('quiet')) {
325                 echo "Generated data has been deleted." . $this->eolchar;
326             }
327         }
329         /**
330          * FINISHING SCRIPT
331          */
332         $stoptimer = time()+microtime();
333         $timer = round($stoptimer-$this->starttime,4);
334         if (!$this->get('quiet')) {
335             echo "End of script! ($timer seconds taken){$this->eolchar}";
336         }
338     }
340     public function generate_courses() {
341         global $DB;
343         $this->verbose("Generating " . $this->get('number_of_courses')." courses...");
344         $base_course = new stdClass();
345         $next_course_id = $DB->get_field_sql("SELECT MAX(id) FROM {course}") + 1;
347         $base_course->MAX_FILE_SIZE = '2097152';
348         $base_course->category = '1';
349         $base_course->summary = 'Blah Blah';
350         $base_course->format = 'weeks';
351         $base_course->numsections = '10';
352         $base_course->startdate = mktime();
353         $base_course->id = '0';
355         $courses_count = 0;
356         $courses = array();
357         for ($i = 1; $i <= $this->get('number_of_courses'); $i++) {
358             $newcourse = fullclone($base_course);
359             $newcourse->fullname = "Test course $next_course_id";
360             $newcourse->shortname = "Test $next_course_id";
361             $newcourse->idnumber = $next_course_id;
362             if (!$course = create_course($newcourse)) {
363                 $this->verbose("Error inserting a new course in the database!");
364                 if (!$this->get('ignore_errors')) {
365                     die();
366                 }
367             } else {
368                 $courses_count++;
369                 $next_course_id++;
370                 $courses[] = $course->id;
371                 $next_course_id = $course->id + 1;
372                 $this->verbose("Inserted $course->fullname into DB (idnumber=$course->idnumber).");
373             }
374         }
376         if (!$this->get('quiet')) {
377             echo "$courses_count test courses correctly inserted into the database.{$this->eolchar}";
378         }
379         return $courses;
380     }
382     public function generate_modules($courses) {
383         global $DB, $CFG;
384         // Parse the modules-list variable
386         $this->verbose("Generating " . $this->get('number_of_sections')." sections with "
387             .$this->get('number_of_modules')." modules in each section, for each course...");
389         list($modules_list_sql, $modules_params) =
390             $DB->get_in_or_equal($this->get('modules_list'), SQL_PARAMS_NAMED, 'param0000', true);
392         list($modules_ignored_sql, $ignore_params) =
393             $DB->get_in_or_equal($this->modules_to_ignore, SQL_PARAMS_NAMED, 'param2000', false);
395         $wheresql = "name $modules_list_sql AND name $modules_ignored_sql";
396         $modules = $DB->get_records_select('modules', $wheresql, array_merge($modules_params, $ignore_params));
398         foreach ($modules as $key => $module) {
399             $module->count = 0;
401             // Scorm, lams and hotpot are too complex to set up, remove them
402             if (in_array($module->name, $this->modules_to_ignore) ||
403                 !in_array($module->name, $this->modules_list)) {
404                 unset($modules[$key]);
405             }
406         }
408         // Dirty hack for renumbering the modules array's keys
409         $first_module = reset($modules);
410         array_shift($modules);
411         array_unshift($modules, $first_module);
413         $modules_array = array();
415         if (count($courses) > 0) {
416             $libraries = array();
417             foreach ($courses as $courseid) {
419                 // Text resources
420                 for ($i = 1; $i <= $this->get('number_of_sections'); $i++) {
421                     for ($j = 0; $j < $this->get('number_of_modules'); $j++) {
423                         $module = new stdClass();
425                         // If only one module is created, and we also need to add a question to a quiz, create only a quiz
426                         if ($this->get('number_of_modules') == 1
427                                     && $this->get('questions_per_quiz') > 0
428                                     && !empty($modules[8])) {
429                             $moduledata = $modules[8];
430                         } else {
431                             $moduledata = $modules[array_rand($modules)];
432                         }
434                         $libfile = "$CFG->dirroot/mod/$moduledata->name/lib.php";
435                         if (file_exists($libfile)) {
436                             if (!in_array($libfile, $libraries)) {
437                                 $this->verbose("Including library for $moduledata->name...");
438                                 $libraries[] = $libfile;
439                                 require_once($libfile);
440                             }
441                         } else {
442                             $this->verbose("Could not load lib file for module $moduledata->name!");
443                             if (!$this->get('ignore_errors')) {
444                                 die();
445                             }
446                         }
448                         // Basically 2 types of text fields: description and content
449                         $description = "This $moduledata->name has been randomly generated by a very useful script, "
450                                      . "for the purpose of testing "
451                                      . "the boundaries of Moodle in various contexts. Moodle should be able to scale to "
452                                      . "any size without "
453                                      . "its speed and ease of use being affected dramatically.";
454                         $content = 'Very useful content, I am sure you would agree';
456                         $module_type_index = 0;
457                         $module->introformat = FORMAT_MOODLE;
458                         $module->messageformat = FORMAT_MOODLE;
460                         // Special module-specific config
461                         switch ($moduledata->name) {
462                             case 'assignment':
463                                 $module->intro = $description;
464                                 $module->assignmenttype = $this->get_module_type('assignment');
465                                 $module->timedue = mktime() + 89487321;
466                                 $module->grade = rand(50,100);
467                                 break;
468                             case 'chat':
469                                 $module->intro = $description;
470                                 $module->schedule = 1;
471                                 $module->chattime = 60 * 60 * 4;
472                                 break;
473                             case 'data':
474                                 $module->intro = $description;
475                                 $module->name = 'test';
476                                 break;
477                             case 'choice':
478                                 $module->intro = $description;
479                                 $module->text = $content;
480                                 $module->option = array('Good choice', 'Bad choice', 'No choice');
481                                 $module->limit  = array(1, 5, 0);
482                                 break;
483                             case 'comments':
484                                 $module->intro = $description;
485                                 $module->comments = $content;
486                                 break;
487                             case 'feedback':
488                                 $module->intro = $description;
489                                 $module->page_after_submit = $description;
490                                 $module->comments = $content;
491                                 break;
492                             case 'forum':
493                                 $module->intro = $description;
494                                 $module->type = $this->get_module_type('forum');
495                                 $module->forcesubscribe = rand(0, 1);
496                                 $module->format = 1;
497                                 break;
498                             case 'glossary':
499                                 $module->intro = $description;
500                                 $module->displayformat = $this->glossary_formats[rand(0, count($this->glossary_formats) - 1)];
501                                 $module->cmidnumber = rand(0,999999);
502                                 break;
503                             case 'label':
504                                 $module->content = $content;
505                                 $module->intro = $description;
506                                 break;
507                             case 'lesson':
508                                 $module->lessondefault = 1;
509                                 $module->available = mktime();
510                                 $module->deadline = mktime() + 719891987;
511                                 $module->grade = 100;
512                                 break;
513                             case 'quiz':
514                                 $module->intro = $description;
515                                 $module->feedbacktext = 'blah';
516                                 $module->feedback = 1;
517                                 $module->feedbackboundaries = array(2, 1);
518                                 $module->grade = 10;
519                                 $module->timeopen = time();
520                                 $module->timeclose = time() + 68854;
521                                 $module->shufflequestions = true;
522                                 $module->shuffleanswers = true;
523                                 $module->quizpassword = '';
524                                 break;
525                             case 'resource':
526                                 $module->type = $this->get_module_type('resource');
527                                 $module->alltext = $content;
528                                 $module->summary = $description;
529                                 $module->windowpopup = rand(0,1);
530                                 $module->display = rand(0,1);
531                                 $module->resizable = rand(0,1);
532                                 $module->scrollbars = rand(0,1);
533                                 $module->directories = rand(0,1);
534                                 $module->location = 'file.txt';
535                                 $module->menubar = rand(0,1);
536                                 $module->toolbar = rand(0,1);
537                                 $module->status = rand(0,1);
538                                 $module->width = rand(200,600);
539                                 $module->height = rand(200,600);
540                                 $module->directories = rand(0,1);
541                                 $module->files = false;
542                                 $module->param_navigationmenu = rand(0,1);
543                                 $module->param_navigationbuttons = rand(0,1);
544                                 $module->reference = 1;
545                                 $module->forcedownload = 1;
546                                 break;
547                             case 'survey':
548                                 $module->template = rand(1,5);
549                                 $module->intro = $description;
550                                 break;
551                             case 'wiki':
552                                 $module->intro = $description;
553                                 $module->summary = $description;
554                                 break;
555                         }
557                         $module->name = ucfirst($moduledata->name) . ' ' . $moduledata->count++;
559                         $module->course = $courseid;
560                         $module->section = $i;
561                         $module->module = $moduledata->id;
562                         $module->modulename = $moduledata->name;
563                         $module->add = $moduledata->name;
564                         $module->cmidnumber = '';
565                         $module->coursemodule = '';
566                         $add_instance_function = $moduledata->name . '_add_instance';
568                         $section = get_course_section($i, $courseid);
569                         $module->section = $section->id;
570                         $module->coursemodule = add_course_module($module);
571                         $module->section = $i;
573                         if (function_exists($add_instance_function)) {
574                             $this->verbose("Calling module function $add_instance_function");
575                             $module->instance = $add_instance_function($module, '');
576                             $DB->set_field('course_modules', 'instance', $module->instance, array('id'=>$module->coursemodule));
577                         } else {
578                             $this->verbose("Function $add_instance_function does not exist!");
579                             if (!$this->get('ignore_errors')) {
580                                 die();
581                             }
582                         }
584                         add_mod_to_section($module);
586                         $module->cmidnumber = set_coursemodule_idnumber($module->coursemodule, '');
588                         $this->verbose("A $moduledata->name module was added to section $i (id $module->section) "
589                             ."of course $courseid.");
590                         rebuild_course_cache($courseid);
592                         $module_instance = $DB->get_field('course_modules', 'instance', array('id' => $module->coursemodule));
593                         $module_record = $DB->get_record($moduledata->name, array('id' => $module_instance));
594                         $module_record->instance = $module_instance;
596                         if (empty($modules_array[$moduledata->name])) {
597                             $modules_array[$moduledata->name] = array();
598                         }
600                         // TODO Find out why some $module_record end up empty here... (particularly quizzes)
601                         if (!empty($module_record->instance)) {
602                             $modules_array[$moduledata->name][] = $module_record;
603                         }
604                     }
605                 }
606             }
608             if (!$this->get('quiet')) {
609                 echo "Successfully generated " . $this->get('number_of_modules') * $this->get('number_of_sections')
610                     . " modules in each course!{$this->eolchar}";
611             }
613             return $modules_array;
614         }
615         return null;
616     }
618     public function generate_questions($courses, $modules) {
619         global $DB, $CFG;
621         if (!is_null($this->get('questions_per_course')) && count($courses) > 0 && is_array($courses)) {
622             require_once($CFG->libdir .'/questionlib.php');
623             require_once($CFG->dirroot .'/mod/quiz/editlib.php');
624             $questions = array();
625             $questionsmenu = question_type_menu();
626             $questiontypes = array();
627             foreach ($questionsmenu as $qtype => $qname) {
628                 $questiontypes[] = $qtype;
629             }
631             // Add the questions
632             foreach ($courses as $courseid) {
633                 $questions[$courseid] = array();
634                 for ($i = 0; $i < $this->get('questions_per_course'); $i++) {
635                     $qtype = $questiontypes[array_rand($questiontypes)];
637                     // Only the following types are supported right now. Hang around for more!
638                     $supported_types = array('match', 'essay', 'multianswer', 'multichoice', 'shortanswer',
639                             'numerical', 'truefalse', 'calculated');
640                     $qtype = $supported_types[array_rand($supported_types)];
642                     if ($qtype == 'calculated') {
643                         continue;
644                     }
645                     $classname = "question_{$qtype}_qtype";
646                     if ($qtype == 'multianswer') {
647                         $classname = "embedded_cloze_qtype";
648                     }
650                     $question = new $classname();
651                     $question->qtype = $qtype;
652                     $questions[$courseid][] = $question->generate_test("question$qtype-$i", $courseid);
653                     $this->verbose("Generated a question of type $qtype for course id $courseid.");
654                 }
655             }
657             // Assign questions to quizzes, if such exist
658             if (!empty($modules['quiz']) && !empty($questions) && !is_null($this->get('questions_per_quiz'))) {
659                 $quizzes = $modules['quiz'];
661                 // Cannot assign more questions per quiz than are available, so determine which is the largest
662                 $questions_per_quiz = max(count($questions), $this->get('questions_per_quiz'));
664                 foreach ($quizzes as $quiz) {
665                     $questions_added = array();
666                     for ($i = 0; $i < $questions_per_quiz; $i++) {
668                         // Add a random question to the quiz
669                         do {
670                             if (empty($quiz->course)) {
671                                 print_object($quizzes);die();
672                             }
673                             $random = rand(0, count($questions[$quiz->course]));
674                         } while (in_array($random, $questions_added) || !array_key_exists($random, $questions[$quiz->course]));
676                         if (!quiz_add_quiz_question($questions[$quiz->course][$random]->id, $quiz)) {
678                             // Could not add question to quiz!! report error
679                             if (!$this->get('quiet')) {
680                                 echo "WARNING: Could not add question id $random to quiz id $quiz->id{$this->eolchar}";
681                             }
682                         } else {
683                             $this->verbose("Adding question id $random to quiz id $quiz->id.");
684                             $questions_added[] = $random;
685                         }
686                     }
687                 }
688             }
689             return $questions;
690         }
691         return null;
692     }
694     public function generate_role_assignments($users, $courses) {
695         global $CFG, $DB;
696         $course_users = array();
698         if (count($courses) > 0) {
699             $this->verbose("Inserting student->course role assignments...");
700             $assigned_count = 0;
701             $assigned_users = array();
703             foreach ($courses as $courseid) {
704                 $course_users[$courseid] = array();
706                 // Select $students_per_course for assignment to course
707                 shuffle($users);
708                 $users_to_assign = array_slice($users, 0, $this->get('students_per_course'));
710                 $context = get_context_instance(CONTEXT_COURSE, $courseid);
711                 foreach ($users_to_assign as $random_user) {
712                     role_assign(5, $random_user, $context->id);
714                     $assigned_count++;
715                     $course_users[$courseid][] = $random_user;
716                     if (!isset($assigned_users[$random_user])) {
717                         $assigned_users[$random_user] = 1;
718                     } else {
719                         $assigned_users[$random_user]++;
720                     }
721                     $this->verbose("Student $random_user was assigned to course $courseid.");
722                 }
723             }
725             if (!$this->get('quiet')) {
726                 echo "$assigned_count user => course role assignments have been correctly performed.{$this->eolchar}";
727             }
728             return $course_users;
729         }
730         return null;
731     }
733     public function generate_forum_posts($course_users, $modules) {
734         global $CFG, $DB, $USER;
736         if (in_array('forum', $this->modules_list) &&
737                 $this->get('discussions_per_forum') &&
738                 $this->get('posts_per_discussion') &&
739                 isset($modules['forum'])) {
741             $discussions_count = 0;
742             $posts_count = 0;
744             foreach ($modules['forum'] as $forum) {
745                 $forum_users = $course_users[$forum->course];
747                 for ($i = 0; $i < $this->get('discussions_per_forum'); $i++) {
748                     $mform = new fake_form();
750                     require_once($CFG->dirroot.'/mod/forum/lib.php');
752                     $discussion = new object();
753                     $discussion->course        = $forum->course;
754                     $discussion->forum         = $forum->id;
755                     $discussion->name          = 'Test discussion';
756                     $discussion->intro         = 'This is just a test forum discussion';
757                     $discussion->assessed      = 0;
758                     $discussion->messageformat = 1;
759                     $discussion->messagetrust = 0;
760                     $discussion->mailnow       = false;
761                     $discussion->groupid       = -1;
762                     $discussion->attachments   = null;
763                     $discussion->itemid = 752157083;
765                     $message = '';
766                     $super_global_user = clone($USER);
767                     $user_id = $forum_users[array_rand($forum_users)];
768                     $USER = $DB->get_record('user', array('id' => $user_id));
770                     if ($discussion_id = forum_add_discussion($discussion, $mform, $message)) {
771                         $discussion = $DB->get_record('forum_discussions', array('id' => $discussion_id));
772                         $discussions_count++;
774                         // Add posts to this discussion
775                         $post_ids = array($discussion->firstpost);
777                         for ($j = 0; $j < $this->get('posts_per_discussion'); $j++) {
778                             $global_user = clone($USER);
779                             $user_id = $forum_users[array_rand($forum_users)];
780                             $USER = $DB->get_record('user', array('id' => $user_id));
781                             $post = new stdClass();
782                             $post->discussion = $discussion_id;
783                             $post->subject = 'Re: test discussion';
784                             $post->message = '<p>Nothing much to say, since this is just a test...</p>';
785                             $post->format = 1;
786                             $post->attachments = null;
787                             $post->itemid = 752157083;
788                             $post->parent = $post_ids[array_rand($post_ids)];
790                             if ($post_ids[] = forum_add_new_post($post, $mform, $message)) {
791                                 $posts_count++;
792                             }
793                             $USER = $global_user;
794                         }
795                     }
797                     $USER = $super_global_user;
799                     if ($forum->type == 'single') {
800                         break;
801                     }
802                 }
803             }
804             if ($discussions_count > 0 && !$this->get('quiet')) {
805                 echo "$discussions_count forum discussions have been generated.{$this->eolchar}";
806             }
807             if ($posts_count > 0 && !$this->get('quiet')) {
808                 echo "$posts_count forum posts have been generated.{$this->eolchar}";
809             }
811             return true;
812         }
813         return null;
815     }
817     public function generate_grades($course_users, $courses, $modules) {
818         global $CFG, $DB, $USER;
820         /**
821          * ASSIGNMENT GRADES GENERATION
822          */
823         if ($this->get('assignment_grades') && isset($modules['assignment'])) {
824             $grades_count = 0;
825             foreach ($course_users as $courseid => $userid_array) {
826                 foreach ($userid_array as $userid) {
827                     foreach ($modules['assignment'] as $assignment) {
828                         if (in_array($assignment->course, $courses)) {
829                             $maxgrade = $assignment->grade;
830                             $random_grade = rand(0, $maxgrade);
831                             $grade = new stdClass();
832                             $grade->assignment = $assignment->id;
833                             $grade->userid = $userid;
834                             $grade->grade = $random_grade;
835                             $grade->rawgrade = $random_grade;
836                             $grade->teacher = $USER->id;
837                             $grade->submissioncomment = 'comment';
838                             $DB->insert_record('assignment_submissions', $grade);
839                             grade_update('mod/assignment', $assignment->course, 'mod', 'assignment', $assignment->id, 0, $grade);
840                             $this->verbose("A grade ($random_grade) has been given to user $userid "
841                                         . "for assignment $assignment->id");
842                             $grades_count++;
843                         }
844                     }
845                 }
846             }
847             if ($grades_count > 0) {
848                 $this->verbose("$grades_count assignment grades have been generated.{$this->eolchar}");
849             }
850         }
852         /**
853          * QUIZ GRADES GENERATION
854          */
855         if ($this->get('quiz_grades') && isset($modules['quiz'])) {
856             $grades_count = 0;
857             foreach ($course_users as $userid => $courses) {
858                 foreach ($modules['quiz'] as $quiz) {
859                     if (in_array($quiz->course, $courses)) {
860                         $maxgrade = $quiz->grade;
861                         $random_grade = rand(0, $maxgrade);
862                         $grade = new stdClass();
863                         $grade->quiz = $quiz->id;
864                         $grade->userid = $userid;
865                         $grade->grade = $random_grade;
866                         $grade->rawgrade = $random_grade;
867                         $DB->insert_record('quiz_grades', $grade);
868                         grade_update('mod/quiz', $courseid, 'mod', 'quiz', $quiz->id, 0, $grade);
869                         $this->verbose("A grade ($random_grade) has been given to user $userid for quiz $quiz->id");
870                         $grades_count++;
871                     }
872                 }
873             }
874             if ($grades_count > 0 && !$this->get('quiet')) {
875                 echo "$grades_count quiz grades have been generated.{$this->eolchar}";
876             }
877         }
878         return null;
879     }
881     public function generate_module_content($course_users, $courses, $modules) {
882         global $USER, $DB, $CFG;
883         $result = null;
885         $entries_count = 0;
886         if ($this->get('entries_per_glossary') && !empty($modules['glossary'])) {
887             foreach ($modules['glossary'] as $glossary) {
888                 for ($i = 0; $i < $this->get('entries_per_glossary'); $i++) {
889                     $entry = new stdClass();
890                     $entry->glossaryid = $glossary->id;
891                     $entry->userid = $USER->id;
892                     $entry->concept = "Test concept";
893                     $entry->definition = "A test concept is nothing to write home about: just a test concept.";
894                     $entry->format = 1;
895                     $entry->timecreated = time();
896                     $entry->timemodified = time();
897                     $entry->teacherentry = 0;
898                     $entry->approved = 1;
899                     $DB->insert_record('glossary_entries', $entry);
900                     $entries_count++;
901                 }
902             }
903             if ($entries_count > 0 && !$this->get('quiet')) {
904                 echo "$entries_count glossary definitions have been generated.{$this->eolchar}";
905             }
906             $result = true;
907         }
909         $fields_count = 0;
910         if (!empty($modules['data']) && $this->get('fields_per_database') && $this->get('database_records_per_student')) {
911             $database_field_types = array('checkbox',
912                                           'date',
913                                           'file',
914                                           'latlong',
915                                           'menu',
916                                           'multimenu',
917                                           'number',
918                                           'picture',
919                                           'radiobutton',
920                                           'text',
921                                           'textarea',
922                                           'url');
925             $fields = array();
927             foreach ($modules['data'] as $data) {
929                 for ($i = 0; $i < $this->get('fields_per_database'); $i++) {
930                     $type = $database_field_types[array_rand($database_field_types)];
931                     require_once($CFG->dirroot.'/mod/data/field/'.$type.'/field.class.php');
932                     $newfield = 'data_field_'.$type;
933                     $cm = get_coursemodule_from_instance('data', $data->id);
934                     $newfield = new $newfield(0, $data, $cm);
935                     $fields[$data->id][] = $newfield;
936                     $newfield->insert_field();
937                 }
939                 // Generate fields for each database (same fields for all, no arguing)
940                 for ($i = 0; $i < $this->get('fields_per_database'); $i++) {
942                 }
944                 // Generate database records for each student, if needed
945                 for ($i = 0; $i < $this->get('database_records_per_student'); $i++) {
947                 }
948             }
949             if ($fields_count > 0 && !$this->get('quiet')) {
950                 $datacount = count($modules['data']);
951                 echo "$fields_count database fields have been generated for each of the "
952                    . "$datacount generated databases.{$this->eolchar}";
953             }
954             $result = true;
955         }
957         $messages_count = 0;
958         if (!empty($modules['chat']) && $this->get('messages_per_chat')) {
960             // Insert all users into chat_users table, then a message from each user
961             foreach ($modules['chat'] as $chat) {
963                 foreach ($course_users as $courseid => $users_array) {
965                     foreach ($users_array as $userid) {
966                         if ($messages_count < $this->get('messages_per_chat')) {
967                             $chat_user = new stdClass();
968                             $chat_user->chatid = $chat->id;
969                             $chat_user->userid = $userid;
970                             $chat_user->course = $courseid;
971                             $DB->insert_record('chat_users', $chat_user);
973                             $chat_message = new stdClass();
974                             $chat_message->chatid = $chat->id;
975                             $chat_message->userid = $userid;
976                             $chat_message->message = "Hi, everyone!";
977                             $DB->insert_record('chat_messages', $chat_message);
979                             $messages_count++;
980                         }
981                     }
982                 }
983             }
985             if ($messages_count > 0 && !$this->get('quiet')) {
986                 $datacount = count($modules['chat']);
987                 echo "$messages_count messages have been generated for each of the "
988                    . "$datacount generated chats.{$this->eolchar}";
989             }
990             $result = true;
991         }
993         return $result;
994     }
997     /**
998      * If verbose is switched on, prints a string terminated by the global eolchar string.
999      * @param string $string The string to STDOUT
1000      */
1001     public function verbose($string) {
1002         if ($this->get('verbose') && !$this->get('quiet')) {
1003             echo $string . $this->eolchar;
1004         }
1005     }
1008     /**
1009      * Attempts to delete all generated test data.
1010      * WARNING: THIS WILL COMPLETELY MESS UP A "REAL" SITE, AND IS INTENDED ONLY FOR DEVELOPMENT PURPOSES
1011      */
1012     function data_cleanup() {
1013         global $DB;
1015         if ($this->get('quiet')) {
1016             ob_start();
1017         }
1019         // TODO Cleanup code
1021         if ($this->get('quiet')) {
1022             ob_end_clean();
1023         }
1024     }
1026     public function get($setting) {
1027         if (isset($this->settings[$setting])) {
1028             return $this->settings[$setting]->value;
1029         } else {
1030             return null;
1031         }
1032     }
1034     public function set($setting, $value) {
1035         if (isset($this->settings[$setting])) {
1036             $this->settings[$setting]->value = $value;
1037         } else {
1038             return false;
1039         }
1040     }
1042     public function get_module_type($modulename) {
1043         $return_val = false;
1045         $type = $this->get($modulename.'_type');
1047         if (is_object($type) && isset($type->type) && isset($type->options)) {
1049             if ($type->type == GENERATOR_RANDOM) {
1050                 $return_val = $type->options[array_rand($type->options)];
1052             } elseif ($type->type == GENERATOR_SEQUENCE) {
1053                 $return_val = $type->options[$this->{$modulename.'_type_counter'}];
1054                 $this->{$modulename.'_type_counter'}++;
1056                 if ($this->{$modulename.'_type_counter'} == count($type->options)) {
1057                     $this->{$modulename.'_type_counter'} = 0;
1058                 }
1059             }
1061         } elseif (is_array($type)) {
1062             $return_val = $type[array_rand($type)];
1064         } elseif (is_string($type)) {
1065             $return_val = $type;
1066         }
1068         return $return_val;
1069     }
1072 class generator_argument {
1073     public $short;
1074     public $long;
1075     public $help;
1076     public $type;
1077     public $default = null;
1078     public $value;
1080     public function __construct($params) {
1081         foreach ($params as $key => $val) {
1082             $this->$key = $val;
1083         }
1084         $this->value = $this->default;
1085     }
1088 class generator_cli extends generator {
1089     public $eolchar = "\n";
1091     public function __construct($settings, $argc) {
1092         parent::__construct();
1094         // Building the USAGE output of the command line version
1095         $help = "Moodle Data Generator. Generates Data for Moodle sites. Good for benchmarking and other tests.\n\n"
1096               . "FOR DEVELOPMENT PURPOSES ONLY! DO NOT USE ON A PRODUCTION SITE!\n\n"
1097               . "Note: By default the script attempts to fill DB tables prefixed with tst_\n"
1098               . "To override the prefix, use the -P (--database_prefix) setting.\n\n"
1099               . "Usage: {$settings[0]}; [OPTION] ...\n"
1100               . "Options:\n"
1101               . "  -h,    -?, -help, --help               This output\n";
1103         foreach ($this->settings as $argument) {
1104             $equal = '';
1105             if (!empty($argument->type)) {
1106                 $equal = "={$argument->type}";
1107             }
1109             $padding1 = 5 - strlen($argument->short);
1110             $padding2 = 30 - (strlen($argument->long) + strlen($equal));
1111             $paddingstr1 = '';
1112             for ($i = 0; $i < $padding1; $i++) {
1113                 $paddingstr1 .= ' ';
1114             }
1115             $paddingstr2 = '';
1116             for ($i = 0; $i < $padding2; $i++) {
1117                 $paddingstr2 .= ' ';
1118             }
1120             $help .= "  -{$argument->short},$paddingstr1--{$argument->long}$equal$paddingstr2{$argument->help}\n";
1121         }
1123         $help .= "\nEmail nicolas@moodle.com for any suggestions or bug reports.\n";
1125         if ($argc == 1 || in_array($settings[1], array('--help', '-help', '-h', '-?'))) {
1126             echo $help;
1127             die();
1129         } else {
1130             $this->do_generation = true;
1131             $settings = $this->_arguments($settings);
1132             $argscount = 0;
1134             foreach ($this->settings as $argument) {
1135                 $value = null;
1137                 if (in_array($argument->short, array_keys($settings))) {
1138                     $value = $settings[$argument->short];
1139                     unset($settings[$argument->short]);
1141                 } elseif (in_array($argument->long, array_keys($settings))) {
1142                     $value = $settings[$argument->long];
1143                     unset($settings[$argument->long]);
1144                 }
1146                 if (!is_null($value)) {
1148                     if (!empty($argument->type) && ($argument->type == 'mod1,mod2...' || $argument->type == 'SELECT')) {
1149                         $value = explode(',', $value);
1150                     }
1152                     $this->set($argument->long, $value);
1153                     $argscount++;
1154                 }
1155             }
1157             // If some params are left in argv, it means they are not supported
1158             if ($argscount == 0 || count($settings) > 0) {
1159                 echo $help;
1160                 die();
1161             }
1162         }
1164         $this->connect();
1165     }
1167     public function generate_data() {
1168         if (is_null($this->get('username')) || $this->get('username') == '') {
1169             echo "You must enter a valid username for a moodle administrator account on this site.{$this->eolchar}";
1170             die();
1171         } elseif (is_null($this->get('password')) || $this->get('password') == '') {
1172             echo "You must enter a valid password for a moodle administrator account on this site.{$this->eolchar}";
1173             die();
1174         } else {
1175             if (!$user = authenticate_user_login($this->get('username'), $this->get('password'))) {
1176                 echo "Invalid username or password!{$this->eolchar}";
1177                 die();
1178             }
1179             complete_user_login($user);
1180             $systemcontext = get_context_instance(CONTEXT_SYSTEM);
1182             if (!is_siteadmin($user->id)) {//TODO: add some proper access control check here!!
1183                 echo "You do not have administration privileges on this Moodle site. "
1184                     ."These are required for running the generation script.{$this->eolchar}";
1185                 die();
1186             }
1187         }
1189         parent::generate_data();
1190     }
1192     /**
1193      * Converts the standard $argv into an associative array taking var=val arguments into account
1194      * @param array $argv
1195      * @return array $_ARG
1196      */
1197     private function _arguments($argv) {
1198         $_ARG = array();
1199         foreach ($argv as $arg) {
1200             if (preg_match('/--?([^=]+)=(.*)/',$arg,$reg)) {
1201                 $_ARG[$reg[1]] = $reg[2];
1202             } elseif(preg_match('/-([a-zA-Z0-9]+)/',$arg,$reg)) {
1203                $_ARG[$reg[1]] = 'true';
1204             }
1205         }
1206         return $_ARG;
1207     }
1210 class generator_web extends generator {
1211     public $eolchar = '<br />';
1212     public $mform;
1214     public function setup() {
1215         global $CFG;
1216         $this->mform = new generator_form();
1218         $this->do_generation = optional_param('do_generation', false, PARAM_BOOL);
1220         if ($data = $this->mform->get_data(false)) {
1221             foreach ($this->settings as $setting) {
1222                 if (isset($data->{$setting->long})) {
1223                     $this->set($setting->long, $data->{$setting->long});
1224                 }
1225             }
1226         }
1227     }
1229     public function display() {
1230         global $OUTPUT, $PAGE;
1231         $PAGE->set_title("Data generator");
1232         echo $OUTPUT->header();
1233         echo $OUTPUT->heading("Data generator: web interface");
1234         echo $OUTPUT->heading("FOR DEVELOPMENT PURPOSES ONLY. DO NOT USE ON A PRODUCTION SITE!", 3);
1235         echo $OUTPUT->heading("Your database contents will probably be massacred. You have been warned", 5);
1237         $this->mform->display();
1238         $this->connect();
1239     }
1241     public function complete() {
1242         global $OUTPUT;
1243         $this->dispose();
1244         echo $OUTPUT->footer();
1245     }
1248 class generator_silent extends generator {
1252 function generator_generate_data($settings) {
1253     $generator = new generator($settings);
1254     $generator->do_generation = true;
1255     $generator->generate_data();
1258 class fake_form {
1259     function get_new_filename($string) {
1260         return false;
1261     }
1263     function save_stored_file() {
1264         return true;
1265     }
1267     function get_data() {
1268         return array();
1269     }
1272 class generator_form extends moodleform {
1273     function definition() {
1274         global $generator, $CFG;
1276         $mform =& $this->_form;
1277         $mform->addElement('hidden', 'do_generation', 1);
1278         $mform->setType('do_generation', PARAM_INT);
1280         foreach ($generator->settings as $setting) {
1281             $type = 'advcheckbox';
1282             $options = null;
1283             $htmloptions = null;
1285             $label = ucfirst(str_replace('_', ' ', $setting->long));
1286             if (!empty($setting->type) && $setting->type == 'mod1,mod2...') {
1287                 $type = 'select';
1288                 $options = $generator->modules_list;
1289                 $htmloptions = array('multiple' => 'multiple');
1290             } elseif (!empty($setting->type) && $setting->type == 'SELECT') {
1291                 $type = 'select';
1292                 $options = array();
1293                 foreach ($setting->default as $option) {
1294                     $options[$option] = $option;
1295                 }
1296                 $htmloptions = array('multiple' => 'multiple');
1297             } elseif (!empty($setting->type)) {
1298                 $type = 'text';
1299             }
1301             if ($setting->long == 'password' || $setting->long == 'username') {
1302                 continue;
1303             }
1305             $mform->addElement($type, $setting->long, $label, $options, $htmloptions);
1307             if (isset($setting->default)) {
1308                 $mform->setDefault($setting->long, $setting->default);
1309             }
1310         }
1311         $this->add_action_buttons(false, 'Generate data!');
1312     }
1314     function definition_after_data() {
1316     }
1319 if (CLI_SCRIPT) {
1320     $generator = new generator_cli($argv, $argc);
1321     $generator->generate_data();
1322 } elseif (strstr($_SERVER['REQUEST_URI'], 'generator.php')) {
1323     require_login();
1324     $systemcontext = get_context_instance(CONTEXT_SYSTEM);
1325     require_capability('moodle/site:config', $systemcontext);
1327     $PAGE->set_url('/admin/generator.php');
1328     $PAGE->set_pagelayout('base');
1329     $generator = new generator_web();
1330     $generator->setup();
1331     $generator->display();
1332     $generator->generate_data();
1333     $generator->complete();
1334 } else {
1335     $generator = new generator_silent();