[system] / branches / rel-2-1-a1 / webwork-modperl / lib / WeBWorK / Utils / CourseManagement.pm Repository:
ViewVC logotype

View of /branches/rel-2-1-a1/webwork-modperl/lib/WeBWorK/Utils/CourseManagement.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2536 - (download) (as text) (annotate)
Sun Jul 18 13:35:24 2004 UTC (8 years, 11 months ago) by gage
File size: 24517 byte(s)
CAUTION.  Major update!!!
Modifications made up until the release of 2.0 on July 16, 2004
on the 2.0 branch have been incorporated into version 2.1 alpha 1.
A moderate amount of testing has been done.  It will take
some time to reconfigure your global.conf file once you update to
this version.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: webwork2/lib/WeBWorK/Utils/CourseManagement.pm,v 1.17 2004/06/24 17:44:16 sh002i Exp $
    5 #
    6 # This program is free software; you can redistribute it and/or modify it under
    7 # the terms of either: (a) the GNU General Public License as published by the
    8 # Free Software Foundation; either version 2, or (at your option) any later
    9 # version, or (b) the "Artistic License" which comes with this package.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 package WeBWorK::Utils::CourseManagement;
   18 use base qw(Exporter);
   19 
   20 =head1 NAME
   21 
   22 WeBWorK::Utils::CourseManagement - create, rename, and delete courses.
   23 
   24 =cut
   25 
   26 use strict;
   27 use warnings;
   28 use Carp;
   29 use DBI;
   30 use File::Path qw(rmtree);
   31 use WeBWorK::CourseEnvironment;
   32 use WeBWorK::Debug;
   33 use WeBWorK::Utils qw(runtime_use undefstr readDirectory);
   34 
   35 our @EXPORT    = ();
   36 our @EXPORT_OK = qw(
   37   addCourse
   38   renameCourse
   39   deleteCourse
   40   listCourses
   41 );
   42 
   43 use constant CREATE_HELPERS => {
   44   sql => \&addCourseSQL,
   45 };
   46 
   47 use constant RENAME_HELPERS => {
   48   sql => \&renameCourseSQL,
   49   gdbm => \&renameCourseGDBM,
   50 };
   51 
   52 use constant DELETE_HELPERS => {
   53   sql => \&deleteCourseSQL,
   54 };
   55 
   56 =head1 FUNCTIONS
   57 
   58 =over
   59 
   60 =item addCourse(%options)
   61 
   62 %options must contain:
   63 
   64  courseID => $courseID,
   65  ce => $ce,
   66  courseOptions => $courseOptions,
   67  dbOptions => $dbOptions,
   68  users => $users
   69 
   70 %options may contain:
   71 
   72  templatesFrom => $templatesCourseID,
   73 
   74 Create a new course named $courseID.
   75 
   76 $ce is a WeBWorK::CourseEnvironment object that describes the new course's
   77 environment.
   78 
   79 $courseOptions is a reference to a hash containing the following options:
   80 
   81  dbLayoutName         => $dbLayoutName
   82  globalUserID         => $dbLayouts{gdbm}->{set}->{params}->{globalUserID}
   83                          $dbLayouts{gdbm}->{problem}->{params}->{globalUserID}
   84  allowedRecipients    => $mail{allowedRecipients}
   85  feedbackRecipients   => $mail{feedbackRecipients}
   86  PRINT_FILE_NAMES_FOR => $pg{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR}
   87 
   88 C<dbLayoutName> is required. C<allowedRecipients>, C<feedbackRecipients>, and
   89 C<PRINT_FILE_NAMES_FOR> are references to arrays.
   90 
   91 $dbOptions is a reference to a hash containing information required to create a
   92 database for the course.
   93 
   94  if dbLayout == "sql":
   95 
   96   host     => host to connect to
   97   port     => port to connect to
   98   username => user to connect as (must have CREATE, DELETE, FILE, INSERT,
   99               SELECT, UPDATE privileges, WITH GRANT OPTION.)
  100   password => password to supply
  101   database => the name of the database to create
  102   wwhost   => the host from which the webwork database users will be allowed
  103               to connect. (if host is set to localhost, this should be set to
  104               localhost too.)
  105 
  106 These values must match the information given in the selected dbLayout. If
  107 $dbOptions is undefined, addCourse() assumes that the database has already been
  108 created, and skips that step in the course creation process.
  109 
  110 $users is a list of arrayrefs, each containing a User, Password, and
  111 PermissionLevel record for a single user:
  112 
  113  $users = [ $User, $Password, $PermissionLevel ]
  114 
  115 These users are added to the course.
  116 
  117 $templatesCourseID indicates the ID of a course from which the contents of the
  118 templates directory will be copied to the new course.
  119 
  120 =cut
  121 
  122 sub addCourse {
  123   my (%options) = @_;
  124 
  125   my $courseID = $options{courseID};
  126   my $ce = $options{ce};
  127   my %courseOptions = %{ $options{courseOptions} };
  128   my %dbOptions = defined $options{dbOptions} ? %{ $options{dbOptions} } : ();
  129   my @users = exists $options{users} ? @{ $options{users} } : ();
  130 
  131   # get the database layout out of the options hash
  132   my $dbLayoutName = $courseOptions{dbLayoutName};
  133 
  134   # collect some data
  135   my $coursesDir = $ce->{webworkDirs}->{courses};
  136   my $courseDir = "$coursesDir/$courseID";
  137 
  138   # fail if the course already exists
  139   # IMPORTANT: this must be the first check! if any check other than this one
  140   # fails, CourseAdmin deletes the course!! Oh no!!!
  141   if (-e $courseDir) {
  142     croak "$courseID: course exists";
  143   }
  144 
  145   # FIXME: is hyphen ok? signs point to "no"
  146   croak "Invalid characters in course ID: '$courseID' (valid characters are [A-Za-z0-9_])"
  147     unless $courseID =~ m/^[\w-]*$/;
  148 
  149   # fail if the database layout is invalid
  150   if (defined $dbLayoutName and not exists $ce->{dbLayouts}->{$dbLayoutName}) {
  151     croak "$dbLayoutName: not found in \%dbLayouts";
  152   }
  153 
  154   # if we didn't get a database layout, use the default one
  155   if (not defined $dbLayoutName) {
  156     $dbLayoutName = $ce->{dbLayoutName};
  157   }
  158 
  159   ##### step 1: create course directory structure #####
  160 
  161   my @subDirs = sort values %{ $ce->{courseDirs} };
  162   foreach my $subDir (@subDirs) {
  163     mkdir "$subDir"
  164       or die "Failed to create course directory $subDir: $!\n";
  165   }
  166 
  167   ##### step 2: create course database (if necessary) #####
  168 
  169   my $createHelper = CREATE_HELPERS->{$dbLayoutName};
  170   if (defined $createHelper) {
  171     my $createHelperResult = $createHelper->($courseID, $ce, $dbLayoutName, %dbOptions);
  172     die "$courseID: course database creation failed.\n" unless $createHelperResult;
  173   }
  174 
  175   ##### step 3: populate course database #####
  176 
  177   my $db = WeBWorK::DB->new($ce->{dbLayouts}->{$dbLayoutName});
  178 
  179   # make sure we add the global user
  180   if (exists $courseOptions{globalUserID}) {
  181     unless (grep { $_->[0]->user_id eq $courseOptions{globalUserID} } @users) {
  182       push @users, [
  183         $db->newUser(user_id => $courseOptions{globalUserID}),
  184         $db->newPassword(user_id => $courseOptions{globalUserID}),
  185         $db->newPermissionLevel(user_id => $courseOptions{globalUserID}),
  186       ];
  187     }
  188   }
  189 
  190   my @professors; # user ID of any user whose permission level == 10
  191 
  192   foreach my $userTriple (@users) {
  193     my ($User, $Password, $PermissionLevel) = @$userTriple;
  194 
  195     if (defined $PermissionLevel->permission and $PermissionLevel->permission == 10) {
  196       push @professors, $PermissionLevel->user_id;
  197     }
  198 
  199     eval { $db->addUser($User)                       }; warn $@ if $@;
  200     eval { $db->addPassword($Password)               }; warn $@ if $@;
  201     eval { $db->addPermissionLevel($PermissionLevel) }; warn $@ if $@;
  202   }
  203 
  204   ##### step 4: write course.conf file #####
  205 
  206   my $courseEnvFile = $ce->{courseFiles}->{environment};
  207   open my $fh, ">", $courseEnvFile
  208     or die "failed to open $courseEnvFile for writing.\n";
  209   writeCourseConf($fh, $ce, %courseOptions);
  210   close $fh;
  211 
  212   ##### step 5: copy templates #####
  213 
  214   if (exists $options{templatesFrom}) {
  215     my $sourceCourse = $options{templatesFrom};
  216     my $sourceCE = new WeBWorK::CourseEnvironment(
  217       $ce->{webworkDirs}->{root},
  218       $ce->{webworkURLs}->{root},
  219       $ce->{pg}->{directories}->{root},
  220       $sourceCourse,
  221     );
  222     my $sourceDir = $sourceCE->{courseDirs}->{templates};
  223 
  224     if (-d $sourceDir) {
  225       my $destDir = $ce->{courseDirs}->{templates};
  226       my $errno = system "/bin/cp -R $sourceDir/* $destDir";
  227       if ($errno) {
  228         warn "Failed to copy templates from course '$sourceCourse' (errno=$errno): $!\n";
  229       }
  230     } else {
  231       warn "Failed to copy templates from course '$sourceCourse': templates directory '$sourceDir' does not exist.\n";
  232     }
  233   }
  234 
  235 }
  236 
  237 =item renameCourse($webworkRoot, $oldCourseID, $newCourseID)
  238 
  239 Rename the course named $oldCourseID to $newCourseID.
  240 
  241 The name course directory is set to $newCourseID.
  242 
  243 If the course's database layout is C<sql>, a new database is created, course
  244 data is exported from the old database and imported into the new database, and
  245 the old database is deleted.
  246 
  247 If the course's database layout is C<gdbm>, the DBM files are simply renamed on
  248 disk.
  249 
  250 If the course's database layout is something else, no database changes are made.
  251 
  252 Any errors encountered while renaming the course are returned.
  253 
  254 =cut
  255 
  256 sub renameCourse {
  257   my ($webworkRoot, $oldCourseID, $newCourseID) = @_;
  258 
  259 
  260 }
  261 
  262 =item deleteCourse(%options)
  263 
  264 Options must contain:
  265 
  266  courseID => $courseID,
  267  ce => $ce,
  268  dbOptions => $dbOptions,
  269 
  270 $ce is a WeBWorK::CourseEnvironment object that describes the course's
  271 environment. It is your responsability to pass a course environment object that
  272 describes the course to be deleted. Do not pass the course environment object
  273 associated with the request, unless you are deleting the course you're currently
  274 using.
  275 
  276 $dbOptions is a reference to a hash containing information required to create a
  277 database for the course.
  278 
  279  if dbLayout == "sql":
  280 
  281   host     => host to connect to
  282   port     => port to connect to
  283   username => user to connect as (must have CREATE, DELETE, FILE, INSERT,
  284               SELECT, UPDATE privileges, WITH GRANT OPTION.)
  285   password => password to supply
  286   database => the name of the database to create
  287 
  288 Deletes the course named $courseID. The course directory is removed.
  289 
  290 If the course's database layout is C<sql>, the course database is dropped.
  291 
  292 If the course's database layout is something else, no databases are removed.
  293 
  294 Any errors encountered while deleting the course are returned.
  295 
  296 =cut
  297 
  298 sub deleteCourse {
  299   my (%options) = @_;
  300 
  301   my $courseID = $options{courseID};
  302   my $ce = $options{ce};
  303   my %dbOptions = defined $options{dbOptions} ? %{ $options{dbOptions} } : ();
  304 
  305   # make sure the user isn't brain damaged
  306   die "the course environment supplied doesn't appear to describe the course $courseID. can't proceed."
  307     unless $ce->{courseName} eq $courseID;
  308 
  309   ##### step 1: delete course database (if necessary) #####
  310 
  311   my $dbLayoutName = $ce->{dbLayoutName};
  312   my $deleteHelper = DELETE_HELPERS->{$dbLayoutName};
  313   if (defined $deleteHelper) {
  314     my $deleteHelperResult = $deleteHelper->($courseID, $ce, $dbLayoutName, %dbOptions);
  315     debug("deleteHelper returned '$deleteHelperResult'.");
  316     unless ($deleteHelperResult) {
  317       die "Failed to delete course database. Does the database exist? Were proper admin credentials given?\n";
  318     }
  319   }
  320 
  321   ##### step 2: delete course directory structure #####
  322 
  323   # my $courseDir = $ce->{courseDirs}->{root};
  324   # the tmp file might be in a different tree
  325   my @courseDirs = keys %{ $ce->{courseDirs} };
  326   foreach my $key (@courseDirs) {
  327       my $courseDir = $ce->{courseDirs}->{$key};
  328     rmtree($courseDir, 0, 0) if -e $courseDir;
  329   }
  330 }
  331 
  332 =item listCourses($ce)
  333 
  334 Lists the courses defined.
  335 
  336 =cut
  337 
  338 sub listCourses {
  339   my ($ce) = @_;
  340 
  341   my $coursesDir = $ce->{webworkDirs}->{courses};
  342 
  343   return grep { not (m/^\./ or m/^CVS$/) and -d "$coursesDir/$_" } readDirectory($coursesDir);
  344 }
  345 
  346 =back
  347 
  348 =cut
  349 
  350 ################################################################################
  351 
  352 =head1 DATABASE-LAYOUT SPECIFIC HELPER FUNCTIONS
  353 
  354 These functions are used by the methods and should not be called directly.
  355 
  356 =over
  357 
  358 =item addCourseSQL($courseID, $ce, $dbLayoutName, %options)
  359 
  360 Creates the course database for an SQL course. Return value is boolean,
  361 indicates success or failure.
  362 
  363 =cut
  364 
  365 sub addCourseSQL {
  366   my ($courseID, $ce, $dbLayoutName, %options) = @_;
  367 
  368   ##### parse dbLayout to generate sql statements #####
  369 
  370   my %sources;
  371 
  372   debug("dbLayoutName=$dbLayoutName");
  373 
  374   my %dbLayout = %{ $ce->{dbLayouts}->{$dbLayoutName} };
  375 
  376   my @tables = keys %dbLayout;
  377   debug("layout defines the following tables: @tables");
  378 
  379   foreach my $table (@tables) {
  380     my %table = %{ $dbLayout{$table} };
  381     my %params = %{ $table{params} };
  382 
  383     my $source = $table{source};
  384     debug("$table: DBI source is $source\n");
  385 
  386     my $tableOverride = $params{tableOverride};
  387     debug("$table: SQL table name is ", undefstr("not defined", $tableOverride), "\n");
  388 
  389     my $recordClass = $table{record};
  390     debug("$table: record class is $recordClass\n");
  391 
  392     runtime_use($recordClass);
  393     my @fields = $recordClass->FIELDS;
  394     debug("$table: WeBWorK field names: @fields\n");
  395 
  396     if (exists $params{fieldOverride}) {
  397       my %fieldOverride = %{ $params{fieldOverride} };
  398       foreach my $field (@fields) {
  399         $field = $fieldOverride{$field} if exists $fieldOverride{$field};
  400       }
  401       debug("$table: SQL field names: @fields\n");
  402     }
  403 
  404     # generate table creation statement
  405 
  406     my $tableName = $tableOverride || $table;
  407     my @fieldList;
  408     foreach my $field (@fields) {
  409       # a stupid hack to make PSVNs numeric and auto-increment
  410       if ($field eq "psvn") {
  411         push @fieldList, "$field INT NOT NULL PRIMARY KEY AUTO_INCREMENT";
  412       } else {
  413         push @fieldList, "$field TEXT";
  414       }
  415     }
  416     my $fieldString = join(", ", @fieldList);
  417     my $createStmt = "CREATE TABLE $tableName ( $fieldString );";
  418 
  419     debug("$table: CREATE statement is: $createStmt\n");
  420 
  421     # generate GRANT statements
  422 
  423     my $grantStmtRO = "GRANT SELECT"
  424         . " ON `$options{database}`.$tableName"
  425         . " TO $params{usernameRO}\@$options{wwhost}"
  426         . " IDENTIFIED BY '$params{passwordRO}';";
  427     my $grantStmtRW = "GRANT SELECT, INSERT, UPDATE, DELETE"
  428         . " ON `$options{database}`.$tableName"
  429         . " TO $params{usernameRW}\@$options{wwhost}"
  430         . " IDENTIFIED BY '$params{passwordRW}';";
  431 
  432     debug("$table: GRANT RO statement is: $grantStmtRO\n");
  433     debug("$table: GRANT RW statement is: $grantStmtRW\n");
  434 
  435     # add to source hash
  436 
  437     if (exists $sources{$source}) {
  438       push @{ $sources{$source} }, $createStmt, $grantStmtRO, $grantStmtRW;
  439     } else {
  440       $sources{$source} = [ $createStmt, $grantStmtRO, $grantStmtRW ];
  441     }
  442 
  443     #warn "\n";
  444   }
  445 
  446   ##### handle multiple sources #####
  447 
  448   # if more than one source is listed, we only want to create the tables that
  449   # have the most popular source
  450 
  451   my $source;
  452   if (keys %sources > 1) {
  453     # more than one -- warn and select the most popular source
  454     debug("database layout $dbLayoutName defines more than one SQL source.\n");
  455     foreach my $curr (keys %sources) {
  456       $source = $curr if not defined $source or @{ $sources{$curr} } > @{ $sources{$source} };
  457     }
  458     debug("only creating tables with source \"$source\".\n");
  459     debug("others will have to be created manually.\n");
  460   } else {
  461     # there's only one
  462     ($source) = keys %sources;
  463   }
  464   my @stmts = (
  465     "CREATE DATABASE `$options{database}`;",
  466     "USE $options{database};", # oddly, backquotes prohibited with USE statement...
  467     @{ $sources{$source} }
  468   );
  469 
  470   ##### issue SQL statements #####
  471 
  472   my ($driver) = $source =~ m/^dbi:(\w+):/i;
  473   return execSQLStatements($driver, $ce->{externalPrograms}, \%options, @stmts)
  474 }
  475 
  476 =item renameCourseSQL($oldCourseID, $newCourseID, $ce, $dbLayoutName, %options)
  477 
  478 =cut
  479 
  480 =item deleteCourseSQL($courseID, $ce, $dbLayoutName, %options)
  481 
  482 =cut
  483 
  484 sub deleteCourseSQL {
  485   my ($courseID, $ce, $dbLayoutName, %options) = @_;
  486 
  487   # get the most popular DBI source, so we know what driver to use
  488   my $dbi_source = do {
  489     my %sources;
  490     foreach my $table (keys %{ $ce->{dbLayouts}->{$dbLayoutName} }) {
  491       $sources{$ce->{dbLayouts}->{$dbLayoutName}->{$table}->{source}}++;
  492     }
  493     my $source;
  494     if (keys %sources > 1) {
  495       foreach my $curr (keys %sources) {
  496         $source = $curr if @{ $sources{$curr} } > @{ $sources{$source} };
  497       }
  498     } else {
  499       ($source) = keys %sources;
  500     }
  501     $source;
  502   };
  503 
  504   my $stmt = "DROP DATABASE `$options{database}`;";
  505 
  506   my ($driver) = $dbi_source =~ m/^dbi:(\w+):/i;
  507   return execSQLStatements($driver, $ce->{externalPrograms}, \%options, $stmt);
  508 }
  509 
  510 =item renameCourseGDBM($oldCourseID, $newCourseID, $ce, $dbLayoutName, %options)
  511 
  512 =cut
  513 
  514 =back
  515 
  516 =cut
  517 
  518 ################################################################################
  519 
  520 =head1 UTILITIES
  521 
  522 These functions are used by the methods and should not be called directly.
  523 
  524 =over
  525 
  526 =item execSQLStatements($driver, $externalPrograms, $dbOptions, @statements)
  527 
  528 Execute the listed SQL statements. The appropriate SQL console is determined
  529 using $driver and invoked with the options listed in $dbOptions.
  530 
  531 $options is a reference to a hash containing the pairs accepted in %dbOptions by
  532 addCourse(), above.
  533 
  534 Returns true on success, false on failure.
  535 
  536 =cut
  537 
  538 sub execSQLStatements {
  539   my ($driver, $externalPrograms, $dbOptions, @statements) = @_;
  540   my %options = %$dbOptions;
  541 
  542   my $exit_status;
  543 
  544   if (lc $driver eq "mysql") {
  545     my @commandLine = ( $externalPrograms->{mysql} );
  546     push @commandLine, "--host=$options{host}" if exists $options{host};
  547     push @commandLine, "--port=$options{port}" if exists $options{port};
  548     push @commandLine, "--user=$options{username}" if exists $options{username};
  549     push @commandLine, "--password=$options{password}" if exists $options{password};
  550 
  551     open my $mysql, "|@commandLine"
  552         or die "execSQLStatements: failed to execute \"@commandLine\": $!\n";
  553 
  554     # exec sql statements
  555     foreach my $stmt (@statements) {
  556       debug("exec: $stmt");
  557       print $mysql "$stmt\n";
  558     }
  559 
  560     close $mysql;
  561     $exit_status = $?;
  562   }
  563 
  564   # add code to deal with other RDBMSs here:
  565   #
  566   #elsif (lc $driver eq "foobar") {
  567   # # do something else
  568   #}
  569 
  570   else {
  571     die "execSQLStatements: driver \"$driver\" is not supported.\n";
  572   }
  573 
  574   # "...the exit value of the subprocess is in the high byte, that is, $? >>
  575   # 8; in the low byte, $? & 127 says which signal (if any) the process died
  576   # from, while $? & 128 reports whether its demise produced a core dump."
  577   #     -- Camel, 3rd ed
  578   my $status = $exit_status >> 8;
  579   #my $signal = $exit_status & 127;
  580   #my $core = $exit_status & 128
  581 
  582   # we want to return true for success and false for failure
  583   debug("SQL console returned exit status $status.\n");
  584   return not $status;
  585 }
  586 
  587 =item protectQString($string)
  588 
  589 Protects the contents of a single-quoted Perl string.
  590 
  591 =cut
  592 
  593 sub protectQString {
  594   my ($string) = @_;
  595   $string =~ s/'/\'/g;
  596   return $string;
  597 }
  598 
  599 =item writeCourseConf($fh, $ce, %options)
  600 
  601 Writes a course.conf file to $fh, a file handle, using defaults from the course
  602 environment object $ce and overrides from %options. %options can contain any of
  603 the pairs accepted in %courseOptions by addCourse(), above.
  604 
  605 =cut
  606 
  607 sub writeCourseConf {
  608   my ($fh, $ce, %options) = @_;
  609 
  610   # several options should be defined no matter what
  611   $options{dbLayoutName} = $ce->{dbLayoutName} unless defined $options{dbLayoutName};
  612   $options{globalUserID} = $ce->{dbLayouts}->{gdbm}->{set}->{params}->{globalUserID}
  613     unless defined $options{globalUserID};
  614 
  615   print $fh <<'EOF';
  616 #!perl
  617 ################################################################################
  618 # WeBWorK Online Homework Delivery System
  619 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
  620 #
  621 # This program is free software; you can redistribute it and/or modify it under
  622 # the terms of either: (a) the GNU General Public License as published by the
  623 # Free Software Foundation; either version 2, or (at your option) any later
  624 # version, or (b) the "Artistic License" which comes with this package.
  625 #
  626 # This program is distributed in the hope that it will be useful, but WITHOUT
  627 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  628 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
  629 # Artistic License for more details.
  630 ################################################################################
  631 
  632 # This file is used to override the global WeBWorK course environment for
  633 # requests to this course. All package variables set in this file are added to
  634 # the course environment. If you wish to set a variable here but omit it from
  635 # the course environment,  use the "my" keyword. Commonly changed configuration
  636 # options are noted below.
  637 
  638 EOF
  639 
  640   print $fh <<'EOF';
  641 # Database Layout (global value typically defined in global.conf)
  642 #
  643 # Several database are defined in the file conf/database.conf and stored in the
  644 # hash %dbLayouts.
  645 #
  646 # The database layout is always set here, since one should be able to change the
  647 # default value in global.conf without disrupting existing courses.
  648 #
  649 # global.conf values:
  650 EOF
  651 
  652   print $fh "# \t", '$dbLayoutName = \'', protectQString($ce->{dbLayoutName}), '\';', "\n";
  653   print $fh "# \t", '*dbLayout = $dbLayouts{$dbLayoutName};', "\n";
  654   print $fh "\n";
  655 
  656   if (defined $options{dbLayoutName}) {
  657     print $fh '$dbLayoutName = \'', protectQString($options{dbLayoutName}), '\';', "\n";
  658     print $fh '*dbLayout = $dbLayouts{$dbLayoutName};', "\n";
  659     print $fh "\n";
  660   } else {
  661     print $fh "\n\n\n";
  662   }
  663 
  664   print $fh <<'EOF';
  665 # Global User ID (global value typically defined in database.conf)
  666 #
  667 # The globalUserID parameter given for the set and problem tables denotes the ID
  668 # of the user that the GlobalTableEmulator will use to store data for the set
  669 # and problem tables.
  670 #
  671 # If a course will be used under WeBWorK 1.x, this value should be overridden on
  672 # a course-by-course basis to the ID of the professor who is most likely to be
  673 # involved in creating new problem sets. Sets which have not been assigned will
  674 # only be visible to this user when logging into WeBWorK 1.x.
  675 #
  676 # The global user ID is always set here, since one should be able to change the
  677 # default value in database.conf without disrupting existing courses.
  678 #
  679 # global.conf values:
  680 EOF
  681 
  682   print $fh "# \t", '$dbLayouts{gdbm}->{set}->{params}->{globalUserID} = \'',
  683       protectQString($ce->{dbLayouts}->{gdbm}->{set}->{params}->{globalUserID}), '\';', "\n";
  684   print $fh "# \t", '$dbLayouts{gdbm}->{problem}->{params}->{globalUserID} = \'',
  685       protectQString($ce->{dbLayouts}->{gdbm}->{problem}->{params}->{globalUserID}), '\';', "\n";
  686   print $fh "\n";
  687 
  688   if (defined $options{globalUserID} or defined $options{globalUserID}) {
  689     if (defined $options{globalUserID}) {
  690       print $fh '$dbLayouts{gdbm}->{set}->{params}->{globalUserID} = \'',
  691           protectQString($options{globalUserID}), '\';', "\n";
  692     }
  693     if (defined $options{globalUserID}) {
  694       print $fh '$dbLayouts{gdbm}->{problem}->{params}->{globalUserID} = \'',
  695           protectQString($options{globalUserID}), '\';', "\n";
  696     }
  697     print $fh "\n";
  698   } else {
  699     print $fh "\n\n\n";
  700   }
  701 
  702   print $fh <<'EOF';
  703 # Allowed Mail Recipients (global value typically not defined)
  704 #
  705 # Defines addresses to which the PG system is allowed to send mail. This should
  706 # probably be set to the addresses of professors of this course. Sending mail
  707 # from the PG system (i.e. questionaires, essay questions) will fail if this is
  708 # not set.
  709 #
  710 # global.conf values:
  711 EOF
  712 
  713   if (defined $ce->{mail}->{allowedRecipients}) {
  714     print $fh "# \t", '$mail{allowedRecipients} = [',
  715         join(", ", map { "'" . protectQString($_) . "'" } @{ $ce->{mail}->{allowedRecipients} }), '];', "\n";
  716   } else {
  717     print $fh "# \t", '$mail{allowedRecipients} = [  ];', "\n";
  718   }
  719   print $fh "\n";
  720 
  721   if (defined $options{allowedRecipients}) {
  722     print $fh '$mail{allowedRecipients} = [',
  723         join(", ", map { "'" . protectQString($_) . "'" } @{ $options{allowedRecipients} }), '];', "\n";
  724     print $fh "\n";
  725   } else {
  726     print $fh "\n\n\n";
  727   }
  728 
  729   print $fh <<'EOF';
  730 # Feedback Mail Recipients (global value typically not defined)
  731 #
  732 # Defines recipients for feedback mail. If not defined, mail is sent to all
  733 # instructors and TAs.
  734 #
  735 # global.conf values:
  736 EOF
  737 
  738   if (defined $ce->{mail}->{feedbackRecipients}) {
  739     print $fh "# \t", '$mail{feedbackRecipients} = [',
  740         join(", ", map { "'" . protectQString($_) . "'" } @{ $ce->{mail}->{feedbackRecipients} }), '];', "\n";
  741   } else {
  742     print $fh "# \t", '$mail{feedbackRecipients} = [  ];', "\n";
  743   }
  744   print $fh "\n";
  745 
  746   if (defined $options{feedbackRecipients}) {
  747     print $fh '$mail{feedbackRecipients} = [',
  748         join(", ", map { "'" . protectQString($_) . "'" } @{ $options{feedbackRecipients} }), '];', "\n";
  749     print $fh "\n";
  750   } else {
  751     print $fh "\n\n\n";
  752   }
  753 
  754   print $fh <<'EOF';
  755 # Users for whom to label problems with the PG file name (global value typically "professor")
  756 #
  757 # For users in this list, PG will display the source file name when rendering a problem.
  758 #
  759 # global.conf values:
  760 EOF
  761 
  762   if (defined $ce->{pg}{specialPGEnvironmentVars}{PRINT_FILE_NAMES_FOR}) {
  763     print $fh "# \t", '$pg{specialPGEnvironmentVars}{PRINT_FILE_NAMES_FOR} = [',
  764         join(", ", map { "'" . protectQString($_) . "'" } @{ $ce->{pg}{specialPGEnvironmentVars}{PRINT_FILE_NAMES_FOR} }), '];', "\n";
  765   } else {
  766     print $fh "# \t", '$pg{specialPGEnvironmentVars}{PRINT_FILE_NAMES_FOR} = [  ];', "\n";
  767   }
  768   print $fh "\n";
  769 
  770   if (defined $options{PRINT_FILE_NAMES_FOR}) {
  771     print $fh '$pg{specialPGEnvironmentVars}{PRINT_FILE_NAMES_FOR} = [',
  772         join(", ", map { "'" . protectQString($_) . "'" } @{ $options{PRINT_FILE_NAMES_FOR} }), '];', "\n";
  773     print $fh "\n";
  774   } else {
  775     print $fh "\n\n\n";
  776   }
  777 }
  778 
  779 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9