[system] / branches / rel-2-3-dev / webwork2 / lib / WeBWorK / ContentGenerator / CourseAdmin.pm Repository:
ViewVC logotype

View of /branches/rel-2-3-dev/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2138 - (download) (as text) (annotate)
Fri May 21 20:55:38 2004 UTC (9 years ago) by sh002i
Original Path: trunk/webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm
File size: 31756 byte(s)
added missing "use" line.
"use WeBWorK::CourseEnvironment".

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v 1.10 2004/05/13 20:49:18 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::ContentGenerator::CourseAdmin;
   18 use base qw(WeBWorK::ContentGenerator);
   19 
   20 =head1 NAME
   21 
   22 WeBWorK::ContentGenerator::CourseAdmin - Add, rename, and delete courses.
   23 
   24 =cut
   25 
   26 use strict;
   27 use warnings;
   28 use CGI::Pretty qw();
   29 use Data::Dumper;
   30 use File::Temp qw/tempfile/;
   31 use WeBWorK::CourseEnvironment;
   32 use WeBWorK::Utils qw(cryptPassword);
   33 use WeBWorK::Utils::CourseManagement qw(addCourse deleteCourse listCourses);
   34 use WeBWorK::Utils::DBImportExport qw(dbExport dbImport);
   35 
   36 sub pre_header_initialize {
   37   my ($self) = @_;
   38   my $r = $self->r;
   39   my $ce = $r->ce;
   40   my $db = $r->db;
   41   my $authz = $r->authz;
   42   my $urlpath = $r->urlpath;
   43   my $user        = $r->param('user');
   44 
   45   # check permissions
   46   unless ($authz->hasPermissions($user, "create_and_delete_courses")) {
   47     $self->addmessage( CGI::div({class=>'ResultsWithError'},"$user is not authorized to create or delete courses") );
   48     return;
   49   }
   50 
   51   if (defined $r->param("download_exported_database")) {
   52     my $courseID = $r->param("export_courseID");
   53     my $random_chars = $r->param("download_exported_database");
   54 
   55     die "courseID not specified" unless defined $courseID;
   56     die "invalid file specification" unless $random_chars =~ m/^\w+$/;
   57 
   58     my $tempdir = $ce->{webworkDirs}->{tmp};
   59     my $export_file = "$tempdir/db_export_$random_chars";
   60 
   61     $self->reply_with_file("text/xml", $export_file, "${courseID}_database.xml", 0);
   62   }
   63 }
   64 
   65 sub body {
   66   my ($self) = @_;
   67   my $r = $self->r;
   68   my $ce = $r->ce;
   69   my $db = $r->db;
   70   my $authz = $r->authz;
   71   my $urlpath = $r->urlpath;
   72 
   73   my $user        = $r->param('user');
   74 
   75   # check permissions
   76   unless ($authz->hasPermissions($user, "create_and_delete_courses")) {
   77     return "";
   78   }
   79 
   80   print CGI::p({style=>"text-align: center"},
   81     CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"add_course"})}, "Add Course"),
   82     #" | ",
   83     #CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"rename_course"})}, "Rename Course"),
   84     " | ",
   85     CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"delete_course"})}, "Delete Course"),
   86     " | ",
   87     CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"export_database"})}, "Export Database"),
   88     " | ",
   89     CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"import_database"})}, "Import Database"),
   90   );
   91 
   92   print CGI::hr();
   93 
   94   my $subDisplay = $r->param("subDisplay");
   95   if (defined $subDisplay) {
   96 
   97     if ($subDisplay eq "add_course") {
   98       if (defined $r->param("add_course")) {
   99         my @errors = $self->add_course_validate;
  100         if (@errors) {
  101           print CGI::div({class=>"ResultsWithError"},
  102             CGI::p("Please correct the following errors and try again:"),
  103             CGI::ul(CGI::li(\@errors)),
  104           );
  105           $self->add_course_form;
  106         } else {
  107           $self->do_add_course;
  108         }
  109       } else {
  110         $self->add_course_form;
  111       }
  112     }
  113 
  114     elsif ($subDisplay eq "delete_course") {
  115       if (defined $r->param("delete_course")) {
  116         # validate or confirm
  117         my @errors = $self->delete_course_validate;
  118         if (@errors) {
  119           print CGI::div({class=>"ResultsWithError"},
  120             CGI::p("Please correct the following errors and try again:"),
  121             CGI::ul(CGI::li(\@errors)),
  122           );
  123           $self->delete_course_form;
  124         } else {
  125           $self->delete_course_confirm;
  126         }
  127       } elsif (defined $r->param("confirm_delete_course")) {
  128         # validate and delete
  129         my @errors = $self->delete_course_validate;
  130         if (@errors) {
  131           print CGI::div({class=>"ResultsWithError"},
  132             CGI::p("Please correct the following errors and try again:"),
  133             CGI::ul(CGI::li(\@errors)),
  134           );
  135           $self->delete_course_form;
  136         } else {
  137           $self->do_delete_course;
  138         }
  139       } else {
  140         # form only
  141         $self->delete_course_form;
  142       }
  143     }
  144 
  145     elsif ($subDisplay eq "export_database") {
  146       if (defined $r->param("export_database")) {
  147         my @errors = $self->export_database_validate;
  148         if (@errors) {
  149           print CGI::div({class=>"ResultsWithError"},
  150             CGI::p("Please correct the following errors and try again:"),
  151             CGI::ul(CGI::li(\@errors)),
  152           );
  153           $self->export_database_form;
  154         } else {
  155           $self->do_export_database;
  156         }
  157       } else {
  158         $self->export_database_form;
  159       }
  160     }
  161 
  162     elsif ($subDisplay eq "import_database") {
  163       if (defined $r->param("import_database")) {
  164         my @errors = $self->import_database_validate;
  165         if (@errors) {
  166           print CGI::div({class=>"ResultsWithError"},
  167             CGI::p("Please correct the following errors and try again:"),
  168             CGI::ul(CGI::li(\@errors)),
  169           );
  170           $self->import_database_form;
  171         } else {
  172           $self->do_import_database;
  173         }
  174       } else {
  175         $self->import_database_form;
  176       }
  177     }
  178 
  179     else {
  180       print CGI::div({class=>"ResultsWithError"},
  181         "Unrecognized sub-display @{[ CGI::b($subDisplay) ]}.");
  182     }
  183 
  184   }
  185 
  186   return "";
  187 }
  188 
  189 ################################################################################
  190 
  191 sub add_course_form {
  192   my ($self) = @_;
  193   my $r = $self->r;
  194   my $ce = $r->ce;
  195   #my $db = $r->db;
  196   #my $authz = $r->authz;
  197   #my $urlpath = $r->urlpath;
  198 
  199   my $add_courseID          = $r->param("add_courseID") || "";
  200   my $add_dbLayout          = $r->param("add_dbLayout") || "";
  201   my $add_sql_host          = $r->param("add_sql_host") || "";
  202   my $add_sql_port          = $r->param("add_sql_port") || "";
  203   my $add_sql_username      = $r->param("add_sql_username") || "";
  204   my $add_sql_password      = $r->param("add_sql_password") || "";
  205   my $add_sql_database      = $r->param("add_sql_database") || "";
  206   my $add_sql_wwhost        = $r->param("add_sql_wwhost") || "";
  207   my $add_gdbm_globalUserID = $r->param("add_gdbm_globalUserID") || "";
  208   my $add_initial_userID    = $r->param("add_initial_userID") || "";
  209   my $add_initial_password  = $r->param("add_initial_password") || "";
  210 
  211   my @dbLayouts = sort keys %{ $ce->{dbLayouts} };
  212 
  213   my $ce2 = WeBWorK::CourseEnvironment->new(
  214     $ce->{webworkDirs}->{root},
  215     $ce->{webworkURLs}->{root},
  216     $ce->{pg}->{directories}->{root},
  217     "COURSENAME",
  218   );
  219 
  220   my $dbi_source = do {
  221     # find the most common SQL source (stolen from CourseManagement.pm)
  222     my %sources;
  223     foreach my $table (keys %{ $ce2->{dbLayouts}->{sql} }) {
  224       $sources{$ce2->{dbLayouts}->{sql}->{$table}->{source}}++;
  225     }
  226     my $source;
  227     if (keys %sources > 1) {
  228       foreach my $curr (keys %sources) {
  229         $source = $curr if not defined $source or
  230           $sources{$curr} > $sources{$source};
  231       }
  232     } else {
  233       ($source) = keys %sources;
  234     }
  235     $source;
  236   };
  237 
  238   print CGI::h2("Add Course");
  239 
  240   print CGI::start_form("POST", $r->uri);
  241   print $self->hidden_authen_fields;
  242   print $self->hidden_fields("subDisplay");
  243 
  244   print CGI::p("Specify a name for the new course.");
  245 
  246   print CGI::table({class=>"FormLayout"},
  247     CGI::Tr(
  248       CGI::th({class=>"LeftHeader"}, "Course Name:"),
  249       CGI::td(CGI::textfield("add_courseID", $add_courseID, 25)),
  250     ),
  251   );
  252 
  253   print CGI::p("Select a database layout below. Some database layouts require additional information.");
  254 
  255   #print CGI::start_Tr();
  256   #print CGI::th({class=>"LeftHeader"}, "Database Layout:");
  257   #print CGI::start_td();
  258 
  259   foreach my $dbLayout (@dbLayouts) {
  260     print CGI::start_table({class=>"FormLayout"});
  261 
  262     # we generate singleton radio button tags ourselves because it's too much of a pain to do it with CGI.pm
  263     print CGI::Tr(
  264       CGI::td({style=>"text-align: right"},
  265         '<input type="radio" name="add_dbLayout" value="' . $dbLayout . '"'
  266         . ($add_dbLayout eq $dbLayout ? " checked" : "") . ' />',
  267       ),
  268       CGI::td($dbLayout),
  269     );
  270 
  271     print CGI::start_Tr();
  272     print CGI::td(); # for indentation :(
  273     print CGI::start_td();
  274 
  275     if ($dbLayout eq "sql") {
  276       print CGI::p(
  277         "The SQL settings you enter below must match the settings in the DBI source",
  278         " specification ", CGI::tt($dbi_source), ". Replace ", CGI::tt("COURSENAME"),
  279         " with the course name you entered above."
  280       );
  281       print CGI::start_table({class=>"FormLayout"});
  282       print CGI::Tr(
  283         CGI::th({class=>"LeftHeader"}, "SQL Server Host:"),
  284         CGI::td(
  285           CGI::textfield("add_sql_host", $add_sql_host, 25),
  286           CGI::br(),
  287           CGI::small("Leave blank to use the default host."),
  288         ),
  289       );
  290       print CGI::Tr(
  291         CGI::th({class=>"LeftHeader"}, "SQL Server Port:"),
  292         CGI::td(
  293           CGI::textfield("add_sql_port", $add_sql_port, 25),
  294           CGI::br(),
  295           CGI::small("Leave blank to use the default port."),
  296         ),
  297       );
  298       print CGI::Tr(
  299         CGI::th({class=>"LeftHeader"}, "SQL Admin Username:"),
  300         CGI::td(CGI::textfield("add_sql_username", $add_sql_username, 25)),
  301       );
  302       print CGI::Tr(
  303         CGI::th({class=>"LeftHeader"}, "SQL Admin Password:"),
  304         CGI::td(CGI::password_field("add_sql_password", $add_sql_password, 25)),
  305       );
  306       print CGI::Tr(
  307         CGI::th({class=>"LeftHeader"}, "SQL Database Name:"),
  308         CGI::td(
  309           CGI::textfield("add_sql_database", $add_sql_database, 25),
  310           CGI::br(),
  311           CGI::small("Leave blank to use the name ", CGI::tt("webwork_COURSENAME"), "."),
  312         ),
  313       );
  314       print CGI::Tr(
  315         CGI::th({class=>"LeftHeader"}, "WeBWorK Host:"),
  316         CGI::td(
  317           CGI::textfield("add_sql_wwhost", $add_sql_wwhost || "localhost", 25),
  318           CGI::br(),
  319           CGI::small("If the SQL server does not run on the same host as WeBWorK, enter the host name of the WeBWorK server as seen by the SQL server."),
  320         ),
  321       );
  322       print CGI::end_table();
  323     } elsif ($dbLayout eq "gdbm") {
  324       print CGI::start_table({class=>"FormLayout"});
  325       print CGI::Tr(
  326         CGI::th({class=>"LeftHeader"}, "GDBM Global User ID:"),
  327         CGI::td(CGI::textfield("add_gdbm_globalUserID", $add_gdbm_globalUserID || "global_user", 25)),
  328       );
  329       print CGI::end_table();
  330     }
  331 
  332     print CGI::end_td();
  333     print CGI::end_Tr();
  334     print CGI::end_table();
  335   }
  336 
  337 
  338   print CGI::p("To add an initial user to the new course, enter a user ID and password below. If you do not do so, you will not be able to log into the course.");
  339 
  340   print CGI::table({class=>"FormLayout"},
  341     CGI::Tr(
  342       CGI::th({class=>"LeftHeader"}, "Professor User ID:"),
  343       CGI::td(CGI::textfield("add_initial_userID", $add_initial_userID || "professor", 25)),
  344     ),
  345     CGI::Tr(
  346       CGI::th({class=>"LeftHeader"}, "Professor Password:"),
  347       CGI::td(CGI::password_field("add_initial_password", $add_initial_password, 25)),
  348     ),
  349   );
  350 
  351   print CGI::p({style=>"text-align: center"}, CGI::submit("add_course", "Add Course"));
  352 
  353   print CGI::end_form();
  354 }
  355 
  356 sub add_course_validate {
  357   my ($self) = @_;
  358   my $r = $self->r;
  359   my $ce = $r->ce;
  360   #my $db = $r->db;
  361   #my $authz = $r->authz;
  362   #my $urlpath = $r->urlpath;
  363 
  364   my $add_courseID          = $r->param("add_courseID") || "";
  365   my $add_dbLayout          = $r->param("add_dbLayout") || "";
  366   my $add_sql_host          = $r->param("add_sql_host") || "";
  367   my $add_sql_port          = $r->param("add_sql_port") || "";
  368   my $add_sql_username      = $r->param("add_sql_username") || "";
  369   my $add_sql_password      = $r->param("add_sql_password") || "";
  370   my $add_sql_database      = $r->param("add_sql_database") || "";
  371   my $add_sql_wwhost        = $r->param("add_sql_wwhost") || "";
  372   my $add_gdbm_globalUserID = $r->param("add_gdbm_globalUserID") || "";
  373   my $add_initial_userID    = $r->param("add_initial_userID") || "";
  374   my $add_initial_password  = $r->param("add_initial_password") || "";
  375 
  376   my @errors;
  377 
  378   if ($add_courseID eq "") {
  379     push @errors, "You must specify a course name.";
  380   }
  381 
  382   if ($add_dbLayout eq "") {
  383     push @errors, "You must select a database layout.";
  384   } else {
  385     if (exists $ce->{dbLayouts}->{$add_dbLayout}) {
  386       if ($add_dbLayout eq "sql") {
  387         push @errors, "You must specify the SQL admin username." if $add_sql_username eq "";
  388         #push @errors, "You must specify the SQL admin password." if $add_sql_password eq "";
  389         #push @errors, "You must specify the SQL database name." if $add_sql_database eq "";
  390         push @errors, "You must specify the WeBWorK host." if $add_sql_wwhost eq "";
  391       } elsif ($add_dbLayout eq "gdbm") {
  392         push @errors, "You must specify the GDBM global user ID." if $add_gdbm_globalUserID eq "";
  393       }
  394     } else {
  395       push @errors, "The database layout $add_dbLayout doesn't exist.";
  396     }
  397   }
  398 
  399   if ($add_initial_userID ne "") {
  400     push @errors, "You must specify a professor password." if $add_initial_password eq "";
  401   }
  402 
  403   return @errors;
  404 }
  405 
  406 sub do_add_course {
  407   my ($self) = @_;
  408   my $r = $self->r;
  409   my $ce = $r->ce;
  410   my $db = $r->db;
  411   #my $authz = $r->authz;
  412   my $urlpath = $r->urlpath;
  413 
  414   my $add_courseID          = $r->param("add_courseID") || "";
  415   my $add_dbLayout          = $r->param("add_dbLayout") || "";
  416   my $add_sql_host          = $r->param("add_sql_host") || "";
  417   my $add_sql_port          = $r->param("add_sql_port") || "";
  418   my $add_sql_username      = $r->param("add_sql_username") || "";
  419   my $add_sql_password      = $r->param("add_sql_password") || "";
  420   my $add_sql_database      = $r->param("add_sql_database") || "";
  421   my $add_sql_wwhost        = $r->param("add_sql_wwhost") || "";
  422   my $add_gdbm_globalUserID = $r->param("add_gdbm_globalUserID") || "";
  423   my $add_initial_userID    = $r->param("add_initial_userID") || "";
  424   my $add_initial_password  = $r->param("add_initial_password") || "";
  425 
  426   my $ce2 = WeBWorK::CourseEnvironment->new(
  427     $ce->{webworkDirs}->{root},
  428     $ce->{webworkURLs}->{root},
  429     $ce->{pg}->{directories}->{root},
  430     $add_courseID,
  431   );
  432 
  433   my %courseOptions = ( dbLayoutName => $add_dbLayout );
  434   if ($add_dbLayout eq "gdbm") {
  435     $courseOptions{globalUserID} = $add_gdbm_globalUserID if $add_gdbm_globalUserID ne "";
  436   }
  437 
  438   my %dbOptions;
  439   if ($add_dbLayout eq "sql") {
  440     $dbOptions{host}     = $add_sql_host if $add_sql_host ne "";
  441     $dbOptions{port}     = $add_sql_port if $add_sql_port ne "";
  442     $dbOptions{username} = $add_sql_username;
  443     $dbOptions{password} = $add_sql_password;
  444     $dbOptions{database} = $add_sql_database || "webwork_$add_courseID";
  445     $dbOptions{wwhost}   = $add_sql_wwhost;
  446   }
  447 
  448   my @users;
  449   if ($add_initial_userID ne "") {
  450     my $User = $db->newUser(
  451       user_id => $add_initial_userID,
  452       status => "C",
  453     );
  454     my $Password = $db->newPassword(
  455       user_id => $add_initial_userID,
  456       password => cryptPassword($add_initial_password),
  457     );
  458     my $PermissionLevel = $db->newPermissionLevel(
  459       user_id => $add_initial_userID,
  460       permission => "10",
  461     );
  462     push @users, [ $User, $Password, $PermissionLevel ];
  463   }
  464 
  465   eval {
  466     addCourse(
  467       courseID      => $add_courseID,
  468       ce            => $ce2,
  469       courseOptions => \%courseOptions,
  470       dbOptions     => \%dbOptions,
  471       users         => \@users,
  472     );
  473   };
  474 
  475   if ($@) {
  476     my $error = $@;
  477     print CGI::div({class=>"ResultsWithError"},
  478       CGI::p("An error occured while creating the course $add_courseID:"),
  479       CGI::tt(CGI::escapeHTML($error)),
  480     );
  481   } else {
  482     print CGI::div({class=>"ResultsWithoutError"},
  483       CGI::p("Successfully created the course $add_courseID"),
  484     );
  485     my $newCoursePath = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets",
  486       courseID => $add_courseID);
  487     my $newCourseURL = $self->systemLink($newCoursePath, authen => 0);
  488     print CGI::div({style=>"text-align: center"},
  489       CGI::a({href=>$newCourseURL}, "Log into $add_courseID"),
  490     );
  491   }
  492 }
  493 
  494 ################################################################################
  495 
  496 sub delete_course_form {
  497   my ($self) = @_;
  498   my $r = $self->r;
  499   my $ce = $r->ce;
  500   #my $db = $r->db;
  501   #my $authz = $r->authz;
  502   #my $urlpath = $r->urlpath;
  503 
  504   my $delete_courseID     = $r->param("delete_courseID")     || "";
  505   my $delete_sql_host     = $r->param("delete_sql_host")     || "";
  506   my $delete_sql_port     = $r->param("delete_sql_port")     || "";
  507   my $delete_sql_username = $r->param("delete_sql_username") || "";
  508   my $delete_sql_password = $r->param("delete_sql_password") || "";
  509   my $delete_sql_database = $r->param("delete_sql_database")    || "";
  510 
  511   my @courseIDs = listCourses($ce);
  512   @courseIDs    = sort @courseIDs;
  513 
  514   my %courseLabels; # records... heh.
  515   foreach my $courseID (@courseIDs) {
  516     my $tempCE = WeBWorK::CourseEnvironment->new(
  517       $ce->{webworkDirs}->{root},
  518       $ce->{webworkURLs}->{root},
  519       $ce->{pg}->{directories}->{root},
  520       $courseID,
  521     );
  522     $courseLabels{$courseID} = "$courseID (" . $tempCE->{dbLayoutName} . ")";
  523   }
  524 
  525   print CGI::h2("Delete Course");
  526 
  527   print CGI::start_form("POST", $r->uri);
  528   print $self->hidden_authen_fields;
  529   print $self->hidden_fields("subDisplay");
  530 
  531   print CGI::p("Select a course to delete.");
  532 
  533   print CGI::table({class=>"FormLayout"},
  534     CGI::Tr(
  535       CGI::th({class=>"LeftHeader"}, "Course Name:"),
  536       CGI::td(
  537         CGI::scrolling_list(
  538           -name => "delete_courseID",
  539           -values => \@courseIDs,
  540           -default => $delete_courseID,
  541           -size => 10,
  542           -multiple => 0,
  543           -labels => \%courseLabels,
  544         ),
  545       ),
  546     ),
  547   );
  548 
  549   print CGI::p(
  550     "If the course's database layout (indicated in parentheses above) is "
  551     . CGI::b("sql") . ", supply the SQL connections information requested below."
  552   );
  553 
  554   print CGI::start_table({class=>"FormLayout"});
  555   print CGI::Tr(
  556     CGI::th({class=>"LeftHeader"}, "SQL Server Host:"),
  557     CGI::td(
  558       CGI::textfield("delete_sql_host", $delete_sql_host, 25),
  559       CGI::br(),
  560       CGI::small("Leave blank to use the default host."),
  561     ),
  562   );
  563   print CGI::Tr(
  564     CGI::th({class=>"LeftHeader"}, "SQL Server Port:"),
  565     CGI::td(
  566       CGI::textfield("delete_sql_port", $delete_sql_port, 25),
  567       CGI::br(),
  568       CGI::small("Leave blank to use the default port."),
  569     ),
  570   );
  571   print CGI::Tr(
  572     CGI::th({class=>"LeftHeader"}, "SQL Admin Username:"),
  573     CGI::td(CGI::textfield("delete_sql_username", $delete_sql_username, 25)),
  574   );
  575   print CGI::Tr(
  576     CGI::th({class=>"LeftHeader"}, "SQL Admin Password:"),
  577     CGI::td(CGI::password_field("delete_sql_password", $delete_sql_password, 25)),
  578   );
  579   print CGI::Tr(
  580     CGI::th({class=>"LeftHeader"}, "SQL Database Name:"),
  581     CGI::td(CGI::textfield("delete_sql_database", $delete_sql_database, 25)),
  582   );
  583   print CGI::end_table();
  584 
  585   print CGI::p({style=>"text-align: center"}, CGI::submit("delete_course", "Delete Course"));
  586 
  587   print CGI::end_form();
  588 }
  589 
  590 sub delete_course_validate {
  591   my ($self) = @_;
  592   my $r = $self->r;
  593   my $ce = $r->ce;
  594   #my $db = $r->db;
  595   #my $authz = $r->authz;
  596   my $urlpath = $r->urlpath;
  597 
  598   my $delete_courseID     = $r->param("delete_courseID")     || "";
  599   my $delete_sql_host     = $r->param("delete_sql_host")     || "";
  600   my $delete_sql_port     = $r->param("delete_sql_port")     || "";
  601   my $delete_sql_username = $r->param("delete_sql_username") || "";
  602   my $delete_sql_password = $r->param("delete_sql_password") || "";
  603   my $delete_sql_database = $r->param("delete_sql_database") || "";
  604 
  605   my @errors;
  606 
  607   if ($delete_courseID eq "") {
  608     push @errors, "You must specify a course name.";
  609   } elsif ($delete_courseID eq $urlpath->arg("courseID")) {
  610     push @errors, "You cannot delete the course you are currently using.";
  611   }
  612 
  613   my $ce2 = WeBWorK::CourseEnvironment->new(
  614     $ce->{webworkDirs}->{root},
  615     $ce->{webworkURLs}->{root},
  616     $ce->{pg}->{directories}->{root},
  617     $delete_courseID,
  618   );
  619 
  620   if ($ce2->{dbLayoutName} eq "sql") {
  621     push @errors, "You must specify the SQL admin username." if $delete_sql_username eq "";
  622     push @errors, "You must specify the SQL admin password." if $delete_sql_password eq "";
  623     push @errors, "You must specify the SQL database name." if $delete_sql_database eq "";
  624   }
  625 
  626   return @errors;
  627 }
  628 
  629 sub delete_course_confirm {
  630   my ($self) = @_;
  631   my $r = $self->r;
  632   my $ce = $r->ce;
  633   #my $db = $r->db;
  634   #my $authz = $r->authz;
  635   #my $urlpath = $r->urlpath;
  636 
  637   print CGI::h2("Delete Course");
  638 
  639   my $delete_courseID     = $r->param("delete_courseID")     || "";
  640   my $delete_sql_host     = $r->param("delete_sql_host")     || "";
  641   my $delete_sql_port     = $r->param("delete_sql_port")     || "";
  642   my $delete_sql_database = $r->param("delete_sql_database") || "";
  643 
  644   my $ce2 = WeBWorK::CourseEnvironment->new(
  645     $ce->{webworkDirs}->{root},
  646     $ce->{webworkURLs}->{root},
  647     $ce->{pg}->{directories}->{root},
  648     $delete_courseID,
  649   );
  650 
  651   if ($ce2->{dbLayoutName} eq "sql") {
  652     print CGI::p("Are you sure you want to delete the course " . CGI::b($delete_courseID)
  653     . "? All course files and data and the following database will be destroyed."
  654     . " There is no undo available.");
  655 
  656     print CGI::table({class=>"FormLayout"},
  657       CGI::Tr(
  658         CGI::th({class=>"LeftHeader"}, "SQL Server Host:"),
  659         CGI::td($delete_sql_host || "system default"),
  660       ),
  661       CGI::Tr(
  662         CGI::th({class=>"LeftHeader"}, "SQL Server Port:"),
  663         CGI::td($delete_sql_port || "system default"),
  664       ),
  665       CGI::Tr(
  666         CGI::th({class=>"LeftHeader"}, "SQL Database Name:"),
  667         CGI::td($delete_sql_database),
  668       ),
  669     );
  670   } else {
  671     print CGI::p("Are you sure you want to delete the course " . CGI::b($delete_courseID)
  672       . "? All course files and data will be destroyed. There is no undo available.");
  673   }
  674 
  675   print CGI::start_form("POST", $r->uri);
  676   print $self->hidden_authen_fields;
  677   print $self->hidden_fields("subDisplay");
  678   print $self->hidden_fields(qw/delete_courseID delete_sql_host delete_sql_port delete_sql_username delete_sql_password delete_sql_database/);
  679 
  680   print CGI::p({style=>"text-align: center"},
  681     CGI::submit("decline_delete_course", "Don't delete"),
  682     "&nbsp;",
  683     CGI::submit("confirm_delete_course", "Delete"),
  684   );
  685 
  686   print CGI::end_form();
  687 }
  688 
  689 sub do_delete_course {
  690   my ($self) = @_;
  691   my $r = $self->r;
  692   my $ce = $r->ce;
  693   #my $db = $r->db;
  694   #my $authz = $r->authz;
  695   #my $urlpath = $r->urlpath;
  696 
  697   my $delete_courseID     = $r->param("delete_courseID")     || "";
  698   my $delete_sql_host     = $r->param("delete_sql_host")     || "";
  699   my $delete_sql_port     = $r->param("delete_sql_port")     || "";
  700   my $delete_sql_username = $r->param("delete_sql_username") || "";
  701   my $delete_sql_password = $r->param("delete_sql_password") || "";
  702   my $delete_sql_database = $r->param("delete_sql_database") || "";
  703 
  704   my $ce2 = WeBWorK::CourseEnvironment->new(
  705     $ce->{webworkDirs}->{root},
  706     $ce->{webworkURLs}->{root},
  707     $ce->{pg}->{directories}->{root},
  708     $delete_courseID,
  709   );
  710 
  711   my %dbOptions;
  712   if ($ce2->{dbLayoutName} eq "sql") {
  713     $dbOptions{host}     = $delete_sql_host if $delete_sql_host ne "";
  714     $dbOptions{port}     = $delete_sql_port if $delete_sql_port ne "";
  715     $dbOptions{username} = $delete_sql_username;
  716     $dbOptions{password} = $delete_sql_password;
  717     $dbOptions{database} = $delete_sql_database;
  718   }
  719 
  720   eval {
  721     deleteCourse(
  722       courseID => $delete_courseID,
  723       ce => $ce2,
  724       dbOptions => \%dbOptions,
  725     );
  726   };
  727 
  728   if ($@) {
  729     my $error = $@;
  730     print CGI::div({class=>"ResultsWithError"},
  731       CGI::p("An error occured while deleting the course $delete_courseID:"),
  732       CGI::tt(CGI::escapeHTML($error)),
  733     );
  734   } else {
  735     print CGI::div({class=>"ResultsWithoutError"},
  736       CGI::p("Possibly deleted the course $delete_courseID. (We need better error checking in deleteCourse().)"),
  737     );
  738 
  739     print CGI::start_form("POST", $r->uri);
  740     print $self->hidden_authen_fields;
  741     print $self->hidden_fields("subDisplay");
  742 
  743     print CGI::p({style=>"text-align: center"}, CGI::submit("decline_delete_course", "OK"),);
  744 
  745     print CGI::end_form();
  746   }
  747 }
  748 
  749 ################################################################################
  750 
  751 sub export_database_form {
  752   my ($self) = @_;
  753   my $r = $self->r;
  754   my $ce = $r->ce;
  755   #my $db = $r->db;
  756   #my $authz = $r->authz;
  757   #my $urlpath = $r->urlpath;
  758 
  759   my @tables = keys %{$ce->{dbLayout}};
  760 
  761   my $export_courseID = $r->param("export_courseID") || "";
  762   my @export_tables   = $r->param("export_tables");
  763 
  764   @export_tables = @tables unless @export_tables;
  765 
  766   my @courseIDs = listCourses($ce);
  767   @courseIDs    = sort @courseIDs;
  768 
  769   my %courseLabels; # records... heh.
  770   foreach my $courseID (@courseIDs) {
  771     my $tempCE = WeBWorK::CourseEnvironment->new(
  772       $ce->{webworkDirs}->{root},
  773       $ce->{webworkURLs}->{root},
  774       $ce->{pg}->{directories}->{root},
  775       $courseID,
  776     );
  777     $courseLabels{$courseID} = "$courseID (" . $tempCE->{dbLayoutName} . ")";
  778   }
  779 
  780   print CGI::h2("Export Database");
  781 
  782   print CGI::start_form("POST", $r->uri);
  783   print $self->hidden_authen_fields;
  784   print $self->hidden_fields("subDisplay");
  785 
  786   print CGI::p("Select a course to export the course's database.");
  787 
  788   print CGI::table({class=>"FormLayout"},
  789     CGI::Tr(
  790       CGI::th({class=>"LeftHeader"}, "Course Name:"),
  791       CGI::td(
  792         CGI::scrolling_list(
  793           -name => "export_courseID",
  794           -values => \@courseIDs,
  795           -default => $export_courseID,
  796           -size => 10,
  797           -multiple => 0,
  798           -labels => \%courseLabels,
  799         ),
  800       ),
  801     ),
  802     CGI::Tr(
  803       CGI::th({class=>"LeftHeader"}, "Tables to Export:"),
  804       CGI::td(
  805         CGI::checkbox_group(
  806           -name => "export_tables",
  807           -values => \@tables,
  808           -default => \@export_tables,
  809           -linebreak => 1,
  810         ),
  811       ),
  812     ),
  813   );
  814 
  815   print CGI::p({style=>"text-align: center"}, CGI::submit("export_database", "Export Database"));
  816 
  817   print CGI::end_form();
  818 }
  819 
  820 sub export_database_validate {
  821   my ($self) = @_;
  822   my $r = $self->r;
  823   #my $ce = $r->ce;
  824   #my $db = $r->db;
  825   #my $authz = $r->authz;
  826   #my $urlpath = $r->urlpath;
  827 
  828   my $export_courseID = $r->param("export_courseID") || "";
  829   my @export_tables   = $r->param("export_tables");
  830 
  831   my @errors;
  832 
  833   if ($export_courseID eq "") {
  834     push @errors, "You must specify a course name.";
  835   }
  836 
  837   unless (@export_tables) {
  838     push @errors, "You must specify at least one table to export.";
  839   }
  840 
  841   return @errors;
  842 }
  843 
  844 sub do_export_database {
  845   my ($self) = @_;
  846   my $r = $self->r;
  847   my $ce = $r->ce;
  848   #my $db = $r->db;
  849   #my $authz = $r->authz;
  850   my $urlpath = $r->urlpath;
  851 
  852   my $export_courseID = $r->param("export_courseID");
  853   my @export_tables   = $r->param("export_tables");
  854 
  855   my $ce2 = WeBWorK::CourseEnvironment->new(
  856     $ce->{webworkDirs}->{root},
  857     $ce->{webworkURLs}->{root},
  858     $ce->{pg}->{directories}->{root},
  859     $export_courseID,
  860   );
  861 
  862   my $db2 = new WeBWorK::DB($ce2->{dbLayout});
  863 
  864   my ($fh, $export_file) = tempfile("db_export_XXXXXX", DIR => $ce->{webworkDirs}->{tmp});
  865   my ($random_chars) = $export_file =~ m/db_export_(\w+)$/;
  866 
  867   my @errors;
  868 
  869   eval {
  870     @errors = dbExport(
  871       db => $db2,
  872       xml => $fh,
  873       tables => \@export_tables,
  874     );
  875   };
  876 
  877   push @errors, "Fatal exception: $@" if $@;
  878 
  879   if (@errors) {
  880     print CGI::div({class=>"ResultsWithError"},
  881       CGI::p("An error occured while exporting the database of course $export_courseID:"),
  882       CGI::ul(CGI::li(\@errors)),
  883     );
  884   } else {
  885     print CGI::div({class=>"ResultsWithoutError"},
  886       CGI::p("Export succeeded."),
  887     );
  888 
  889     print CGI::div({style=>"text-align: center"},
  890       CGI::a({href=>$self->systemLink($urlpath, params=>{download_exported_database=>$random_chars, export_courseID=>undef})}, "Download Exported Database"),
  891     );
  892   }
  893 }
  894 
  895 ################################################################################
  896 
  897 sub import_database_form {
  898   my ($self) = @_;
  899   my $r = $self->r;
  900   my $ce = $r->ce;
  901   #my $db = $r->db;
  902   #my $authz = $r->authz;
  903   #my $urlpath = $r->urlpath;
  904 
  905   my @tables = keys %{$ce->{dbLayout}};
  906 
  907   my $import_file     = $r->param("import_file")     || "";
  908   my $import_courseID = $r->param("import_courseID") || "";
  909   my @import_tables   = $r->param("import_tables");
  910   my $import_conflict = $r->param("import_conflict") || "skip";
  911 
  912   @import_tables = @tables unless @import_tables;
  913 
  914   my @courseIDs = listCourses($ce);
  915   @courseIDs    = sort @courseIDs;
  916 
  917 
  918   my %courseLabels; # records... heh.
  919   foreach my $courseID (@courseIDs) {
  920     my $tempCE = WeBWorK::CourseEnvironment->new(
  921       $ce->{webworkDirs}->{root},
  922       $ce->{webworkURLs}->{root},
  923       $ce->{pg}->{directories}->{root},
  924       $courseID,
  925     );
  926     $courseLabels{$courseID} = "$courseID (" . $tempCE->{dbLayoutName} . ")";
  927   }
  928 
  929   print CGI::h2("Import Database");
  930 
  931   print CGI::start_form("POST", $r->uri, &CGI::MULTIPART);
  932   print $self->hidden_authen_fields;
  933   print $self->hidden_fields("subDisplay");
  934 
  935   print CGI::table({class=>"FormLayout"},
  936     CGI::Tr(
  937       CGI::th({class=>"LeftHeader"}, "Database XML File:"),
  938       CGI::td(
  939         CGI::filefield(
  940           -name => "import_file",
  941           -size => 50,
  942         ),
  943       ),
  944     ),
  945     CGI::Tr(
  946       CGI::th({class=>"LeftHeader"}, "Tables to Import:"),
  947       CGI::td(
  948         CGI::checkbox_group(
  949           -name => "import_tables",
  950           -values => \@tables,
  951           -default => \@import_tables,
  952           -linebreak => 1,
  953         ),
  954       ),
  955     ),
  956     CGI::Tr(
  957       CGI::th({class=>"LeftHeader"}, "Import into Course:"),
  958       CGI::td(
  959         CGI::scrolling_list(
  960           -name => "import_courseID",
  961           -values => \@courseIDs,
  962           -default => $import_courseID,
  963           -size => 10,
  964           -multiple => 0,
  965           -labels => \%courseLabels,
  966         ),
  967       ),
  968     ),
  969     CGI::Tr(
  970       CGI::th({class=>"LeftHeader"}, "Conflicts:"),
  971       CGI::td(
  972         CGI::radio_group(
  973           -name => "import_conflict",
  974           -values => [qw/skip replace/],
  975           -default => $import_conflict,
  976           -linebreak=>'true',
  977           -labels => {
  978             skip => "Skip duplicate records",
  979             replace => "Replace duplicate records",
  980           },
  981         ),
  982       ),
  983     ),
  984   );
  985 
  986   print CGI::p({style=>"text-align: center"}, CGI::submit("import_database", "Import Database"));
  987 
  988   print CGI::end_form();
  989 }
  990 
  991 sub import_database_validate {
  992   my ($self) = @_;
  993   my $r = $self->r;
  994   #my $ce = $r->ce;
  995   #my $db = $r->db;
  996   #my $authz = $r->authz;
  997   #my $urlpath = $r->urlpath;
  998 
  999   my $import_file     = $r->param("import_file")     || "";
 1000   my $import_courseID = $r->param("import_courseID") || "";
 1001   my @import_tables   = $r->param("import_tables");
 1002   #my $import_conflict = $r->param("import_conflict") || "skip"; # not checked
 1003 
 1004   my @errors;
 1005 
 1006   if ($import_file eq "") {
 1007     push @errors, "You must specify a database file to upload.";
 1008   }
 1009 
 1010   if ($import_courseID eq "") {
 1011     push @errors, "You must specify a course name.";
 1012   }
 1013 
 1014   unless (@import_tables) {
 1015     push @errors, "You must specify at least one table to import.";
 1016   }
 1017 
 1018   return @errors;
 1019 }
 1020 
 1021 sub do_import_database {
 1022   my ($self) = @_;
 1023   my $r = $self->r;
 1024   my $ce = $r->ce;
 1025   #my $db = $r->db;
 1026   #my $authz = $r->authz;
 1027   my $urlpath = $r->urlpath;
 1028 
 1029   my $import_file     = $r->param("import_file");
 1030   my $import_courseID = $r->param("import_courseID");
 1031   my @import_tables   = $r->param("import_tables");
 1032   my $import_conflict = $r->param("import_conflict") || "skip"; # need default -- not checked above
 1033 
 1034   my $ce2 = WeBWorK::CourseEnvironment->new(
 1035     $ce->{webworkDirs}->{root},
 1036     $ce->{webworkURLs}->{root},
 1037     $ce->{pg}->{directories}->{root},
 1038     $import_courseID,
 1039   );
 1040 
 1041   my $db2 = new WeBWorK::DB($ce2->{dbLayout});
 1042 
 1043   # retrieve upload from upload cache
 1044   my ($id, $hash) = split /\s+/, $import_file;
 1045   my $upload = WeBWorK::Upload->retrieve($id, $hash,
 1046     dir => $ce->{webworkDirs}->{uploadCache}
 1047   );
 1048 
 1049   my @errors;
 1050 
 1051   eval {
 1052     @errors = dbImport(
 1053       db => $db2,
 1054       xml => $upload->fileHandle,
 1055       tables => \@import_tables,
 1056       conflict => $import_conflict,
 1057     );
 1058   };
 1059 
 1060   $upload->dispose;
 1061 
 1062   push @errors, "Fatal exception: $@" if $@;
 1063 
 1064   if (@errors) {
 1065     print CGI::div({class=>"ResultsWithError"},
 1066       CGI::p("An error occured while importing the database of course $import_courseID:"),
 1067       CGI::ul(CGI::li(\@errors)),
 1068     );
 1069   } else {
 1070     print CGI::div({class=>"ResultsWithoutError"},
 1071       CGI::p("Import succeeded."),
 1072     );
 1073   }
 1074 }
 1075 
 1076 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9