Parent Directory
|
Revision Log
HEAD backport: Fixed small bug in the message passing facility Changed message passing when there is a duplicate administrator. (gage)
1 ################################################################################ 2 # WeBWorK Online Homework Delivery System 3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/ 4 # $CVSHeader: webwork2/lib/WeBWorK/ContentGenerator/CourseAdmin.pm,v 1.31 2004/10/10 21:04:47 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 writeLog); 33 use WeBWorK::Utils::CourseManagement qw(addCourse deleteCourse listCourses); 34 use WeBWorK::Utils::DBImportExport qw(dbExport dbImport); 35 36 # put the following database layouts at the top of the list, in this order 37 our @DB_LAYOUT_ORDER = qw/sql_single gdbm sql/; 38 39 our %DB_LAYOUT_DESCRIPTIONS = ( 40 gdbm => "Deprecated. Uses GDBM databases to record WeBWorK data. Use this layout if the course must be used with WeBWorK 1.x.", 41 sql => "Deprecated. Uses a separate SQL database to record WeBWorK data for each course.", 42 sql_single => "Uses a single SQL database to record WeBWorK data for all courses using this layout. This is the recommended layout for new courses.", 43 ); 44 45 sub pre_header_initialize { 46 my ($self) = @_; 47 my $r = $self->r; 48 my $ce = $r->ce; 49 my $db = $r->db; 50 my $authz = $r->authz; 51 my $urlpath = $r->urlpath; 52 my $user = $r->param('user'); 53 54 # check permissions 55 unless ($authz->hasPermissions($user, "create_and_delete_courses")) { 56 $self->addmessage( CGI::div({class=>'ResultsWithError'},"$user is not authorized to create or delete courses") ); 57 return; 58 } 59 60 # get result and send to message 61 my $status_message = $r->param("status_message"); 62 $self->addmessage(CGI::p("$status_message")) if $status_message; 63 64 ## if the user is asking for the downloaded database... 65 #if (defined $r->param("download_exported_database")) { 66 # my $courseID = $r->param("export_courseID"); 67 # my $random_chars = $r->param("download_exported_database"); 68 # 69 # die "courseID not specified" unless defined $courseID; 70 # die "invalid file specification" unless $random_chars =~ m/^\w+$/; 71 # 72 # my $tempdir = $ce->{webworkDirs}->{tmp}; 73 # my $export_file = "$tempdir/db_export_$random_chars"; 74 # 75 # $self->reply_with_file("application/xml", $export_file, "${courseID}_database.xml", 0); 76 # 77 # return ""; 78 #} 79 # 80 ## otherwise... 81 82 my @errors; 83 my $method_to_call; 84 85 my $subDisplay = $r->param("subDisplay"); 86 if (defined $subDisplay) { 87 88 if ($subDisplay eq "add_course") { 89 if (defined $r->param("add_course")) { 90 @errors = $self->add_course_validate; 91 if (@errors) { 92 $method_to_call = "add_course_form"; 93 } else { 94 $method_to_call = "do_add_course"; 95 } 96 } else { 97 $method_to_call = "add_course_form"; 98 } 99 } 100 101 elsif ($subDisplay eq "delete_course") { 102 if (defined $r->param("delete_course")) { 103 # validate or confirm 104 @errors = $self->delete_course_validate; 105 if (@errors) { 106 $method_to_call = "delete_course_form"; 107 } else { 108 $method_to_call = "delete_course_confirm"; 109 } 110 } elsif (defined $r->param("confirm_delete_course")) { 111 # validate and delete 112 @errors = $self->delete_course_validate; 113 if (@errors) { 114 $method_to_call = "delete_course_form"; 115 } else { 116 $method_to_call = "do_delete_course"; 117 } 118 } else { 119 # form only 120 $method_to_call = "delete_course_form"; 121 } 122 } 123 124 elsif ($subDisplay eq "export_database") { 125 if (defined $r->param("export_database")) { 126 @errors = $self->export_database_validate; 127 if (@errors) { 128 $method_to_call = "export_database_form"; 129 } else { 130 # we have to do something special here, since we're sending 131 # the database as we export it. $method_to_call still gets 132 # set here, but it gets caught by header() and content() 133 # below instead of by body(). 134 $method_to_call = "do_export_database"; 135 } 136 } else { 137 $method_to_call = "export_database_form"; 138 } 139 } 140 141 elsif ($subDisplay eq "import_database") { 142 if (defined $r->param("import_database")) { 143 @errors = $self->import_database_validate; 144 if (@errors) { 145 $method_to_call = "import_database_form"; 146 } else { 147 $method_to_call = "do_import_database"; 148 } 149 } else { 150 $method_to_call = "import_database_form"; 151 } 152 } 153 154 else { 155 @errors = "Unrecognized sub-display @{[ CGI::b($subDisplay) ]}."; 156 } 157 158 } 159 160 $self->{errors} = \@errors; 161 $self->{method_to_call} = $method_to_call; 162 } 163 164 sub header { 165 my ($self) = @_; 166 my $method_to_call = $self->{method_to_call}; 167 if (defined $method_to_call and $method_to_call eq "do_export_database") { 168 my $r = $self->r; 169 my $courseID = $r->param("export_courseID"); 170 $r->content_type("application/octet-stream"); 171 $r->header_out("Content-Disposition" => "attachment; filename=\"${courseID}_database.xml\""); 172 $r->send_http_header; 173 } else { 174 $self->SUPER::header; 175 } 176 } 177 178 # sends: 179 # 180 # HTTP/1.1 200 OK 181 # Date: Fri, 09 Jul 2004 19:05:55 GMT 182 # Server: Apache/1.3.27 (Unix) mod_perl/1.27 183 # Content-Disposition: attachment; filename="mth143_database.xml" 184 # Connection: close 185 # Content-Type: application/octet-stream 186 187 sub content { 188 my ($self) = @_; 189 my $method_to_call = $self->{method_to_call}; 190 if (defined $method_to_call and $method_to_call eq "do_export_database") { 191 $self->do_export_database; 192 } else { 193 $self->SUPER::content; 194 } 195 } 196 197 sub body { 198 my ($self) = @_; 199 my $r = $self->r; 200 my $ce = $r->ce; 201 my $db = $r->db; 202 my $authz = $r->authz; 203 my $urlpath = $r->urlpath; 204 205 my $user = $r->param('user'); 206 207 # check permissions 208 unless ($authz->hasPermissions($user, "create_and_delete_courses")) { 209 return ""; 210 } 211 212 print CGI::p({style=>"text-align: center"}, 213 CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"add_course"})}, "Add Course"), 214 " | ", 215 CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"delete_course"})}, "Delete Course"), 216 " | ", 217 CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"export_database"})}, "Export Database"), 218 " | ", 219 CGI::a({href=>$self->systemLink($urlpath, params=>{subDisplay=>"import_database"})}, "Import Database"), 220 ); 221 222 print CGI::hr(); 223 224 my @errors = @{$self->{errors}}; 225 my $method_to_call = $self->{method_to_call}; 226 227 if (@errors) { 228 print CGI::div({class=>"ResultsWithError"}, 229 CGI::p("Please correct the following errors and try again:"), 230 CGI::ul(CGI::li(\@errors)), 231 ); 232 } 233 234 if (defined $method_to_call and $method_to_call ne "") { 235 $self->$method_to_call; 236 } 237 238 return ""; 239 } 240 241 ################################################################################ 242 243 sub add_course_form { 244 my ($self) = @_; 245 my $r = $self->r; 246 my $ce = $r->ce; 247 #my $db = $r->db; 248 #my $authz = $r->authz; 249 #my $urlpath = $r->urlpath; 250 251 my $add_courseID = $r->param("add_courseID") || ""; 252 my $add_courseTitle = $r->param("add_courseTitle") || ""; 253 my $add_courseInstitution = $r->param("add_courseInstitution") || ""; 254 255 my $add_admin_users = $r->param("add_admin_users") || ""; 256 257 my $add_initial_userID = $r->param("add_initial_userID") || ""; 258 my $add_initial_password = $r->param("add_initial_password") || ""; 259 my $add_initial_confirmPassword = $r->param("add_initial_confirmPassword") || ""; 260 my $add_initial_firstName = $r->param("add_initial_firstName") || ""; 261 my $add_initial_lastName = $r->param("add_initial_lastName") || ""; 262 my $add_initial_email = $r->param("add_initial_email") || ""; 263 264 my $add_templates_course = $r->param("add_templates_course") || ""; 265 266 my $add_dbLayout = $r->param("add_dbLayout") || ""; 267 my $add_sql_host = $r->param("add_sql_host") || ""; 268 my $add_sql_port = $r->param("add_sql_port") || ""; 269 my $add_sql_username = $r->param("add_sql_username") || ""; 270 my $add_sql_password = $r->param("add_sql_password") || ""; 271 my $add_sql_database = $r->param("add_sql_database") || ""; 272 my $add_sql_wwhost = $r->param("add_sql_wwhost") || ""; 273 my $add_gdbm_globalUserID = $r->param("add_gdbm_globalUserID") || ""; 274 275 my @dbLayouts = do { 276 my @ordered_layouts; 277 foreach my $layout (@DB_LAYOUT_ORDER) { 278 if (exists $ce->{dbLayouts}->{$layout}) { 279 push @ordered_layouts, $layout; 280 } 281 } 282 283 my %ordered_layouts; @ordered_layouts{@ordered_layouts} = (); 284 my @other_layouts; 285 foreach my $layout (keys %{ $ce->{dbLayouts} }) { 286 unless (exists $ordered_layouts{$layout}) { 287 push @other_layouts, $layout; 288 } 289 } 290 291 (@ordered_layouts, @other_layouts); 292 }; 293 294 my $ce2 = WeBWorK::CourseEnvironment->new( 295 $ce->{webworkDirs}->{root}, 296 $ce->{webworkURLs}->{root}, 297 $ce->{pg}->{directories}->{root}, 298 "COURSENAME", 299 ); 300 301 my $dbi_source = do { 302 # find the most common SQL source (stolen from CourseManagement.pm) 303 my %sources; 304 foreach my $table (keys %{ $ce2->{dbLayouts}->{sql} }) { 305 $sources{$ce2->{dbLayouts}->{sql}->{$table}->{source}}++; 306 } 307 my $source; 308 if (keys %sources > 1) { 309 foreach my $curr (keys %sources) { 310 $source = $curr if not defined $source or 311 $sources{$curr} > $sources{$source}; 312 } 313 } else { 314 ($source) = keys %sources; 315 } 316 $source; 317 }; 318 319 my @existingCourses = listCourses($ce); 320 @existingCourses = sort @existingCourses; 321 322 print CGI::h2("Add Course"); 323 324 print CGI::start_form("POST", $r->uri); 325 print $self->hidden_authen_fields; 326 print $self->hidden_fields("subDisplay"); 327 328 print CGI::p("Specify an ID, title, and institution for the new course. The course ID may contain only letters, numbers, hyphens, and underscores."); 329 330 print CGI::table({class=>"FormLayout"}, 331 CGI::Tr( 332 CGI::th({class=>"LeftHeader"}, "Course ID:"), 333 CGI::td(CGI::textfield("add_courseID", $add_courseID, 25)), 334 ), 335 CGI::Tr( 336 CGI::th({class=>"LeftHeader"}, "Course Title:"), 337 CGI::td(CGI::textfield("add_courseTitle", $add_courseTitle, 25)), 338 ), 339 CGI::Tr( 340 CGI::th({class=>"LeftHeader"}, "Institution:"), 341 CGI::td(CGI::textfield("add_courseInstitution", $add_courseInstitution, 25)), 342 ), 343 ); 344 345 print CGI::p("To add the WeBWorK administrators to the new course (as instructors) check the box below."); 346 347 print CGI::p(CGI::checkbox("add_admin_users", $add_admin_users, "on", "Add WeBWorK administrators to new course")); 348 349 print CGI::p("To add an additional instructor to the new course, specify user information below. The user ID may contain only numbers, letters, hyphens, and underscores."); 350 351 print CGI::table({class=>"FormLayout"}, CGI::Tr( 352 CGI::td( 353 CGI::table({class=>"FormLayout"}, 354 CGI::Tr( 355 CGI::th({class=>"LeftHeader"}, "User ID:"), 356 CGI::td(CGI::textfield("add_initial_userID", $add_initial_userID, 25)), 357 ), 358 CGI::Tr( 359 CGI::th({class=>"LeftHeader"}, "Password:"), 360 CGI::td(CGI::password_field("add_initial_password", $add_initial_password, 25)), 361 ), 362 CGI::Tr( 363 CGI::th({class=>"LeftHeader"}, "Confirm Password:"), 364 CGI::td(CGI::password_field("add_initial_confirmPassword", $add_initial_confirmPassword, 25)), 365 ), 366 ), 367 ), 368 CGI::td( 369 CGI::table({class=>"FormLayout"}, 370 CGI::Tr( 371 CGI::th({class=>"LeftHeader"}, "First Name:"), 372 CGI::td(CGI::textfield("add_initial_firstName", $add_initial_firstName, 25)), 373 ), 374 CGI::Tr( 375 CGI::th({class=>"LeftHeader"}, "Last Name:"), 376 CGI::td(CGI::textfield("add_initial_lastName", $add_initial_lastName, 25)), 377 ), 378 CGI::Tr( 379 CGI::th({class=>"LeftHeader"}, "Email Address:"), 380 CGI::td(CGI::textfield("add_initial_email", $add_initial_email, 25)), 381 ), 382 ), 383 384 ), 385 )); 386 387 print CGI::p("To copy problem templates from an existing course, select the course below."); 388 389 print CGI::table({class=>"FormLayout"}, 390 CGI::Tr( 391 CGI::th({class=>"LeftHeader"}, "Copy templates from:"), 392 CGI::td( 393 CGI::popup_menu( 394 -name => "add_templates_course", 395 -values => [ "", @existingCourses ], 396 -default => $add_templates_course, 397 #-size => 10, 398 #-multiple => 0, 399 #-labels => \%courseLabels, 400 ), 401 402 ), 403 ), 404 ); 405 406 print CGI::p("Select a database layout below."); 407 408 foreach my $dbLayout (@dbLayouts) { 409 print CGI::start_table({class=>"FormLayout"}); 410 411 my $dbLayoutLabel = (defined $DB_LAYOUT_DESCRIPTIONS{$dbLayout}) 412 ? "$dbLayout - $DB_LAYOUT_DESCRIPTIONS{$dbLayout}" 413 : $dbLayout; 414 415 # we generate singleton radio button tags ourselves because it's too much of a pain to do it with CGI.pm 416 print CGI::Tr( 417 CGI::td({style=>"text-align: right"}, 418 '<input type="radio" name="add_dbLayout" value="' . $dbLayout . '"' 419 . ($add_dbLayout eq $dbLayout ? " checked" : "") . ' />', 420 ), 421 CGI::td($dbLayoutLabel), 422 ); 423 424 print CGI::start_Tr(); 425 print CGI::td(); # for indentation :( 426 print CGI::start_td(); 427 428 if ($dbLayout eq "sql") { 429 print CGI::start_table({class=>"FormLayout"}); 430 print CGI::Tr(CGI::td({colspan=>2}, 431 "Enter the user ID and password for an SQL account with sufficient permissions to create a new database." 432 ) 433 ); 434 print CGI::Tr( 435 CGI::th({class=>"LeftHeader"}, "SQL Admin Username:"), 436 CGI::td(CGI::textfield("add_sql_username", $add_sql_username, 25)), 437 ); 438 print CGI::Tr( 439 CGI::th({class=>"LeftHeader"}, "SQL Admin Password:"), 440 CGI::td(CGI::password_field("add_sql_password", $add_sql_password, 25)), 441 ); 442 443 print CGI::Tr(CGI::td({colspan=>2}, 444 "The optionial SQL settings you enter below must match the settings in the DBI source" 445 . " specification " . CGI::tt($dbi_source) . ". Replace " . CGI::tt("COURSENAME") 446 . " with the course name you entered above." 447 ) 448 ); 449 print CGI::Tr( 450 CGI::th({class=>"LeftHeader"}, "SQL Server Host:"), 451 CGI::td( 452 CGI::textfield("add_sql_host", $add_sql_host, 25), 453 CGI::br(), 454 CGI::small("Leave blank to use the default host."), 455 ), 456 ); 457 print CGI::Tr( 458 CGI::th({class=>"LeftHeader"}, "SQL Server Port:"), 459 CGI::td( 460 CGI::textfield("add_sql_port", $add_sql_port, 25), 461 CGI::br(), 462 CGI::small("Leave blank to use the default port."), 463 ), 464 ); 465 466 print CGI::Tr( 467 CGI::th({class=>"LeftHeader"}, "SQL Database Name:"), 468 CGI::td( 469 CGI::textfield("add_sql_database", $add_sql_database, 25), 470 CGI::br(), 471 CGI::small("Leave blank to use the name ", CGI::tt("webwork_COURSENAME"), "."), 472 ), 473 ); 474 print CGI::Tr( 475 CGI::th({class=>"LeftHeader"}, "WeBWorK Host:"), 476 CGI::td( 477 CGI::textfield("add_sql_wwhost", $add_sql_wwhost || "localhost", 25), 478 CGI::br(), 479 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."), 480 ), 481 ); 482 print CGI::end_table(); 483 } elsif ($dbLayout eq "gdbm") { 484 print CGI::start_table({class=>"FormLayout"}); 485 print CGI::Tr( 486 CGI::th({class=>"LeftHeader"}, "GDBM Global User ID:"), 487 CGI::td(CGI::textfield("add_gdbm_globalUserID", $add_gdbm_globalUserID || "global_user", 25)), 488 ); 489 print CGI::end_table(); 490 } 491 492 print CGI::end_td(); 493 print CGI::end_Tr(); 494 print CGI::end_table(); 495 } 496 497 print CGI::p({style=>"text-align: center"}, CGI::submit("add_course", "Add Course")); 498 499 print CGI::end_form(); 500 } 501 502 sub add_course_validate { 503 my ($self) = @_; 504 my $r = $self->r; 505 my $ce = $r->ce; 506 #my $db = $r->db; 507 #my $authz = $r->authz; 508 #my $urlpath = $r->urlpath; 509 510 my $add_courseID = $r->param("add_courseID") || ""; 511 my $add_courseTitle = $r->param("add_courseTitle") || ""; 512 my $add_courseInstitution = $r->param("add_courseInstitution") || ""; 513 514 my $add_admin_users = $r->param("add_admin_users") || ""; 515 516 my $add_initial_userID = $r->param("add_initial_userID") || ""; 517 my $add_initial_password = $r->param("add_initial_password") || ""; 518 my $add_initial_confirmPassword = $r->param("add_initial_confirmPassword") || ""; 519 my $add_initial_firstName = $r->param("add_initial_firstName") || ""; 520 my $add_initial_lastName = $r->param("add_initial_lastName") || ""; 521 my $add_initial_email = $r->param("add_initial_email") || ""; 522 523 my $add_templates_course = $r->param("add_templates_course") || ""; 524 525 my $add_dbLayout = $r->param("add_dbLayout") || ""; 526 my $add_sql_host = $r->param("add_sql_host") || ""; 527 my $add_sql_port = $r->param("add_sql_port") || ""; 528 my $add_sql_username = $r->param("add_sql_username") || ""; 529 my $add_sql_password = $r->param("add_sql_password") || ""; 530 my $add_sql_database = $r->param("add_sql_database") || ""; 531 my $add_sql_wwhost = $r->param("add_sql_wwhost") || ""; 532 my $add_gdbm_globalUserID = $r->param("add_gdbm_globalUserID") || ""; 533 534 my @errors; 535 536 if ($add_courseID eq "") { 537 push @errors, "You must specify a course ID."; 538 } 539 unless ($add_courseID =~ /^[\w-]*$/) { # regex copied from CourseAdministration.pm 540 push @errors, "Course ID may only contain letters, numbers, hyphens, and underscores."; 541 } 542 if (grep { $add_courseID eq $_ } listCourses($ce)) { 543 push @errors, "A course with ID $add_courseID already exists."; 544 } 545 if ($add_courseTitle eq "") { 546 push @errors, "You must specify a course title."; 547 } 548 if ($add_courseInstitution eq "") { 549 push @errors, "You must specify an institution for this course."; 550 } 551 552 if ($add_initial_userID ne "") { 553 if ($add_initial_password eq "") { 554 push @errors, "You must specify a password for the initial instructor."; 555 } 556 if ($add_initial_confirmPassword eq "") { 557 push @errors, "You must confirm the password for the initial instructor."; 558 } 559 if ($add_initial_password ne $add_initial_confirmPassword) { 560 push @errors, "The password and password confirmation for the instructor must match."; 561 } 562 if ($add_initial_firstName eq "") { 563 push @errors, "You must specify a first name for the initial instructor."; 564 } 565 if ($add_initial_lastName eq "") { 566 push @errors, "You must specify a last name for the initial instructor."; 567 } 568 if ($add_initial_email eq "") { 569 push @errors, "You must specify an email address for the initial instructor."; 570 } 571 } 572 573 if ($add_dbLayout eq "") { 574 push @errors, "You must select a database layout."; 575 } else { 576 if (exists $ce->{dbLayouts}->{$add_dbLayout}) { 577 if ($add_dbLayout eq "sql") { 578 push @errors, "You must specify the SQL admin username." if $add_sql_username eq ""; 579 push @errors, "You must specify the WeBWorK host." if $add_sql_wwhost eq ""; 580 } elsif ($add_dbLayout eq "gdbm") { 581 push @errors, "You must specify the GDBM global user ID." if $add_gdbm_globalUserID eq ""; 582 } 583 } else { 584 push @errors, "The database layout $add_dbLayout doesn't exist."; 585 } 586 } 587 588 return @errors; 589 } 590 591 sub do_add_course { 592 my ($self) = @_; 593 my $r = $self->r; 594 my $ce = $r->ce; 595 my $db = $r->db; 596 #my $authz = $r->authz; 597 my $urlpath = $r->urlpath; 598 599 my $add_courseID = $r->param("add_courseID") || ""; 600 my $add_courseTitle = $r->param("add_courseTitle") || ""; 601 my $add_courseInstitution = $r->param("add_courseInstitution") || ""; 602 603 my $add_admin_users = $r->param("add_admin_users") || ""; 604 605 my $add_initial_userID = $r->param("add_initial_userID") || ""; 606 my $add_initial_password = $r->param("add_initial_password") || ""; 607 my $add_initial_confirmPassword = $r->param("add_initial_confirmPassword") || ""; 608 my $add_initial_firstName = $r->param("add_initial_firstName") || ""; 609 my $add_initial_lastName = $r->param("add_initial_lastName") || ""; 610 my $add_initial_email = $r->param("add_initial_email") || ""; 611 612 my $add_templates_course = $r->param("add_templates_course") || ""; 613 614 my $add_dbLayout = $r->param("add_dbLayout") || ""; 615 my $add_sql_host = $r->param("add_sql_host") || ""; 616 my $add_sql_port = $r->param("add_sql_port") || ""; 617 my $add_sql_username = $r->param("add_sql_username") || ""; 618 my $add_sql_password = $r->param("add_sql_password") || ""; 619 my $add_sql_database = $r->param("add_sql_database") || ""; 620 my $add_sql_wwhost = $r->param("add_sql_wwhost") || ""; 621 my $add_gdbm_globalUserID = $r->param("add_gdbm_globalUserID") || ""; 622 623 my $ce2 = WeBWorK::CourseEnvironment->new( 624 $ce->{webworkDirs}->{root}, 625 $ce->{webworkURLs}->{root}, 626 $ce->{pg}->{directories}->{root}, 627 $add_courseID, 628 ); 629 630 my %courseOptions = ( dbLayoutName => $add_dbLayout ); 631 632 if ($add_initial_email ne "") { 633 $courseOptions{allowedRecipients} = [ $add_initial_email ]; 634 # don't set feedbackRecipients -- this just gets in the way of the more 635 # intelligent "receive_recipients" method. 636 #$courseOptions{feedbackRecipients} = [ $add_initial_email ]; 637 } 638 639 if ($add_dbLayout eq "gdbm") { 640 $courseOptions{globalUserID} = $add_gdbm_globalUserID if $add_gdbm_globalUserID ne ""; 641 } 642 643 my %dbOptions; 644 if ($add_dbLayout eq "sql") { 645 $dbOptions{host} = $add_sql_host if $add_sql_host ne ""; 646 $dbOptions{port} = $add_sql_port if $add_sql_port ne ""; 647 $dbOptions{username} = $add_sql_username; 648 $dbOptions{password} = $add_sql_password; 649 $dbOptions{database} = $add_sql_database || "webwork_$add_courseID"; 650 $dbOptions{wwhost} = $add_sql_wwhost; 651 } 652 653 my @users; 654 655 # copy users from current (admin) course if desired 656 if ($add_admin_users ne "") { 657 foreach my $userID ($db->listUsers) { 658 if ($userID eq $add_initial_userID) { 659 $self->addbadmessage( "User '$userID' will not be copied from admin course as it is the initial instructor."); 660 next; 661 } 662 my $User = $db->getUser($userID); 663 my $Password = $db->getPassword($userID); 664 my $PermissionLevel = $db->getPermissionLevel($userID); 665 push @users, [ $User, $Password, $PermissionLevel ]; 666 } 667 } 668 669 # add initial instructor if desired 670 if ($add_initial_userID ne "") { 671 my $User = $db->newUser( 672 user_id => $add_initial_userID, 673 first_name => $add_initial_firstName, 674 last_name => $add_initial_lastName, 675 student_id => $add_initial_userID, 676 email_address => $add_initial_email, 677 status => "C", 678 ); 679 my $Password = $db->newPassword( 680 user_id => $add_initial_userID, 681 password => cryptPassword($add_initial_password), 682 ); 683 my $PermissionLevel = $db->newPermissionLevel( 684 user_id => $add_initial_userID, 685 permission => "10", 686 ); 687 push @users, [ $User, $Password, $PermissionLevel ]; 688 } 689 690 push @{$courseOptions{PRINT_FILE_NAMES_FOR}}, map { $_->[0]->user_id } @users; 691 692 my %optional_arguments; 693 if ($add_templates_course ne "") { 694 $optional_arguments{templatesFrom} = $add_templates_course; 695 } 696 697 eval { 698 addCourse( 699 courseID => $add_courseID, 700 ce => $ce2, 701 courseOptions => \%courseOptions, 702 dbOptions => \%dbOptions, 703 users => \@users, 704 %optional_arguments, 705 ); 706 }; 707 if ($@) { 708 my $error = $@; 709 print CGI::div({class=>"ResultsWithError"}, 710 CGI::p("An error occured while creating the course $add_courseID:"), 711 CGI::tt(CGI::escapeHTML($error)), 712 ); 713 # get rid of any partially built courses 714 # FIXME -- this is too fragile 715 unless ($error =~ /course exists/) { 716 eval { 717 deleteCourse( 718 courseID => $add_courseID, 719 ce => $ce2, 720 dbOptions => \%dbOptions, 721 ); 722 } 723 } 724 } else { 725 #log the action 726 writeLog($ce, "hosted_courses", join("\t", 727 "\tAdded", 728 $add_courseInstitution, 729 $add_courseTitle, 730 $add_courseID, 731 $add_initial_firstName, 732 $add_initial_lastName, 733 $add_initial_email, 734 )); 735 # add contact to admin course as student? 736 # FIXME -- should we do this? 737 print CGI::div({class=>"ResultsWithoutError"}, 738 CGI::p("Successfully created the course $add_courseID"), 739 ); 740 my $newCoursePath = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets", 741 courseID => $add_courseID); 742 my $newCourseURL = $self->systemLink($newCoursePath, authen => 0); 743 print CGI::div({style=>"text-align: center"}, 744 CGI::a({href=>$newCourseURL}, "Log into $add_courseID"), 745 ); 746 } 747 748 749 } 750 751 ################################################################################ 752 753 sub delete_course_form { 754 my ($self) = @_; 755 my $r = $self->r; 756 my $ce = $r->ce; 757 #my $db = $r->db; 758 #my $authz = $r->authz; 759 #my $urlpath = $r->urlpath; 760 761 my $delete_courseID = $r->param("delete_courseID") || ""; 762 my $delete_sql_host = $r->param("delete_sql_host") || ""; 763 my $delete_sql_port = $r->param("delete_sql_port") || ""; 764 my $delete_sql_username = $r->param("delete_sql_username") || ""; 765 my $delete_sql_password = $r->param("delete_sql_password") || ""; 766 my $delete_sql_database = $r->param("delete_sql_database") || ""; 767 768 my @courseIDs = listCourses($ce); 769 @courseIDs = sort @courseIDs; 770 771 my %courseLabels; # records... heh. 772 foreach my $courseID (@courseIDs) { 773 my $tempCE = WeBWorK::CourseEnvironment->new( 774 $ce->{webworkDirs}->{root}, 775 $ce->{webworkURLs}->{root}, 776 $ce->{pg}->{directories}->{root}, 777 $courseID, 778 ); 779 $courseLabels{$courseID} = "$courseID (" . $tempCE->{dbLayoutName} . ")"; 780 } 781 782 print CGI::h2("Delete Course"); 783 784 print CGI::start_form("POST", $r->uri); 785 print $self->hidden_authen_fields; 786 print $self->hidden_fields("subDisplay"); 787 788 print CGI::p("Select a course to delete."); 789 790 print CGI::table({class=>"FormLayout"}, 791 CGI::Tr( 792 CGI::th({class=>"LeftHeader"}, "Course Name:"), 793 CGI::td( 794 CGI::scrolling_list( 795 -name => "delete_courseID", 796 -values => \@courseIDs, 797 -default => $delete_courseID, 798 -size => 10, 799 -multiple => 0, 800 -labels => \%courseLabels, 801 ), 802 ), 803 ), 804 ); 805 806 print CGI::p( 807 "If the course's database layout (indicated in parentheses above) is " 808 . CGI::b("sql") . ", supply the SQL connections information requested below." 809 ); 810 811 print CGI::start_table({class=>"FormLayout"}); 812 print CGI::Tr(CGI::td({colspan=>2}, 813 "Enter the user ID and password for an SQL account with sufficient permissions to delete an existing database." 814 ) 815 ); 816 print CGI::Tr( 817 CGI::th({class=>"LeftHeader"}, "SQL Admin Username:"), 818 CGI::td(CGI::textfield("delete_sql_username", $delete_sql_username, 25)), 819 ); 820 print CGI::Tr( 821 CGI::th({class=>"LeftHeader"}, "SQL Admin Password:"), 822 CGI::td(CGI::password_field("delete_sql_password", $delete_sql_password, 25)), 823 ); 824 825 #print CGI::Tr(CGI::td({colspan=>2}, 826 # "The optionial SQL settings you enter below must match the settings in the DBI source" 827 # . " specification " . CGI::tt($dbi_source) . ". Replace " . CGI::tt("COURSENAME") 828 # . " with the course name you entered above." 829 # ) 830 #); 831 print CGI::Tr( 832 CGI::th({class=>"LeftHeader"}, "SQL Server Host:"), 833 CGI::td( 834 CGI::textfield("delete_sql_host", $delete_sql_host, 25), 835 CGI::br(), 836 CGI::small("Leave blank to use the default host."), 837 ), 838 ); 839 print CGI::Tr( 840 CGI::th({class=>"LeftHeader"}, "SQL Server Port:"), 841 CGI::td( 842 CGI::textfield("delete_sql_port", $delete_sql_port, 25), 843 CGI::br(), 844 CGI::small("Leave blank to use the default port."), 845 ), 846 ); 847 848 print CGI::Tr( 849 CGI::th({class=>"LeftHeader"}, "SQL Database Name:"), 850 CGI::td( 851 CGI::textfield("delete_sql_database", $delete_sql_database, 25), 852 CGI::br(), 853 CGI::small("Leave blank to use the name ", CGI::tt("webwork_COURSENAME"), "."), 854 ), 855 ); 856 print CGI::end_table(); 857 858 print CGI::p({style=>"text-align: center"}, CGI::submit("delete_course", "Delete Course")); 859 860 print CGI::end_form(); 861 } 862 863 sub delete_course_validate { 864 my ($self) = @_; 865 my $r = $self->r; 866 my $ce = $r->ce; 867 #my $db = $r->db; 868 #my $authz = $r->authz; 869 my $urlpath = $r->urlpath; 870 871 my $delete_courseID = $r->param("delete_courseID") || ""; 872 my $delete_sql_host = $r->param("delete_sql_host") || ""; 873 my $delete_sql_port = $r->param("delete_sql_port") || ""; 874 my $delete_sql_username = $r->param("delete_sql_username") || ""; 875 my $delete_sql_password = $r->param("delete_sql_password") || ""; 876 my $delete_sql_database = $r->param("delete_sql_database") || ""; 877 878 my @errors; 879 880 if ($delete_courseID eq "") { 881 push @errors, "You must specify a course name."; 882 } elsif ($delete_courseID eq $urlpath->arg("courseID")) { 883 push @errors, "You cannot delete the course you are currently using."; 884 } 885 886 my $ce2 = WeBWorK::CourseEnvironment->new( 887 $ce->{webworkDirs}->{root}, 888 $ce->{webworkURLs}->{root}, 889 $ce->{pg}->{directories}->{root}, 890 $delete_courseID, 891 ); 892 893 if ($ce2->{dbLayoutName} eq "sql") { 894 push @errors, "You must specify the SQL admin username." if $delete_sql_username eq ""; 895 #push @errors, "You must specify the SQL admin password." if $delete_sql_password eq ""; 896 #push @errors, "You must specify the SQL database name." if $delete_sql_database eq ""; 897 } 898 899 return @errors; 900 } 901 902 sub delete_course_confirm { 903 my ($self) = @_; 904 my $r = $self->r; 905 my $ce = $r->ce; 906 #my $db = $r->db; 907 #my $authz = $r->authz; 908 #my $urlpath = $r->urlpath; 909 910 print CGI::h2("Delete Course"); 911 912 my $delete_courseID = $r->param("delete_courseID") || ""; 913 my $delete_sql_host = $r->param("delete_sql_host") || ""; 914 my $delete_sql_port = $r->param("delete_sql_port") || ""; 915 my $delete_sql_database = $r->param("delete_sql_database") || ""; 916 917 my $ce2 = WeBWorK::CourseEnvironment->new( 918 $ce->{webworkDirs}->{root}, 919 $ce->{webworkURLs}->{root}, 920 $ce->{pg}->{directories}->{root}, 921 $delete_courseID, 922 ); 923 924 if ($ce2->{dbLayoutName} eq "sql") { 925 print CGI::p("Are you sure you want to delete the course " . CGI::b($delete_courseID) 926 . "? All course files and data and the following database will be destroyed." 927 . " There is no undo available."); 928 929 print CGI::table({class=>"FormLayout"}, 930 CGI::Tr( 931 CGI::th({class=>"LeftHeader"}, "SQL Server Host:"), 932 CGI::td($delete_sql_host || "system default"), 933 ), 934 CGI::Tr( 935 CGI::th({class=>"LeftHeader"}, "SQL Server Port:"), 936 CGI::td($delete_sql_port || "system default"), 937 ), 938 CGI::Tr( 939 CGI::th({class=>"LeftHeader"}, "SQL Database Name:"), 940 CGI::td($delete_sql_database || "webwork_$delete_courseID"), 941 ), 942 ); 943 } else { 944 print CGI::p("Are you sure you want to delete the course " . CGI::b($delete_courseID) 945 . "? All course files and data will be destroyed. There is no undo available."); 946 } 947 948 print CGI::start_form("POST", $r->uri); 949 print $self->hidden_authen_fields; 950 print $self->hidden_fields("subDisplay"); 951 print $self->hidden_fields(qw/delete_courseID delete_sql_host delete_sql_port delete_sql_username delete_sql_password delete_sql_database/); 952 953 print CGI::p({style=>"text-align: center"}, 954 CGI::submit("decline_delete_course", "Don't delete"), 955 " ", 956 CGI::submit("confirm_delete_course", "Delete"), 957 ); 958 959 print CGI::end_form(); 960 } 961 962 sub do_delete_course { 963 my ($self) = @_; 964 my $r = $self->r; 965 my $ce = $r->ce; 966 #my $db = $r->db; 967 #my $authz = $r->authz; 968 #my $urlpath = $r->urlpath; 969 970 my $delete_courseID = $r->param("delete_courseID") || ""; 971 my $delete_sql_host = $r->param("delete_sql_host") || ""; 972 my $delete_sql_port = $r->param("delete_sql_port") || ""; 973 my $delete_sql_username = $r->param("delete_sql_username") || ""; 974 my $delete_sql_password = $r->param("delete_sql_password") || ""; 975 my $delete_sql_database = $r->param("delete_sql_database") || ""; 976 977 my $ce2 = WeBWorK::CourseEnvironment->new( 978 $ce->{webworkDirs}->{root}, 979 $ce->{webworkURLs}->{root}, 980 $ce->{pg}->{directories}->{root}, 981 $delete_courseID, 982 ); 983 984 my %dbOptions; 985 if ($ce2->{dbLayoutName} eq "sql") { 986 $dbOptions{host} = $delete_sql_host if $delete_sql_host ne ""; 987 $dbOptions{port} = $delete_sql_port if $delete_sql_port ne ""; 988 $dbOptions{username} = $delete_sql_username; 989 $dbOptions{password} = $delete_sql_password; 990 $dbOptions{database} = $delete_sql_database || "webwork_$delete_courseID"; 991 } 992 993 eval { 994 deleteCourse( 995 courseID => $delete_courseID, 996 ce => $ce2, 997 dbOptions => \%dbOptions, 998 ); 999 }; 1000 1001 if ($@) { 1002 my $error = $@; 1003 print CGI::div({class=>"ResultsWithError"}, 1004 CGI::p("An error occured while deleting the course $delete_courseID:"), 1005 CGI::tt(CGI::escapeHTML($error)), 1006 ); 1007 } else { 1008 print CGI::div({class=>"ResultsWithoutError"}, 1009 CGI::p("Successfully deleted the course $delete_courseID."), 1010 ); 1011 writeLog($ce, "hosted_courses", join("\t", 1012 "\tDeleted", 1013 "", 1014 "", 1015 $delete_courseID, 1016 )); 1017 print CGI::start_form("POST", $r->uri); 1018 print $self->hidden_authen_fields; 1019 print $self->hidden_fields("subDisplay"); 1020 1021 print CGI::p({style=>"text-align: center"}, CGI::submit("decline_delete_course", "OK"),); 1022 1023 print CGI::end_form(); 1024 } 1025 } 1026 1027 ################################################################################ 1028 1029 sub export_database_form { 1030 my ($self) = @_; 1031 my $r = $self->r; 1032 my $ce = $r->ce; 1033 #my $db = $r->db; 1034 #my $authz = $r->authz; 1035 #my $urlpath = $r->urlpath; 1036 1037 my @tables = keys %{$ce->{dbLayout}}; 1038 1039 my $export_courseID = $r->param("export_courseID") || ""; 1040 my @export_tables = $r->param("export_tables"); 1041 1042 @export_tables = @tables unless @export_tables; 1043 1044 my @courseIDs = listCourses($ce); 1045 @courseIDs = sort @courseIDs; 1046 1047 my %courseLabels; # records... heh. 1048 foreach my $courseID (@courseIDs) { 1049 my $tempCE = WeBWorK::CourseEnvironment->new( 1050 $ce->{webworkDirs}->{root}, 1051 $ce->{webworkURLs}->{root}, 1052 $ce->{pg}->{directories}->{root}, 1053 $courseID, 1054 ); 1055 $courseLabels{$courseID} = "$courseID (" . $tempCE->{dbLayoutName} . ")"; 1056 } 1057 1058 print CGI::h2("Export Database"); 1059 1060 print CGI::start_form("GET", $r->uri); 1061 print $self->hidden_authen_fields; 1062 print $self->hidden_fields("subDisplay"); 1063 1064 print CGI::p("Select a course to export the course's database. Please note 1065 that exporting can take a very long time for a large course. If you have 1066 shell access to the WeBWorK server, you may use the ", CGI::code("wwdb"), " 1067 utility instead."); 1068 1069 print CGI::table({class=>"FormLayout"}, 1070 CGI::Tr( 1071 CGI::th({class=>"LeftHeader"}, "Course Name:"), 1072 CGI::td( 1073 CGI::scrolling_list( 1074 -name => "export_courseID", 1075 -values => \@courseIDs, 1076 -default => $export_courseID, 1077 -size => 10, 1078 -multiple => 0, 1079 -labels => \%courseLabels, 1080 ), 1081 ), 1082 ), 1083 CGI::Tr( 1084 CGI::th({class=>"LeftHeader"}, "Tables to Export:"), 1085 CGI::td( 1086 CGI::checkbox_group( 1087 -name => "export_tables", 1088 -values => \@tables, 1089 -default => \@export_tables, 1090 -linebreak => 1, 1091 ), 1092 ), 1093 ), 1094 ); 1095 1096 print CGI::p({style=>"text-align: center"}, CGI::submit("export_database", "Export Database")); 1097 1098 print CGI::end_form(); 1099 } 1100 1101 sub export_database_validate { 1102 my ($self) = @_; 1103 my $r = $self->r; 1104 #my $ce = $r->ce; 1105 #my $db = $r->db; 1106 #my $authz = $r->authz; 1107 #my $urlpath = $r->urlpath; 1108 1109 my $export_courseID = $r->param("export_courseID") || ""; 1110 my @export_tables = $r->param("export_tables"); 1111 1112 my @errors; 1113 1114 if ($export_courseID eq "") { 1115 push @errors, "You must specify a course name."; 1116 } 1117 1118 unless (@export_tables) { 1119 push @errors, "You must specify at least one table to export."; 1120 } 1121 1122 return @errors; 1123 } 1124 1125 sub do_export_database { 1126 my ($self) = @_; 1127 my $r = $self->r; 1128 my $ce = $r->ce; 1129 #my $db = $r->db; 1130 #my $authz = $r->authz; 1131 my $urlpath = $r->urlpath; 1132 1133 my $export_courseID = $r->param("export_courseID"); 1134 my @export_tables = $r->param("export_tables"); 1135 1136 my $ce2 = WeBWorK::CourseEnvironment->new( 1137 $ce->{webworkDirs}->{root}, 1138 $ce->{webworkURLs}->{root}, 1139 $ce->{pg}->{directories}->{root}, 1140 $export_courseID, 1141 ); 1142 1143 my $db2 = new WeBWorK::DB($ce2->{dbLayout}); 1144 1145 #my ($fh, $export_file) = tempfile("db_export_XXXXXX", DIR => $ce->{webworkDirs}->{tmp}); 1146 #my ($random_chars) = $export_file =~ m/db_export_(\w+)$/; 1147 1148 my @errors; 1149 1150 eval { 1151 @errors = dbExport( 1152 db => $db2, 1153 #xml => $fh, 1154 xml => *STDOUT, 1155 tables => \@export_tables, 1156 ); 1157 }; 1158 1159 #push @errors, "Fatal exception: $@" if $@; 1160 # 1161 #if (@errors) { 1162 # print CGI::div({class=>"ResultsWithError"}, 1163 # CGI::p("An error occured while exporting the database of course $export_courseID:"), 1164 # CGI::ul(CGI::li(\@errors)), 1165 # ); 1166 #} else { 1167 # print CGI::div({class=>"ResultsWithoutError"}, 1168 # CGI::p("Export succeeded."), 1169 # ); 1170 # 1171 # print CGI::div({style=>"text-align: center"}, 1172 # CGI::a({href=>$self->systemLink($urlpath, params=>{download_exported_database=>$random_chars, export_courseID=>undef})}, "Download Exported Database"), 1173 # ); 1174 #} 1175 } 1176 1177 ################################################################################ 1178 1179 sub import_database_form { 1180 my ($self) = @_; 1181 my $r = $self->r; 1182 my $ce = $r->ce; 1183 #my $db = $r->db; 1184 #my $authz = $r->authz; 1185 #my $urlpath = $r->urlpath; 1186 1187 my @tables = keys %{$ce->{dbLayout}}; 1188 1189 my $import_file = $r->param("import_file") || ""; 1190 my $import_courseID = $r->param("import_courseID") || ""; 1191 my @import_tables = $r->param("import_tables"); 1192 my $import_conflict = $r->param("import_conflict") || "skip"; 1193 1194 @import_tables = @tables unless @import_tables; 1195 1196 my @courseIDs = listCourses($ce); 1197 @courseIDs = sort @courseIDs; 1198 1199 1200 my %courseLabels; # records... heh. 1201 foreach my $courseID (@courseIDs) { 1202 my $tempCE = WeBWorK::CourseEnvironment->new( 1203 $ce->{webworkDirs}->{root}, 1204 $ce->{webworkURLs}->{root}, 1205 $ce->{pg}->{directories}->{root}, 1206 $courseID, 1207 ); 1208 $courseLabels{$courseID} = "$courseID (" . $tempCE->{dbLayoutName} . ")"; 1209 } 1210 1211 print CGI::h2("Import Database"); 1212 1213 print CGI::start_form("POST", $r->uri, &CGI::MULTIPART); 1214 print $self->hidden_authen_fields; 1215 print $self->hidden_fields("subDisplay"); 1216 1217 print CGI::table({class=>"FormLayout"}, 1218 CGI::Tr( 1219 CGI::th({class=>"LeftHeader"}, "Database XML File:"), 1220 CGI::td( 1221 CGI::filefield( 1222 -name => "import_file", 1223 -size => 50, 1224 ), 1225 ), 1226 ), 1227 CGI::Tr( 1228 CGI::th({class=>"LeftHeader"}, "Tables to Import:"), 1229 CGI::td( 1230 CGI::checkbox_group( 1231 -name => "import_tables", 1232 -values => \@tables, 1233 -default => \@import_tables, 1234 -linebreak => 1, 1235 ), 1236 ), 1237 ), 1238 CGI::Tr( 1239 CGI::th({class=>"LeftHeader"}, "Import into Course:"), 1240 CGI::td( 1241 CGI::scrolling_list( 1242 -name => "import_courseID", 1243 -values => \@courseIDs, 1244 -default => $import_courseID, 1245 -size => 10, 1246 -multiple => 0, 1247 -labels => \%courseLabels, 1248 ), 1249 ), 1250 ), 1251 CGI::Tr( 1252 CGI::th({class=>"LeftHeader"}, "Conflicts:"), 1253 CGI::td( 1254 CGI::radio_group( 1255 -name => "import_conflict", 1256 -values => [qw/skip replace/], 1257 -default => $import_conflict, 1258 -linebreak=>'true', 1259 -labels => { 1260 skip => "Skip duplicate records", 1261 replace => "Replace duplicate records", 1262 }, 1263 ), 1264 ), 1265 ), 1266 ); 1267 1268 print CGI::p({style=>"text-align: center"}, CGI::submit("import_database", "Import Database")); 1269 1270 print CGI::end_form(); 1271 } 1272 1273 sub import_database_validate { 1274 my ($self) = @_; 1275 my $r = $self->r; 1276 #my $ce = $r->ce; 1277 #my $db = $r->db; 1278 #my $authz = $r->authz; 1279 #my $urlpath = $r->urlpath; 1280 1281 my $import_file = $r->param("import_file") || ""; 1282 my $import_courseID = $r->param("import_courseID") || ""; 1283 my @import_tables = $r->param("import_tables"); 1284 #my $import_conflict = $r->param("import_conflict") || "skip"; # not checked 1285 1286 my @errors; 1287 1288 if ($import_file eq "") { 1289 push @errors, "You must specify a database file to upload."; 1290 } 1291 1292 if ($import_courseID eq "") { 1293 push @errors, "You must specify a course name."; 1294 } 1295 1296 unless (@import_tables) { 1297 push @errors, "You must specify at least one table to import."; 1298 } 1299 1300 return @errors; 1301 } 1302 1303 sub do_import_database { 1304 my ($self) = @_; 1305 my $r = $self->r; 1306 my $ce = $r->ce; 1307 #my $db = $r->db; 1308 #my $authz = $r->authz; 1309 my $urlpath = $r->urlpath; 1310 1311 my $import_file = $r->param("import_file"); 1312 my $import_courseID = $r->param("import_courseID"); 1313 my @import_tables = $r->param("import_tables"); 1314 my $import_conflict = $r->param("import_conflict") || "skip"; # need default -- not checked above 1315 1316 my $ce2 = WeBWorK::CourseEnvironment->new( 1317 $ce->{webworkDirs}->{root}, 1318 $ce->{webworkURLs}->{root}, 1319 $ce->{pg}->{directories}->{root}, 1320 $import_courseID, 1321 ); 1322 1323 my $db2 = new WeBWorK::DB($ce2->{dbLayout}); 1324 1325 # retrieve upload from upload cache 1326 my ($id, $hash) = split /\s+/, $import_file; 1327 my $upload = WeBWorK::Upload->retrieve($id, $hash, 1328 dir => $ce->{webworkDirs}->{uploadCache} 1329 ); 1330 1331 my @errors; 1332 1333 eval { 1334 @errors = dbImport( 1335 db => $db2, 1336 xml => $upload->fileHandle, 1337 tables => \@import_tables, 1338 conflict => $import_conflict, 1339 ); 1340 }; 1341 1342 $upload->dispose; 1343 1344 push @errors, "Fatal exception: $@" if $@; 1345 1346 if (@errors) { 1347 print CGI::div({class=>"ResultsWithError"}, 1348 CGI::p("An error occured while importing the database of course $import_courseID:"), 1349 CGI::ul(CGI::li(\@errors)), 1350 ); 1351 } else { 1352 print CGI::div({class=>"ResultsWithoutError"}, 1353 CGI::p("Import succeeded."), 1354 ); 1355 } 1356 } 1357 1358 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |