diff --git a/admin/generator.php b/admin/generator.php index d475cc19758e8..ea8f1f4fd82ea 100755 --- a/admin/generator.php +++ b/admin/generator.php @@ -1,35 +1,14 @@ libdir . '/formslib.php'); +require_once($CFG->dirroot .'/course/lib.php'); +require_once($CFG->dirroot .'/mod/resource/lib.php'); /** - * SCRIPT CONFIGURATION + * Controller class for data generation */ -$starttimer = time()+microtime(); - -$settings = array(); -$settings['data-prefix'] = 'test_'; -$settings['database-prefix'] = null; -$settings['modules-to-ignore'] = array('hotpot', 'lams', 'journal', 'scorm', 'exercise', 'dialogue'); -$settings['pre-cleanup'] = false; -$settings['post-cleanup'] = false; -$settings['time-limit'] = 0; -$settings['verbose'] = false; -$settings['quiet'] = false; -$settings['no-data'] = false; -$settings['ignore-errors'] = false; -$settings['number-of-courses'] = 1; -$settings['number-of-students'] = 250; -$settings['students-per-course'] = 20; -$settings['number-of-sections'] = 10; -$settings['number-of-modules'] = 50; -$settings['questions-per-course'] = 20; -$settings['questions-per-quiz'] = 5; -$settings['discussions-per-forum'] = 5; -$settings['posts-per-discussion'] = 15; -$settings['entries-per-glossary'] = 1; -$settings['assignment-grades'] = true; -$settings['quiz-grades'] = true; -$settings['modules-list'] = array('forum' => 'forum', +class generator { + public $modules_to_ignore = array('hotpot', 'lams', 'journal', 'scorm', 'exercise', 'dialogue'); + public $modules_list = array('forum' => 'forum', 'assignment' => 'assignment', 'glossary' => 'glossary', 'quiz' => 'quiz', @@ -43,329 +22,141 @@ 'survey' => 'survey', 'wiki' => 'wiki', 'workshop' => 'workshop'); -$settings['username'] = null; -$settings['password'] = null; -$settings['eolchar'] = '
'; // Character used to break lines - -// Argument arrays: 0=>short name, 1=>long name -$arguments = array( - array('short'=>'u', 'long'=>'username', - 'help' => 'Your moodle username', 'type'=>'STRING', 'default' => ''), - array('short'=>'pw', 'long'=>'password', - 'help' => 'Your moodle password', 'type'=>'STRING', 'default' => ''), - array('short'=>'p', 'long'=>'data-prefix', - 'help' => 'An optional prefix prepended to the unique identifiers of the generated data. Default=test_', - 'type'=>'STRING', 'default' => 'test_'), - array('short'=>'P', 'long' => 'database-prefix', - 'help' => 'Database prefix to use: tables must already exist or the script will abort!', - 'type'=>'STRING', 'default' => $CFG->prefix), - array('short'=>'c', 'long' => 'pre-cleanup', 'help' => 'Delete previously generated data'), - array('short'=>'C', 'long' => 'post-cleanup', - 'help' => 'Deletes all generated data at the end of the script (for benchmarking of generation only)'), - array('short'=>'t', 'long' => 'time-limit', - 'help' => 'Optional time limit after which to abort the generation, 0 = no limit. Default=0', - 'type'=>'SECONDS', 'default' => 0), - array('short'=>'v', 'long' => 'verbose', 'help' => 'Display extra information about the data generation'), - array('short'=>'q', 'long' => 'quiet', 'help' => 'Inhibits all outputs'), - array('short'=>'i', 'long' => 'ignore-errors', 'help' => 'Continue script execution when errors occur'), - array('short'=>'N', 'long' => 'no-data', 'help' => 'Generate nothing (used for cleaning up only)'), - array('short'=>'T', 'long' => 'tiny', 'help' => 'Generates a tiny data set (1 of each course, module, user and section)'), - array('short'=>'nc', 'long' => 'number-of-courses', - 'help' => 'The number of courses to generate. Default=1', 'type'=>'NUMBER', 'default' => 1), - array('short'=>'ns', 'long' => 'number-of-students', - 'help' => 'The number of students to generate. Default=250', 'type'=>'NUMBER', 'default' => 250), - array('short'=>'sc', 'long' => 'students-per-course', - 'help' => 'The number of students to enrol in each course. Default=20', 'type'=>'NUMBER', 'default' => 20), - array('short'=>'nsec', 'long' => 'number-of-sections', - 'help' => 'The number of sections to generate in each course. Default=10', 'type'=>'NUMBER', 'default' => 10), - array('short'=>'nmod', 'long' => 'number-of-modules', - 'help' => 'The number of modules to generate in each section. Default=10', 'type'=>'NUMBER', 'default' => 10), - array('short'=>'mods', 'long' => 'modules-list', - 'help' => 'The list of modules you want to generate', 'default' => $settings['modules-list'], 'type' => 'mod1,mod2...'), - array('short'=>'ag', 'long' => 'assignment-grades', - 'help' => 'Generate random grades for each student/assignment tuple', 'default' => true), - array('short'=>'qg', 'long' => 'quiz-grades', - 'help' => 'Generate random grades for each student/quiz tuple', 'default' => true), - array('short'=>'eg', 'long' => 'entries-per-glossary', - 'help' => 'The number of definitions to generate per glossary. Default=0', 'type'=>'NUMBER', 'default' => 1), - array('short'=>'nq', 'long' => 'questions-per-course', - 'help' => 'The number of questions to generate per course. Default=20', 'type'=>'NUMBER', 'default' => 20), - array('short'=>'qq', 'long' => 'questions-per-quiz', - 'help' => 'The number of questions to assign to each quiz. Default=5', 'type'=>'NUMBER', 'default' => 5), - array('short'=>'df', 'long' => 'discussions-per-forum', - 'help' => 'The number of discussions to generate for each forum. Default=5', 'type'=>'NUMBER', 'default' => 5), - array('short'=>'pd', 'long' => 'posts-per-discussion', - 'help' => 'The number of posts to generate for each forum discussion. Default=15', 'type'=>'NUMBER', 'default' => 15), -); - -// Building the USAGE output of the command line version -if (isset($argv) && isset($argc)) { - $help = "Moodle Data Generator. Generates Data for Moodle sites. Good for benchmarking and other tests.\n\n" - . "Usage: {$argv[0]}; [OPTION] ...\n" - . "Options:\n" - . " -h, -?, -help, --help This output\n"; - - foreach ($arguments as $arg_array) { - $equal = ''; - if (!empty($arg_array['type'])) { - $equal = "={$arg_array['type']}"; - } - - $padding1 = 5 - strlen($arg_array['short']); - $padding2 = 30 - (strlen($arg_array['long']) + strlen($equal)); - $paddingstr1 = ''; - for ($i = 0; $i < $padding1; $i++) { - $paddingstr1 .= ' '; - } - $paddingstr2 = ''; - for ($i = 0; $i < $padding2; $i++) { - $paddingstr2 .= ' '; - } - - $help .= " -{$arg_array['short']},$paddingstr1--{$arg_array['long']}$equal$paddingstr2{$arg_array['help']}\n"; - } - - $help .= "\nEmail nicolas@moodle.com for any suggestions or bug reports."; - - if ($argc == 1 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) { - echo $help; - die(); - - } else { - - $settings['eolchar'] = "\n"; - $argv = arguments($argv); - $argscount = 0; - - foreach ($arguments as $arg_array) { - $value = null; - if (in_array($arg_array['short'], array_keys($argv))) { - $value = $argv[$arg_array['short']]; - unset($argv[$arg_array['short']]); - } elseif (in_array($arg_array['long'], array_keys($argv))) { - $value = $argv[$arg_array['long']]; - unset($argv[$arg_array['long']]); - } - if (!is_null($value)) { - if (!empty($arg_array['type']) && $arg_array['type'] == 'mod1,mod2...') { - $value = explode(',', $value); - } - $settings[$arg_array['long']] = $value; - $argscount++; - } - } - - // If some params are left in argv, it means they are not supported - if ($argscount == 0 || count($argv) > 0) { - echo $help; - die(); - } - } -} - -/** - * SCRIPT SETUP - */ -set_time_limit($settings['time-limit']); -require_once($CFG->libdir . '/formslib.php'); -require_once($CFG->dirroot .'/course/lib.php'); -require_once($CFG->dirroot .'/mod/resource/lib.php'); -verbose("Loading libraries..."); -$systemcontext = get_context_instance(CONTEXT_SYSTEM); - -/** - * WEB INTERFACE FORM - */ - -class generator_form extends moodleform { - function definition() { - global $arguments, $settings; - $mform =& $this->_form; - - foreach ($arguments as $arg_array) { - $type = 'advcheckbox'; - $options = null; - $htmloptions = null; - - $label = ucfirst(str_replace('-', ' ', $arg_array['long'])); - if (!empty($arg_array['type']) && $arg_array['type'] == 'mod1,mod2...') { - $type = 'select'; - $options = $settings['modules-list']; - $htmloptions = array('multiple' => 'multiple'); - } elseif (!empty($arg_array['type'])) { - $type = 'text'; - } - - if ($arg_array['long'] == 'password' || $arg_array['long'] == 'username') { - continue; - } - - $mform->addElement($type, $arg_array['long'], $label, $options, $htmloptions); - $mform->setHelpButton($arg_array['long'], array(false, $label, false, true, false, $arg_array['help'])); - - if (isset($arg_array['default'])) { - $mform->setDefault($arg_array['long'], $arg_array['default']); - } + public $tables = array('user', 'course', 'modules', 'course_modules', 'chat', 'choice', 'context', + 'course_sections', 'data', 'forum', 'glossary', 'label', 'lesson', 'question', + 'quiz', 'resource', 'survey', 'wiki', 'workshop', 'course_categories', + 'role_capabilities', 'config_plugins', 'block', 'message', 'groups', 'block_pinned', + 'log', 'grade_items', 'forum_discussions', 'event', 'lesson_default', 'grade_categories', + 'assignment', 'role_assignments', 'block_instance', 'forum_posts'); + + public $settings = array(); + public $eolchar = '
'; + + public $starttime; + + public function __construct($settings = array(), $generate=false) { + global $CFG; + + $this->starttimer = time()+microtime(); + + $arguments = array( + array('short'=>'u', 'long'=>'username', + 'help' => 'Your moodle username', 'type'=>'STRING', 'default' => ''), + array('short'=>'pw', 'long'=>'password', + 'help' => 'Your moodle password', 'type'=>'STRING', 'default' => ''), + array('short'=>'p', 'long'=>'data_prefix', + 'help' => 'An optional prefix prepended to the unique identifiers of the generated data. Default=test_', + 'type'=>'STRING', 'default' => 'test_'), + array('short'=>'P', 'long' => 'database_prefix', + 'help' => 'Database prefix to use: tables must already exist or the script will abort!', + 'type'=>'STRING', 'default' => $CFG->prefix), + array('short'=>'c', 'long' => 'pre_cleanup', 'help' => 'Delete previously generated data'), + array('short'=>'C', 'long' => 'post_cleanup', + 'help' => 'Deletes all generated data at the end of the script (for benchmarking of generation only)'), + array('short'=>'t', 'long' => 'time_limit', + 'help' => 'Optional time limit after which to abort the generation, 0 = no limit. Default=0', + 'type'=>'SECONDS', 'default' => 0), + array('short'=>'v', 'long' => 'verbose', 'help' => 'Display extra information about the data generation'), + array('short'=>'q', 'long' => 'quiet', 'help' => 'Inhibits all outputs'), + array('short'=>'i', 'long' => 'ignore_errors', 'help' => 'Continue script execution when errors occur'), + array('short'=>'N', 'long' => 'no_data', 'help' => 'Generate nothing (used for cleaning up only)'), + array('short'=>'T', 'long' => 'tiny', + 'help' => 'Generates a tiny data set (1 of each course, module, user and section)', + 'default' => 0), + array('short'=>'nc', 'long' => 'number_of_courses', + 'help' => 'The number of courses to generate. Default=1', + 'type'=>'NUMBER', 'default' => 1), + array('short'=>'ns', 'long' => 'number_of_students', + 'help' => 'The number of students to generate. Default=250', + 'type'=>'NUMBER', 'default' => 250), + array('short'=>'sc', 'long' => 'students_per_course', + 'help' => 'The number of students to enrol in each course. Default=20', + 'type'=>'NUMBER', 'default' => 20), + array('short'=>'nsec', 'long' => 'number_of_sections', + 'help' => 'The number of sections to generate in each course. Default=10', + 'type'=>'NUMBER', 'default' => 10), + array('short'=>'nmod', 'long' => 'number_of_modules', + 'help' => 'The number of modules to generate in each section. Default=10', + 'type'=>'NUMBER', 'default' => 10), + array('short'=>'mods', 'long' => 'modules_list', + 'help' => 'The list of modules you want to generate', 'default' => $this->modules_list, + 'type' => 'mod1,mod2...'), + array('short'=>'ag', 'long' => 'assignment_grades', + 'help' => 'Generate random grades for each student/assignment tuple', 'default' => true), + array('short'=>'qg', 'long' => 'quiz_grades', + 'help' => 'Generate random grades for each student/quiz tuple', 'default' => true), + array('short'=>'eg', 'long' => 'entries_per_glossary', + 'help' => 'The number of definitions to generate per glossary. Default=0', + 'type'=>'NUMBER', 'default' => 1), + array('short'=>'nq', 'long' => 'questions_per_course', + 'help' => 'The number of questions to generate per course. Default=20', + 'type'=>'NUMBER', 'default' => 20), + array('short'=>'qq', 'long' => 'questions_per_quiz', + 'help' => 'The number of questions to assign to each quiz. Default=5', + 'type'=>'NUMBER', 'default' => 5), + array('short'=>'df', 'long' => 'discussions_per_forum', + 'help' => 'The number of discussions to generate for each forum. Default=5', + 'type'=>'NUMBER', 'default' => 5), + array('short'=>'pd', 'long' => 'posts_per_discussion', + 'help' => 'The number of posts to generate for each forum discussion. Default=15', + 'type'=>'NUMBER', 'default' => 15), + ); + foreach ($arguments as $args_array) { + $this->settings[$args_array['long']] = new generator_argument($args_array); } - $this->add_action_buttons(false, 'Generate data!'); - } - - function definition_after_data() { - - } -} - - -if (!is_null($settings['database-prefix'])) { - - $CFG->prefix = $settings['database-prefix']; - // Check that all required tables exist - - $tables = array('user', 'course', 'modules', 'course_modules', 'chat', 'choice', 'context', 'course_sections', 'data', 'forum', - 'glossary', 'label', 'lesson', 'question', 'quiz', 'resource', 'survey', 'wiki', 'workshop', 'course_categories', - 'role_capabilities', 'config_plugins', 'block', 'message', 'groups', 'block_pinned', 'log', 'grade_items', 'forum_discussions', - 'event', 'lesson_default', 'grade_categories', 'assignment', 'role_assignments', 'block_instance', 'forum_posts'); - sort($tables); - $table_errors = array(); - - foreach ($tables as $table) { - require_once($CFG->libdir . '/ddllib.php'); - $dbman = $DB->get_manager(); - $xmltable = new XMLDBTable($table); - if (!$dbman->table_exists($xmltable)) { - $table_errors[] = $settings['database-prefix'] . $table; + foreach ($settings as $setting => $value) { + $this->settings[$setting]->value = $value; } - } - if (!empty($table_errors) && !$settings['quiet']) { - if (!$settings['quiet']) { - echo "The following tables do not exist in the database:" . $settings['eolchar']; - foreach ($table_errors as $table) { - echo " $table" . $settings['eolchar']; - } - echo "Please create these tables or choose a different database prefix before running this script with these parameters again." . $settings['eolchar']; - } - if (!$settings['ignore-errors']) { - die(); + if ($generate) { + $this->generate_data(); } } -} - -// Tiny data set -if (!empty($settings['tiny'])) { - verbose("Generating a tiny data set: 1 student in 1 course with 1 module in 1 section..."); - $settings['number-of-courses'] = 1; - $settings['number-of-students'] = 1; - $settings['number-of-modules'] = 1; - $settings['number-of-sections'] = 1; - $settings['assignment-grades'] = false; - $settings['quiz-grades'] = false; - $settings['students-per-course'] = 1; - $settings['questions-per-course'] = 1; - $settings['questions-per-quiz'] = 1; -} - -$run_script = true; -$web_interface = false; -// If eolchar is still
, load the web interface -if ($settings['eolchar'] == '
') { - print_header("Data generator"); - print_heading("Data generator: web interface"); - $mform = new generator_form(); + public function generate_users() { + global $DB, $CFG; - if ($data = $mform->get_data(false)) { - foreach ($arguments as $arg_array) { - if (!empty($data->{$arg_array['long']})) { - $settings[$arg_array['long']] = $data->{$arg_array['long']}; - } - } - } else { - $run_script = false; - } - - if (!has_capability('moodle/site:doanything', $systemcontext)) { - // If not logged in, give link to login page for current site - notify("You must be logged in as administrator before using this script."); - require_login(); - } else { - $mform->display(); - } - - $web_interface = true; -} - -if ($run_script) { - - // User authentication - if (!$web_interface) { - if (empty($settings['username'])) { - echo "You must enter a valid username for a moodle administrator account on this site.{$settings['eolchar']}"; - die(); - } elseif (empty($settings['password'])) { - echo "You must enter a valid password for a moodle administrator account on this site.{$settings['eolchar']}"; - die(); - } else { - if (!$user = authenticate_user_login($settings['username'], $settings['password'])) { - echo "Invalid username or password!{$settings['eolchar']}"; - die(); - } - $USER = complete_user_login($user); - if (!has_capability('moodle/site:doanything', $systemcontext)) { - echo "You do not have administration privileges on this Moodle site. These are required for running the generation script.{$settings['eolchar']}"; - die(); - } - } - } - - /** - * DELETE PREVIOUS TEST DATA - */ - if ($settings['pre-cleanup']) { - verbose("Deleting previous test data..."); - - data_cleanup(); - - if (!$settings['quiet']) { - echo "Previous test data has been deleted.{$settings['eolchar']}"; - } - } - - if (!$settings['no-data']) { /** * USER GENERATION */ - verbose("Generating {$settings['number-of-students']} students..."); - $lastnames = array('SMITH', 'JOHNSON', 'WILLIAMS', 'JONES', 'BROWN', 'DAVIS', 'MILLER', 'WILSON', 'MOORE', 'TAYLOR', 'ANDERSON', 'THOMAS', 'JACKSON', 'WHITE', - 'HARRIS', 'MARTIN', 'THOMPSON', 'GARCIA', 'MARTINEZ', 'ROBINSON', 'CLARK', 'RODRIGUEZ', 'LEWIS', 'LEE', 'WALKER', 'HALL', 'ALLEN', - 'YOUNG', 'HERNANDEZ', 'KING', 'WRIGHT', 'LOPEZ', 'HILL', 'SCOTT', 'GREEN', 'ADAMS', 'BAKER', 'GONZALEZ', 'NELSON', 'CARTER', - 'MITCHELL', 'PEREZ', 'ROBERTS', 'TURNER', 'PHILLIPS', 'CAMPBELL', 'PARKER', 'EVANS', 'EDWARDS', 'COLLINS', 'STEWART', 'SANCHEZ', 'MORRIS', - 'ROGERS', 'REED', 'COOK', 'MORGAN', 'BELL', 'MURPHY', 'BAILEY', 'RIVERA', 'COOPER', 'RICHARDSON', 'COX', 'HOWARD', 'WARD', - 'TORRES', 'PETERSON', 'GRAY', 'RAMIREZ', 'JAMES', 'WATSON', 'BROOKS', 'KELLY', 'SANDERS', 'PRICE', 'BENNETT', 'WOOD', 'BARNES', - 'ROSS', 'HENDERSON', 'COLEMAN', 'JENKINS', 'PERRY', 'POWELL', 'LONG', 'PATTERSON', 'HUGHES', 'FLORES', 'WASHINGTON', 'BUTLER', - 'SIMMONS', 'FOSTER', 'GONZALES', 'BRYANT', 'ALEXANDER', 'RUSSELL', 'GRIFFIN', 'DIAZ', 'HAYES', 'MYERS', 'FORD', 'HAMILTON', 'GRAHAM', - 'SULLIVAN', 'WALLACE', 'WOODS', 'COLE', 'WEST', 'JORDAN', 'OWENS', 'REYNOLDS', 'FISHER', 'ELLIS', 'HARRISON', 'GIBSON', 'MCDONALD', - 'CRUZ', 'MARSHALL', 'ORTIZ', 'GOMEZ', 'MURRAY', 'FREEMAN', 'WELLS', 'WEBB', 'SIMPSON', 'STEVENS', 'TUCKER', 'PORTER', 'HUNTER', - 'HICKS', 'CRAWFORD', 'HENRY', 'BOYD', 'MASON', 'MORALES', 'KENNEDY', 'WARREN', 'DIXON', 'RAMOS', 'REYES', 'BURNS', 'GORDON', 'SHAW', - 'HOLMES', 'RICE', 'ROBERTSON', 'HUNT', 'BLACK', 'DANIELS', 'PALMER', 'MILLS', 'NICHOLS', 'GRANT', 'KNIGHT', 'FERGUSON', 'ROSE', - 'STONE', 'HAWKINS', 'DUNN', 'PERKINS', 'HUDSON', 'SPENCER', 'GARDNER', 'STEPHENS', 'PAYNE', 'PIERCE', 'BERRY', 'MATTHEWS', 'ARNOLD', - 'WAGNER', 'WILLIS', 'RAY', 'WATKINS', 'OLSON', 'CARROLL', 'DUNCAN', 'SNYDER', 'HART', 'CUNNINGHAM', 'BRADLEY', 'LANE', 'ANDREWS', - 'RUIZ', 'HARPER', 'FOX', 'RILEY', 'ARMSTRONG', 'CARPENTER', 'WEAVER', 'GREENE', 'LAWRENCE', 'ELLIOTT', 'CHAVEZ', 'SIMS', 'AUSTIN', - 'PETERS', 'KELLEY', 'FRANKLIN', 'LAWSON', 'FIELDS', 'GUTIERREZ', 'RYAN', 'SCHMIDT', 'CARR', 'VASQUEZ', 'CASTILLO', 'WHEELER', 'CHAPMAN', - 'OLIVER', 'MONTGOMERY', 'RICHARDS', 'WILLIAMSON', 'JOHNSTON', 'BANKS', 'MEYER', 'BISHOP', 'MCCOY', 'HOWELL', 'ALVAREZ', 'MORRISON', - 'HANSEN', 'FERNANDEZ', 'GARZA', 'HARVEY', 'LITTLE', 'BURTON', 'STANLEY', 'NGUYEN', 'GEORGE', 'JACOBS', 'REID', 'KIM', 'FULLER', 'LYNCH', - 'DEAN', 'GILBERT', 'GARRETT', 'ROMERO', 'WELCH', 'LARSON', 'FRAZIER', 'BURKE', 'HANSON', 'DAY', 'MENDOZA', 'MORENO', 'BOWMAN', 'MEDINA', - 'FOWLER'); - - $firstnames = array( 'JAMES', 'JOHN', 'ROBERT', 'MARY', 'MICHAEL ', 'WILLIAM', 'DAVID', 'RICHARD', 'CHARLES', 'JOSEPH ', 'THOMAS', 'PATRICIA', - 'LINDA', 'CHRISTOPHER', 'BARBARA ', 'DANIEL', 'PAUL', 'MARK', 'ELIZABETH', 'JENNIFER ', 'DONALD', 'GEORGE', 'MARIA', - 'KENNETH', 'SUSAN ', 'STEVEN', 'EDWARD', 'MARGARET', 'BRIAN', 'DOROTHY ', 'RONALD', 'ANTHONY', 'LISA', 'KEVIN', 'NANCY ', - 'KAREN', 'BETTY', 'HELEN', 'JASON', 'MATTHEW ', 'GARY', 'TIMOTHY', 'SANDRA', 'JOSE', 'LARRY ', 'JEFFREY', 'DONNA', 'FRANK', - 'CAROL', 'RUTH ', 'SCOTT', 'ERIC', 'STEPHEN', 'ANDREW', 'SHARON ', 'MICHELLE', 'LAURA', 'SARAH', 'KIMBERLY', 'DEBORAH ', - 'JESSICA', 'RAYMOND', 'SHIRLEY', 'CYNTHIA', 'ANGELA ', 'MELISSA', 'BRENDA', 'AMY', 'GREGORY', 'ANNA ', 'JOSHUA', 'JERRY', - 'REBECCA', 'VIRGINIA', 'KATHLEEN', 'PAMELA', 'DENNIS', 'MARTHA', 'DEBRA', 'AMANDA', 'STEPHANIE', 'WALTER', 'PATRICK', - 'CAROLYN', 'CHRISTINE', 'PETER', 'MARIE', 'JANET', 'CATHERINE', 'HAROLD', 'FRANCES', 'DOUGLAS', 'HENRY', 'ANN', 'JOYCE', - 'DIANE', 'ALICE', 'JULIE', 'CARL', 'HEATHER'); + $this->verbose("Generating ".$this->get('number_of_students')." students..."); + $lastnames = array('SMITH','JOHNSON','WILLIAMS','JONES','BROWN','DAVIS','MILLER','WILSON', + 'MOORE','TAYLOR','ANDERSON','THOMAS','JACKSON','WHITE','HARRIS','MARTIN','THOMPSON', + 'GARCIA','MARTINEZ','ROBINSON','CLARK','RODRIGUEZ','LEWIS','LEE','WALKER','HALL', + 'ALLEN','YOUNG','HERNANDEZ','KING','WRIGHT','LOPEZ','HILL','SCOTT','GREEN','ADAMS', + 'BAKER','GONZALEZ','NELSON','CARTER','MITCHELL','PEREZ','ROBERTS','TURNER','PHILLIPS', + 'CAMPBELL','PARKER','EVANS','EDWARDS','COLLINS','STEWART','SANCHEZ','MORRIS','ROGERS', + 'REED','COOK','MORGAN','BELL','MURPHY','BAILEY','RIVERA','COOPER','RICHARDSON','COX', + 'HOWARD','WARD','TORRES','PETERSON','GRAY','RAMIREZ','JAMES','WATSON','BROOKS','KELLY', + 'SANDERS','PRICE','BENNETT','WOOD','BARNES','ROSS','HENDERSON','COLEMAN','JENKINS','PERRY', + 'POWELL','LONG','PATTERSON','HUGHES','FLORES','WASHINGTON','BUTLER','SIMMONS','FOSTER', + 'GONZALES','BRYANT','ALEXANDER','RUSSELL','GRIFFIN','DIAZ','HAYES','MYERS','FORD','HAMILTON', + 'GRAHAM','SULLIVAN','WALLACE','WOODS','COLE','WEST','JORDAN','OWENS','REYNOLDS','FISHER', + 'ELLIS','HARRISON','GIBSON','MCDONALD','CRUZ','MARSHALL','ORTIZ','GOMEZ','MURRAY','FREEMAN', + 'WELLS','WEBB','SIMPSON','STEVENS','TUCKER','PORTER','HUNTER','HICKS','CRAWFORD','HENRY', + 'BOYD','MASON','MORALES','KENNEDY','WARREN','DIXON','RAMOS','REYES','BURNS','GORDON','SHAW', + 'HOLMES','RICE','ROBERTSON','HUNT','BLACK','DANIELS','PALMER','MILLS','NICHOLS','GRANT', + 'KNIGHT','FERGUSON','ROSE','STONE','HAWKINS','DUNN','PERKINS','HUDSON','SPENCER','GARDNER', + 'STEPHENS','PAYNE','PIERCE','BERRY','MATTHEWS','ARNOLD','WAGNER','WILLIS','RAY','WATKINS', + 'OLSON','CARROLL','DUNCAN','SNYDER','HART','CUNNINGHAM','BRADLEY','LANE','ANDREWS','RUIZ', + 'HARPER','FOX','RILEY','ARMSTRONG','CARPENTER','WEAVER','GREENE','LAWRENCE','ELLIOTT','CHAVEZ', + 'SIMS','AUSTIN','PETERS','KELLEY','FRANKLIN','LAWSON','FIELDS','GUTIERREZ','RYAN','SCHMIDT', + 'CARR','VASQUEZ','CASTILLO','WHEELER','CHAPMAN','OLIVER','MONTGOMERY','RICHARDS','WILLIAMSON', + 'JOHNSTON','BANKS','MEYER','BISHOP','MCCOY','HOWELL','ALVAREZ','MORRISON','HANSEN','FERNANDEZ', + 'GARZA','HARVEY','LITTLE','BURTON','STANLEY','NGUYEN','GEORGE','JACOBS','REID','KIM','FULLER', + 'LYNCH','DEAN','GILBERT','GARRETT','ROMERO','WELCH','LARSON','FRAZIER','BURKE','HANSON','DAY', + 'MENDOZA','MORENO','BOWMAN','MEDINA','FOWLER'); + $firstnames = array( 'JAMES','JOHN','ROBERT','MARY','MICHAEL','WILLIAM','DAVID','RICHARD', + 'CHARLES','JOSEPH','THOMAS','PATRICIA','LINDA','CHRISTOPHER','BARBARA','DANIEL','PAUL', + 'MARK','ELIZABETH','JENNIFER','DONALD','GEORGE','MARIA','KENNETH','SUSAN','STEVEN','EDWARD', + 'MARGARET','BRIAN','DOROTHY','RONALD','ANTHONY','LISA','KEVIN','NANCY','KAREN','BETTY', + 'HELEN','JASON','MATTHEW','GARY','TIMOTHY','SANDRA','JOSE','LARRY','JEFFREY','DONNA', + 'FRANK','CAROL','RUTH','SCOTT','ERIC','STEPHEN','ANDREW','SHARON','MICHELLE','LAURA', + 'SARAH','KIMBERLY','DEBORAH','JESSICA','RAYMOND','SHIRLEY','CYNTHIA','ANGELA','MELISSA', + 'BRENDA','AMY','GREGORY','ANNA','JOSHUA','JERRY','REBECCA','VIRGINIA','KATHLEEN','PAMELA', + 'DENNIS','MARTHA','DEBRA','AMANDA','STEPHANIE','WALTER','PATRICK','CAROLYN','CHRISTINE', + 'PETER','MARIE','JANET','CATHERINE','HAROLD','FRANCES','DOUGLAS','HENRY','ANN','JOYCE', + 'DIANE','ALICE','JULIE','CARL','HEATHER'); $users_count = 0; $users = array(); @@ -373,14 +164,16 @@ function definition_after_data() { shuffle($firstnames); $next_user_id = $DB->get_field_sql("SELECT MAX(id) FROM {user}") + 1; - for ($i = 0; $i < $settings['number-of-students']; $i++) { + + for ($i = 0; $i < $this->get('number_of_students'); $i++) { $lastname = trim(ucfirst(strtolower($lastnames[rand(0, count($lastnames) - 1)]))); $firstname = $firstnames[rand(0, count($firstnames) - 1)]; $user = new stdClass(); $user->firstname = trim(ucfirst(strtolower($firstname))); - $user->username = $settings['data-prefix'] . strtolower(substr($firstname, 0, 7) . substr($lastname, 0, 7)) . $next_user_id++; + $user->username = $this->get('data_prefix') . strtolower(substr($firstname, 0, 7) + . substr($lastname, 0, 7)) . $next_user_id++; $user->lastname = $lastname; $user->email = $user->username . '@example.com'; $user->mnethostid = 1; @@ -393,26 +186,29 @@ function definition_after_data() { $user->timemodified= time(); if (!$user->id = $DB->insert_record("user", $user)) { - verbose("Error inserting a user in the database! Aborting the script!"); - if (!$settings['ignore-errors']) { + $this->verbose("Error inserting a user in the database! Aborting the script!"); + if (!$this->get('ignore_errors')) { die(); } } else { $users_count++; $users[] = $user->id; $next_user_id = $user->id + 1; - verbose("Inserted $user->firstname $user->lastname into DB (username=$user->username, password=password)."); + $this->verbose("Inserted $user->firstname $user->lastname into DB " + ."(username=$user->username, password=password)."); } } - if (!$settings['quiet']) { - echo "$users_count users correctly inserted in the database.{$settings['eolchar']}"; + if (!$this->get('quiet')) { + echo "$users_count users correctly inserted in the database.{$this->eolchar}"; } + return $users; + } - /** - * COURSE GENERATION - */ - verbose("Generating {$settings['number-of-courses']} courses..."); + public function generate_courses() { + global $DB; + + $this->verbose("Generating {$this->get('number_of_courses')} courses..."); $base_course = new stdClass(); $next_course_id = $DB->get_field_sql("SELECT MAX(id) FROM {course}") + 1; @@ -426,15 +222,15 @@ function definition_after_data() { $courses_count = 0; $courses = array(); - for ($i = 1; $i <= $settings['number-of-courses']; $i++) { + for ($i = 1; $i <= $this->get('number_of_courses'); $i++) { $newcourse = fullclone($base_course); $newcourse->fullname = "Test course $next_course_id"; $newcourse->shortname = "Test $next_course_id"; - $newcourse->idnumber = $settings['data-prefix'] . $next_course_id; + $newcourse->idnumber = $this->get('data_prefix') . $next_course_id; if (!$course = create_course($newcourse)) { - verbose("Error inserting a new course in the database!"); - if (!$settings['ignore-errors']) { + $this->verbose("Error inserting a new course in the database!"); + if (!$this->get('ignore_errors')) { die(); } } else { @@ -442,28 +238,30 @@ function definition_after_data() { $next_course_id++; $courses[] = $course->id; $next_course_id = $course->id + 1; - verbose("Inserted $course->fullname into DB (idnumber=$course->idnumber)."); + $this->verbose("Inserted $course->fullname into DB (idnumber=$course->idnumber)."); } } - if (!$settings['quiet']) { - echo "$courses_count test courses correctly inserted into the database.{$settings['eolchar']}"; + if (!$this->get('quiet')) { + echo "$courses_count test courses correctly inserted into the database.{$this->eolchar}"; } + return $courses; + } - /** - * MODULES GENERATION - */ - + public function generate_modules($courses) { + global $DB, $CFG; // Parse the modules-list variable - verbose("Generating {$settings['number-of-sections']} sections with {$settings['number-of-modules']} modules in each section, for each course..."); + $this->verbose("Generating " . $this->get('number_of_sections')." sections with " + .$this->get('number_of_modules')." modules in each section, for each course..."); $modules = $DB->get_records('modules'); foreach ($modules as $key => $module) { $module->count = 0; // Scorm, lams and hotpot are too complex to set up, remove them - if (in_array($module->name, $settings['modules-to-ignore']) || !in_array($module->name, $settings['modules-list'])) { + if (in_array($module->name, $this->modules_to_ignore) || + !in_array($module->name, $this->modules_list)) { unset($modules[$key]); } } @@ -474,27 +272,27 @@ function definition_after_data() { array_unshift($modules, $first_module); $resource_types = array('text', 'file', 'html', 'repository', 'directory', 'ims'); - $glossary_formats = array('continuous', 'encyclopedia', 'entrylist', 'faq', 'fullwithauthor', 'fullwithoutauthor', 'dictionary'); + $glossary_formats = array('continuous', 'encyclopedia', 'entrylist', 'faq', 'fullwithauthor', + 'fullwithoutauthor', 'dictionary'); $assignment_types = array('upload', 'uploadsingle', 'online', 'offline'); $forum_types = array('single', 'eachuser', 'qanda', 'general'); - $quizzes = array(); - $assignments = array(); - $glossaries = array(); - $forums = array(); + $modules_array = array(); if (count($courses) > 0) { $libraries = array(); foreach ($courses as $courseid) { // Text resources - for ($i = 1; $i <= $settings['number-of-sections']; $i++) { - for ($j = 0; $j < $settings['number-of-modules']; $j++) { + for ($i = 1; $i <= $this->get('number_of_sections'); $i++) { + for ($j = 0; $j < $this->get('number_of_modules'); $j++) { $module = new stdClass(); // If only one module is created, and we also need to add a question to a quiz, create only a quiz - if ($settings['number-of-modules'] == 1 && $settings['questions-per-quiz'] > 0 && !empty($modules[8])) { + if ($this->get('number_of_modules') == 1 + && $this->get('questions_per_quiz') > 0 + && !empty($modules[8])) { $moduledata = $modules[8]; } else { $moduledata = $modules[array_rand($modules)]; @@ -503,20 +301,22 @@ function definition_after_data() { $libfile = "$CFG->dirroot/mod/$moduledata->name/lib.php"; if (file_exists($libfile)) { if (!in_array($libfile, $libraries)) { - verbose("Including library for $moduledata->name..."); + $this->verbose("Including library for $moduledata->name..."); $libraries[] = $libfile; require_once($libfile); } } else { - verbose("Could not load lib file for module $moduledata->name!"); - if (!$settings['ignore-errors']) { + $this->verbose("Could not load lib file for module $moduledata->name!"); + if (!$this->get('ignore_errors')) { die(); } } // Basically 2 types of text fields: description and content - $description = "This $moduledata->name has been randomly generated by a very useful script, for the purpose of testing " - . "the boundaries of Moodle in various contexts. Moodle should be able to scale to any size without " + $description = "This $moduledata->name has been randomly generated by a very useful script, " + . "for the purpose of testing " + . "the boundaries of Moodle in various contexts. Moodle should be able to scale to " + . "any size without " . "its speed and ease of use being affected dramatically."; $content = 'Very useful content, I am sure you would agree'; @@ -634,7 +434,7 @@ function definition_after_data() { break; } - $module->name = $settings['data-prefix'] . ucfirst($moduledata->name) . ' ' . $moduledata->count++; + $module->name = $this->get('data_prefix') . ucfirst($moduledata->name) . ' ' . $moduledata->count++; $module->course = $courseid; $module->section = $i; @@ -647,8 +447,8 @@ function definition_after_data() { if (function_exists($add_instance_function)) { $module->instance = $add_instance_function($module, ''); } else { - verbose("Function $add_instance_function does not exist!"); - if (!$settings['ignore-errors']) { + $this->verbose("Function $add_instance_function does not exist!"); + if (!$this->get('ignore_errors')) { die(); } } @@ -662,46 +462,37 @@ function definition_after_data() { $module->cmidnumber = set_coursemodule_idnumber($module->coursemodule, ''); - verbose("A $moduledata->name module was added to section $i (id $module->section) of course $courseid."); + $this->verbose("A $moduledata->name module was added to section $i (id $module->section) " + ."of course $courseid."); rebuild_course_cache($courseid); - if ($moduledata->name == 'quiz') { - $quiz_instance = $DB->get_field('course_modules', 'instance', array('id' => $module->coursemodule)); - $quiz = $DB->get_record('quiz', array('id' => $quiz_instance)); - $quiz->instance = $quiz_instance; - $quizzes[] = $quiz; - } elseif ($moduledata->name == 'assignment') { - $assignment_instance = $DB->get_field('course_modules', 'instance', - array('id' => $module->coursemodule)); - $assignment = $DB->get_record('assignment', array('id' => $assignment_instance)); - $assignment->instance = $assignment_instance; - $assignments[] = $assignment; - } elseif ($moduledata->name == 'glossary') { - $glossary_instance = $DB->get_field('course_modules', 'instance', - array('id' => $module->coursemodule)); - $glossary = $DB->get_record('glossary', array('id' => $glossary_instance)); - $glossary->instance = $glossary_instance; - $glossaries[] = $glossary; - } elseif ($moduledata->name == 'forum') { - $forum_instance = $DB->get_field('course_modules', 'instance', - array('id' => $module->coursemodule)); - $forum = $DB->get_record('forum', array('id' => $forum_instance)); - $forum->instance = $forum_instance; - $forums[] = $forum; + $module_instance = $DB->get_field('course_modules', 'instance', array('id' => $module->coursemodule)); + $module_record = $DB->get_record($moduledata->name, array('id' => $module_instance)); + $module_record->instance = $module_instance; + + if (empty($modules_array[$moduledata->name])) { + $modules_array[$moduledata->name] = array(); } + + $modules_array[$moduledata->name][] = $module_record; } } } - if (!$settings['quiet']) { - echo "Successfully generated " . $settings['number-of-modules'] * $settings['number-of-sections'] . " modules in each course!{$settings['eolchar']}"; + if (!$this->get('quiet')) { + echo "Successfully generated " . $this->get('number_of_modules') * $this->get('number_of_sections') + . " modules in each course!{$this->eolchar}"; } + + return $modules_array; } + return null; + } - /** - * QUESTIONS GENERATION - */ - if (!empty($settings['questions-per-course'])) { + public function generate_questions($courses, $modules) { + global $DB, $CFG; + + if (!is_null($this->get('questions_per_course')) && count($courses) > 0 && is_array($courses)) { require_once($CFG->libdir .'/questionlib.php'); require_once($CFG->dirroot .'/mod/quiz/editlib.php'); $questions = array(); @@ -714,11 +505,12 @@ function definition_after_data() { // Add the questions foreach ($courses as $courseid) { $questions[$courseid] = array(); - for ($i = 0; $i < $settings['questions-per-course']; $i++) { + for ($i = 0; $i < $this->get('questions_per_course'); $i++) { $qtype = $questiontypes[array_rand($questiontypes)]; // Only the following types are supported right now. Hang around for more! - $supported_types = array('match', 'essay', 'multianswer', 'multichoice', 'shortanswer', 'numerical', 'truefalse', 'calculated'); + $supported_types = array('match', 'essay', 'multianswer', 'multichoice', 'shortanswer', + 'numerical', 'truefalse', 'calculated'); $qtype = $supported_types[array_rand($supported_types)]; if ($qtype == 'calculated') { @@ -732,14 +524,16 @@ function definition_after_data() { $question = new $classname(); $question->qtype = $qtype; $questions[$courseid][] = $question->generate_test("question$qtype-$i", $courseid); - verbose("Generated a question of type $qtype for course id $courseid."); + $this->verbose("Generated a question of type $qtype for course id $courseid."); } } // Assign questions to quizzes, if such exist - if (!empty($quizzes) && !empty($questions) && !empty($settings['questions-per-quiz'])) { + if (!empty($modules['quiz']) && !empty($questions) && !is_null($this->get('questions_per_quiz'))) { + $quizzes = $modules['quiz']; + // Cannot assign more questions per quiz than are available, so determine which is the largest - $questions_per_quiz = max(count($questions), $settings['questions-per-quiz']); + $questions_per_quiz = max(count($questions), $this->get('questions_per_quiz')); foreach ($quizzes as $quiz) { $questions_added = array(); @@ -753,22 +547,25 @@ function definition_after_data() { if (!quiz_add_quiz_question($questions[$quiz->course][$random]->id, $quiz)) { // Could not add question to quiz!! report error - echo "WARNING: Could not add question id $random to quiz id $quiz->id{$settings['eolchar']}"; + echo "WARNING: Could not add question id $random to quiz id $quiz->id{$this->eolchar}"; } else { - verbose("Adding question id $random to quiz id $quiz->id."); + $this->verbose("Adding question id $random to quiz id $quiz->id."); $questions_added[] = $random; } } } } + return $questions; } + return null; + } - /** - * ROLE ASSIGNMENTS - */ + public function generate_role_assignments($users, $courses) { + global $CFG, $DB; $course_users = array(); + if (count($courses) > 0) { - verbose("Inserting student->course role assignments..."); + $this->verbose("Inserting student->course role assignments..."); $assigned_count = 0; $assigned_users = array(); @@ -777,7 +574,7 @@ function definition_after_data() { // Select $students_per_course for assignment to course shuffle($users); - $users_to_assign = array_slice($users, 0, $settings['students-per-course']); + $users_to_assign = array_slice($users, 0, $this->get('students_per_course')); foreach ($users_to_assign as $random_user) { @@ -799,35 +596,39 @@ function definition_after_data() { } else { $assigned_users[$random_user]++; } - verbose("Student $random_user was assigned to course $courseid."); + $this->verbose("Student $random_user was assigned to course $courseid."); } else { - verbose("Could not assign student $random_user to course $courseid!"); - if (!$settings['ignore-errors']) { + $this->verbose("Could not assign student $random_user to course $courseid!"); + if (!$this->get('ignore_errors')) { die(); } } } } - if (!$settings['quiet']) { - echo "$assigned_count user => course role assignments have been correctly performed.{$settings['eolchar']}"; + if (!$this->get('quiet')) { + echo "$assigned_count user => course role assignments have been correctly performed.{$this->eolchar}"; } + return $course_users; } + return null; + } - /** - * FORUM DISCUSSIONS AND POSTS GENERATION - */ - if (in_array('forum', $settings['modules-list']) && - $settings['discussions-per-forum'] && - $settings['posts-per-discussion']) { + public function generate_forum_posts($course_users, $modules) { + global $CFG, $DB, $USER; + + if (in_array('forum', $this->modules_list) && + $this->get('discussions_per_forum') && + $this->get('posts_per_discussion') && + isset($modules['forum'])) { $discussions_count = 0; $posts_count = 0; - foreach ($forums as $forum) { + foreach ($modules['forum'] as $forum) { $forum_users = $course_users[$forum->course]; - for ($i = 0; $i < $settings['discussions-per-forum']; $i++) { + for ($i = 0; $i < $this->get('discussions_per_forum'); $i++) { $mform = new fake_form(); require_once($CFG->dirroot.'/mod/forum/lib.php'); @@ -852,7 +653,7 @@ function definition_after_data() { // Add posts to this discussion $post_ids = array($discussion->firstpost); - for ($j = 0; $j < $settings['posts-per-discussion']; $j++) { + for ($j = 0; $j < $this->get('posts_per_discussion'); $j++) { $global_user = clone($USER); $user_id = $forum_users[array_rand($forum_users)]; $USER = $DB->get_record('user', array('id' => $user_id)); @@ -877,21 +678,29 @@ function definition_after_data() { } } } - if ($discussions_count > 0) { - echo "$discussions_count forum discussions have been generated.{$settings['eolchar']}"; + if ($discussions_count > 0 && !$this->get('quiet')) { + echo "$discussions_count forum discussions have been generated.{$this->eolchar}"; } - if ($posts_count > 0) { - echo "$posts_count forum posts have been generated.{$settings['eolchar']}"; + if ($posts_count > 0 && !$this->get('quiet')) { + echo "$posts_count forum posts have been generated.{$this->eolchar}"; } + + return true; } + return null; + + } + + public function generate_grades($course_users, $courses, $modules) { + global $CFG, $DB; /** * ASSIGNMENT GRADES GENERATION */ - if ($settings['assignment-grades']) { + if ($this->get('assignment_grades')) { $grades_count = 0; foreach ($course_users as $userid => $courses) { - foreach ($assignments as $assignment) { + foreach ($modules['assignment'] as $assignment) { if (in_array($assignment->course, $courses)) { $maxgrade = $assignment->grade; $random_grade = rand(0, $maxgrade); @@ -903,23 +712,23 @@ function definition_after_data() { $grade->teacher = $USER->id; $DB->insert_record('assignment_submissions', $grade); grade_update('mod/assignment', $courseid, 'mod', 'assignment', $assignment->id, 0, $grade); - verbose("A grade ($random_grade) has been given to user $userid for assignment $assignment->id"); + $this->verbose("A grade ($random_grade) has been given to user $userid for assignment $assignment->id"); $grades_count++; } } } if ($grades_count > 0) { - echo "$grades_count assignment grades have been generated.{$settings['eolchar']}"; + echo "$grades_count assignment grades have been generated.{$this->eolchar}"; } } /** * QUIZ GRADES GENERATION */ - if ($settings['quiz-grades']) { + if ($this->get('quiz_grades')) { $grades_count = 0; foreach ($course_users as $userid => $courses) { - foreach ($quizzes as $quiz) { + foreach ($modules['quiz'] as $quiz) { if (in_array($quiz->course, $courses)) { $maxgrade = $quiz->grade; $random_grade = rand(0, $maxgrade); @@ -930,23 +739,25 @@ function definition_after_data() { $grade->rawgrade = $random_grade; $DB->insert_record('quiz_grades', $grade); grade_update('mod/quiz', $courseid, 'mod', 'quiz', $quiz->id, 0, $grade); - verbose("A grade ($random_grade) has been given to user $userid for quiz $quiz->id"); + $this->verbose("A grade ($random_grade) has been given to user $userid for quiz $quiz->id"); $grades_count++; } } } if ($grades_count > 0) { - echo "$grades_count quiz grades have been generated.{$settings['eolchar']}"; + echo "$grades_count quiz grades have been generated.{$this->eolchar}"; } } + return null; + } + + public function generate_module_content($course_users, $courses, $modules) { + global $USER, $DB, $CFG; - /** - * GLOSSARY ENTRIES GENERATION - */ $entries_count = 0; - if ($settings['entries-per-glossary']) { - foreach ($glossaries as $glossary) { - for ($i = 0; $i < $settings['entries-per-glossary']; $i++) { + if ($this->get('entries_per_glossary') && !empty($modules['glossary'])) { + foreach ($modules['glossary'] as $glossary) { + for ($i = 0; $i < $this->get('entries_per_glossary'); $i++) { $entry = new stdClass(); $entry->glossaryid = $glossary->id; $entry->userid = $USER->id; @@ -962,128 +773,423 @@ function definition_after_data() { } } } - if ($entries_count > 0) { - echo "$entries_count glossary definitions have been generated.{$settings['eolchar']}"; + if ($entries_count > 0 && !$this->get('quiet')) { + echo "$entries_count glossary definitions have been generated.{$this->eolchar}"; } + return true; } - + return null; } /** - * POST-GENERATION CLEANUP + * If an alternate DB prefix was given, we need to check that the appropriate tables + * exist. */ - if ($settings['post-cleanup']) { - if (!$settings['quiet']) { - echo "Removing generated data..." . $settings['eolchar']; + public function check_test_tables() { + global $CFG; + + sort($this->tables); + $CFG->prefix = $this->get('database_prefix'); + // Check that all required tables exist + + $table_errors = array(); + + foreach ($this->tables as $table) { + require_once($CFG->libdir . '/ddllib.php'); + $dbman = $DB->get_manager(); + $xmltable = new XMLDBTable($table); + if (!$dbman->table_exists($xmltable)) { + $table_errors[] = $this->get('database_prefix') . $table; + } } - data_cleanup(); - if (!$settings['quiet']) { - echo "Generated data has been deleted." . $settings['eolchar']; + + if (!empty($table_errors) && !$this->get('quiet')) { + if (!$this->get('quiet')) { + echo "The following tables do not exist in the database:" . $this->eolchar; + foreach ($table_errors as $table) { + echo " $table" . $this->eolchar; + } + echo "Please create these tables or choose a different database prefix before running " + ."this script with these parameters again." . $this->eolchar; + } + if (!$this->get('ignore_errors')) { + die(); + } } + } /** - * FINISHING SCRIPT + * If verbose is switched on, prints a string terminated by the global eolchar string. + * @param string $string The string to STDOUT */ - $stoptimer = time()+microtime(); - $timer = round($stoptimer-$starttimer,4); - if (!$settings['quiet']) { - echo "End of script! ($timer seconds taken){$settings['eolchar']}"; + public function verbose($string) { + if ($this->get('verbose') && !$this->get('quiet')) { + echo $string . $this->eolchar; + } } -} -if ($settings['eolchar'] == '
') { - print_footer(); -} -/** - * Converts the standard $argv into an associative array taking var=val arguments into account - * @param array $argv - * @return array $_ARG - */ -function arguments($argv) { - $_ARG = array(); - foreach ($argv as $arg) { - if (ereg('--?([^=]+)=(.*)',$arg,$reg)) { - $_ARG[$reg[1]] = $reg[2]; - } elseif(ereg('-([a-zA-Z0-9]+)',$arg,$reg)) { - $_ARG[$reg[1]] = 'true'; + /** + * Attempts to delete all generated test data. A few conditions are required for this to be successful: + * 1. If a database-prefix has been given, tables with this prefix must exist + * 2. If a data prefix has been given (e.g. test_), test data must contain this prefix in their unique identifiers (not PKs) + * The first method is safest, because it will not interfere with existing tables, but you have to create all the tables yourself. + */ + function data_cleanup() { + global $DB; + + if ($this->get('quiet')) { + ob_start(); + } + + // Truncate test tables if a specific db prefix was given + if (!is_null($this->get('database_prefix')) && isset($tables)) { + foreach ($tables as $table_name) { + // Don't empty a few tables + if (!in_array($table_name, array('modules', 'block'))) { + if ($DB->delete_records($table_name)) { + $this->verbose("Truncated table $table_name"); + } else { + $this->verbose("Could not truncate table $table_name"); + if (!$this->get('ignore_errors')) { + die(); + } + } + } + } + + } else { // Delete records in normal tables if no specific db prefix was given + $courses = $DB->get_records_select('course', "idnumber LIKE ?", + array($this->get('data_prefix').'%'), null, 'id'); + + if (is_array($courses) && count($courses) > 0) { + foreach ($courses as $course) { + if (!delete_course($course->id, false)) { + $this->verbose("Could not delete course $course->id or some of " + ."its associated records from the database."); + if (!$this->get('ignore_errors')) { + die(); + } + } else { + $this->verbose("Deleted course $course->id and all associated records from the database."); + } + } + } + + $this->verbose("Deleting test users (permanently)..."); + if (!$DB->delete_records_select('user', "username LIKE ?", array($this->get('data_prefix').'%'))) { + $this->verbose("Error deleting users from the database"); + if (!$this->get('ignore_errors')) { + die(); + } + } + } + + if ($this->get('quiet')) { + ob_end_clean(); + } + } + + public function generate_data() { + set_time_limit($this->get('time_limit')); + + // Process tiny data set + $tiny = $this->get('tiny'); + if (!empty($tiny)) { + $this->verbose("Generating a tiny data set: 1 student in 1 course with 1 module in 1 section..."); + $this->set('number_of_courses',1); + $this->set('number_of_students',1); + $this->set('number_of_modules',1); + $this->set('number_of_sections',1); + $this->set('assignment_grades',false); + $this->set('quiz_grades',false); + $this->set('students_per_course',1); + $this->set('questions_per_course',1); + $this->set('questions_per_quiz',1); + } + + if ($this->get('pre_cleanup')) { + $this->verbose("Deleting previous test data..."); + + $this->data_cleanup(); + + if (!$this->get('quiet')) { + echo "Previous test data has been deleted.{$this->eolchar}"; + } + } + + + if (!$this->get('no_data')) { + $users = $this->generate_users(); + $courses = $this->generate_courses(); + $modules = $this->generate_modules($courses); + $questions = $this->generate_questions($courses, $modules); + $course_users = $this->generate_role_assignments($users, $courses); + $this->generate_forum_posts($course_users, $modules); + $this->generate_grades($course_users, $courses, $modules); + $this->generate_module_content($course_users, $courses, $modules); + } + + if ($this->get('post_cleanup')) { + if (!$this->get('quiet')) { + echo "Removing generated data..." . $this->eolchar; + } + $this->data_cleanup(); + if (!$this->get('quiet')) { + echo "Generated data has been deleted." . $this->eolchar; + } + } + + /** + * FINISHING SCRIPT + */ + $stoptimer = time()+microtime(); + $timer = round($stoptimer-$this->starttimer,4); + if (!$this->get('quiet')) { + echo "End of script! ($timer seconds taken){$this->eolchar}"; + } + + } + + public function get($setting) { + if (isset($this->settings[$setting])) { + return $this->settings[$setting]->value; + } else { + return null; + } + } + + public function set($setting, $value) { + if (isset($this->settings[$setting])) { + $this->settings[$setting]->value = $value; + } else { + return false; } } - return $_ARG; } -/** - * If verbose is switched on, prints a string terminated by the global eolchar string. - * @param string $string The string to STDOUT - */ -function verbose($string) { - global $settings; - if ($settings['verbose'] && !$settings['quiet']) { - echo $string . $settings['eolchar']; +class generator_argument { + public $short; + public $long; + public $help; + public $type; + public $default = null; + public $value; + + public function __construct($params) { + foreach ($params as $key => $val) { + $this->$key = $val; + } + $this->value = $this->default; } } -/** - * Attempts to delete all generated test data. A few conditions are required for this to be successful: - * 1. If a database-prefix has been given, tables with this prefix must exist - * 2. If a data prefix has been given (e.g. test_), test data must contain this prefix in their unique identifiers (not PKs) - * The first method is safest, because it will not interfere with existing tables, but you have to create all the tables yourself. - */ -function data_cleanup() { - global $settings, $tables, $DB; +class generator_cli extends generator { + public $eolchar = "\n"; - if ($settings['quiet']) { - ob_start(); - } + public function __construct($settings, $argc) { + parent::__construct(); - if (!is_null($settings['database-prefix']) && isset($tables)) { // Truncate test tables if a specific db prefix was given - foreach ($tables as $table_name) { - // Don't empty a few tables - if (!in_array($table_name, array('modules', 'block'))) { - if ($DB->delete_records($table_name)) { - verbose("Truncated table $table_name"); - } else { - verbose("Could not truncate table $table_name"); - if (!$settings['ignore-errors']) { - die(); - } - } + // Building the USAGE output of the command line version + $help = "Moodle Data Generator. Generates Data for Moodle sites. Good for benchmarking and other tests.\n\n" + . "Usage: {$settings[0]}; [OPTION] ...\n" + . "Options:\n" + . " -h, -?, -help, --help This output\n"; + + foreach ($this->settings as $argument) { + $equal = ''; + if (!empty($argument->type)) { + $equal = "={$argument->type}"; + } + + $padding1 = 5 - strlen($argument->short); + $padding2 = 30 - (strlen($argument->long) + strlen($equal)); + $paddingstr1 = ''; + for ($i = 0; $i < $padding1; $i++) { + $paddingstr1 .= ' '; } + $paddingstr2 = ''; + for ($i = 0; $i < $padding2; $i++) { + $paddingstr2 .= ' '; + } + + $help .= " -{$argument->short},$paddingstr1--{$argument->long}$equal$paddingstr2{$argument->help}\n"; } - } else { // Delete records in normal tables if no specific db prefix was given - $courses = $DB->get_records_select('course', "idnumber LIKE ?", array("{$settings['data-prefix']}%"), null, 'id'); + $help .= "\nEmail nicolas@moodle.com for any suggestions or bug reports.\n"; + + if ($argc == 1 || in_array($settings[1], array('--help', '-help', '-h', '-?'))) { + echo $help; + die(); + + } else { + + $settings = $this->_arguments($settings); + $argscount = 0; + + foreach ($this->settings as $argument) { + $value = null; - if (is_array($courses) && count($courses) > 0) { - foreach ($courses as $course) { - if (!delete_course($course->id, false)) { - verbose("Could not delete course $course->id or some of its associated records from the database."); - if (!$settings['ignore-errors']) { - die(); + if (in_array($argument->short, array_keys($settings))) { + $value = $settings[$argument->short]; + unset($settings[$argument->short]); + + } elseif (in_array($argument->long, array_keys($settings))) { + $value = $settings[$argument->long]; + unset($settings[$argument->long]); + } + + if (!is_null($value)) { + + if (!empty($argument->type) && $argument->type == 'mod1,mod2...') { + $value = explode(',', $value); } - } else { - verbose("Deleted course $course->id and all associated records from the database."); + + $this->set($argument->long, $value); + $argscount++; } } + + // If some params are left in argv, it means they are not supported + if ($argscount == 0 || count($settings) > 0) { + echo $help; + die(); + } } + } - verbose("Deleting test users (permanently)..."); - if (!$DB->delete_records_select('user', "username LIKE ?", array("{$settings['data-prefix']}%"))) { - verbose("Error deleting users from the database"); - if (!$settings['ignore-errors']) { + public function generate_data() { + if (is_null($this->get('username')) || $this->get('username') == '') { + echo "You must enter a valid username for a moodle administrator account on this site.{$this->eolchar}"; + die(); + } elseif (is_null($this->get('password')) || $this->get('password') == '') { + echo "You must enter a valid password for a moodle administrator account on this site.{$this->eolchar}"; + die(); + } else { + if (!$user = authenticate_user_login($this->get('username'), $this->get('password'))) { + echo "Invalid username or password!{$this->eolchar}"; + die(); + } + $USER = complete_user_login($user); + $systemcontext = get_context_instance(CONTEXT_SYSTEM); + if (!has_capability('moodle/site:doanything', $systemcontext)) { + echo "You do not have administration privileges on this Moodle site. " + ."These are required for running the generation script.{$this->eolchar}"; die(); } } + + parent::generate_data(); } - if ($settings['quiet']) { - ob_end_clean(); + /** + * Converts the standard $argv into an associative array taking var=val arguments into account + * @param array $argv + * @return array $_ARG + */ + private function _arguments($argv) { + $_ARG = array(); + foreach ($argv as $arg) { + if (ereg('--?([^=]+)=(.*)',$arg,$reg)) { + $_ARG[$reg[1]] = $reg[2]; + } elseif(ereg('-([a-zA-Z0-9]+)',$arg,$reg)) { + $_ARG[$reg[1]] = 'true'; + } + } + return $_ARG; } } +class generator_web extends generator { + public $eolchar = '
'; + + public function display() { + print_header("Data generator"); + print_heading("Data generator: web interface"); + $mform = new generator_form(); + + if ($data = $mform->get_data(false)) { + foreach ($this->settings as $setting) { + if (isset($data->{$setting->long})) { + $this->set($setting->long, $data->{$setting->long}); + } + } + } + + $systemcontext = get_context_instance(CONTEXT_SYSTEM); + if (!has_capability('moodle/site:doanything', $systemcontext)) { + // If not logged in, give link to login page for current site + notify("You must be logged in as administrator before using this script."); + require_login(); + } else { + $mform->display(); + } + } + + public function __destroy() { + print_footer(); + } +} + +function generator_generate_data($settings) { + $generator = new generator($settings); + $generator->generate_data(); +} + class fake_form { function get_new_filename($string) { return false; } } + +class generator_form extends moodleform { + function definition() { + global $generator; + $mform =& $this->_form; + $mform->addElement('hidden', 'web_interface', 1); + + foreach ($generator->settings as $setting) { + $type = 'advcheckbox'; + $options = null; + $htmloptions = null; + + $label = ucfirst(str_replace('-', ' ', $setting->long)); + if (!empty($setting->type) && $setting->type == 'mod1,mod2...') { + $type = 'select'; + $options = $generator->modules_list; + $htmloptions = array('multiple' => 'multiple'); + } elseif (!empty($setting->type)) { + $type = 'text'; + } + + if ($setting->long == 'password' || $setting->long == 'username') { + continue; + } + + $mform->addElement($type, $setting->long, $label, $options, $htmloptions); + $mform->setHelpButton($setting->long, array(false, $label, false, true, false, $setting->help)); + + if (isset($setting->default)) { + $mform->setDefault($setting->long, $setting->default); + } + } + $this->add_action_buttons(false, 'Generate data!'); + } + + function definition_after_data() { + + } +} + +$web_interface = optional_param('web_interface', false, PARAM_BOOL); + +if (isset($argv) && isset($argc)) { + $generator = new generator_cli($argv, $argc); + $generator->generate_data(); +} elseif($web_interface) { + $generator = new generator_web(); + $generator->display(); + $generator->generate_data(); +} + ?> diff --git a/lib/simpletest/testportfoliolib.php b/lib/simpletest/testportfoliolib.php index 20636c7b9ebf7..117657f05d29c 100755 --- a/lib/simpletest/testportfoliolib.php +++ b/lib/simpletest/testportfoliolib.php @@ -129,13 +129,17 @@ function tearDown() { $DB->delete_records('portfolio_tempdata', array('id' => $this->exporter->get('id'))); $fs = get_file_storage(); $fs->delete_area_files(SYSCONTEXTID, 'portfolio_exporter', $this->exporter->get('id')); + + $settings = array('no_data' => 1, 'post_cleanup' => 1, 'database_prefix' => 'tst_', 'quiet' => 1); + generator_generate_data($settings); } function test_construct_dupe_instance() { $gotexception = false; try { - portfolio_plugin_base::create_instance('download', 'download1', array()); - portfolio_plugin_base::create_instance('download', 'download2', array()); + $plugin1 = portfolio_plugin_base::create_instance('download', 'download1', array()); + $plugin2 = portfolio_plugin_base::create_instance('download', 'download2', array()); + $test1 = new portfolio_plugin_download($plugin1->get('id')); } catch (portfolio_exception $e) { $this->assertEqual('multipledisallowed', $e->errorcode); $gotexception = true; diff --git a/portfolio/type/boxnet/lib.php b/portfolio/type/boxnet/lib.php index 15b2f1f2d99a7..108a27645ccb0 100644 --- a/portfolio/type/boxnet/lib.php +++ b/portfolio/type/boxnet/lib.php @@ -4,7 +4,7 @@ class portfolio_plugin_boxnet extends portfolio_plugin_push_base { - private $boxclient; + public $boxclient; private $ticket; private $authtoken; private $folders; diff --git a/portfolio/type/boxnet/simpletest/testportfoliopluginboxnet.php b/portfolio/type/boxnet/simpletest/testportfoliopluginboxnet.php index 7b79bc1dc6d9b..89a1cda2a4e3f 100644 --- a/portfolio/type/boxnet/simpletest/testportfoliopluginboxnet.php +++ b/portfolio/type/boxnet/simpletest/testportfoliopluginboxnet.php @@ -1,6 +1,7 @@ libdir.'/simpletest/testportfoliolib.php'); require_once($CFG->dirroot.'/portfolio/type/boxnet/lib.php'); +require_once($CFG->dirroot.'/admin/generator.php'); Mock::generate('boxclient', 'mock_boxclient'); Mock::generatePartial('portfolio_plugin_boxnet', 'mock_boxnetplugin', array('ensure_ticket', 'ensure_account_tree')); @@ -10,6 +11,8 @@ public function setUp() { parent::setUp(); $this->plugin = &new mock_boxnetplugin($this); $this->plugin->boxclient = new mock_boxclient(); + $settings = array('tiny' => 1, 'quiet' => 1, 'database_prefix' => 'tst_', 'pre_cleanup' => 1); + generator_generate_data($settings); } public function tearDown() { diff --git a/portfolio/type/download/simpletest/testportfolioplugindownload.php b/portfolio/type/download/simpletest/testportfolioplugindownload.php new file mode 100755 index 0000000000000..c020e73ed55cf --- /dev/null +++ b/portfolio/type/download/simpletest/testportfolioplugindownload.php @@ -0,0 +1,21 @@ +libdir.'/simpletest/testportfoliolib.php'); +require_once($CFG->dirroot.'/portfolio/type/download/lib.php'); + +Mock::generate('boxclient', 'mock_boxclient'); +Mock::generatePartial('portfolio_plugin_download', 'mock_downloadplugin', array('ensure_ticket', 'ensure_account_tree')); + + +class testPortfolioPluginDownload extends portfoliolib_test { + public function setUp() { + parent::setUp(); + $this->plugin = &new mock_boxnetplugin($this); + $this->plugin->boxclient = new mock_boxclient(); + } + + public function tearDown() { + parent::tearDown(); + } + +} +?> diff --git a/portfolio/type/flickr/lib.php b/portfolio/type/flickr/lib.php new file mode 100755 index 0000000000000..139c797526d73 --- /dev/null +++ b/portfolio/type/flickr/lib.php @@ -0,0 +1,42 @@ +libdir.'/filelib.php'); +require_once($CFG->dirroot.'/repository/flickr/phpFlickr.php'); + +class portfolio_plugin_flickr extends portfolio_plugin_push_base { + + private $flickr; + + public function prepare_package() { + $this->flickr = new phpFlickr($this->get_config('apikey'), $this->get_config('sharedsecret')); + return true; // don't do anything else for this plugin, we want to send all files as they are. + } + + public function send_package() { + + } + + public function get_continue_url() { + return 'http://www.flickr.com/files#0:f:' . $this->get_export_config('folder'); + } + + public function expected_time($callertime) { + return $callertime; + } + + public static function get_allowed_config() { + return array('apikey', 'sharedsecret'); + } + + public static function has_admin_config() { + return true; + } + + public function admin_config_form(&$mform) { + $strrequired = get_string('required'); + $mform->addElement('text', 'apikey', get_string('apikey', 'portfolio_flickr')); + $mform->addRule('apikey', $strrequired, 'required', null, 'client'); + $mform->addElement('text', 'sharedsecret', get_string('sharedsecret', 'portfolio_flickr')); + $mform->addRule('sharedsecret', $strrequired, 'required', null, 'client'); + } + +} diff --git a/portfolio/type/flickr/version.php b/portfolio/type/flickr/version.php new file mode 100755 index 0000000000000..1a008260797be --- /dev/null +++ b/portfolio/type/flickr/version.php @@ -0,0 +1,7 @@ +version = 2008072500; +$plugin->requires = 2008072500; +$plugin->cron = 0; + +?>