From: Mike G. v. a. <we...@ma...> - 2009-01-18 03:34:56
|
Log Message: ----------- changes to support increased error checking when archiving courses Modified Files: -------------- webwork2/lib/WeBWorK/Utils: CourseManagement.pm Revision Data ------------- Index: CourseManagement.pm =================================================================== RCS file: /webwork/cvs/system/webwork2/lib/WeBWorK/Utils/CourseManagement.pm,v retrieving revision 1.43 retrieving revision 1.44 diff -Llib/WeBWorK/Utils/CourseManagement.pm -Llib/WeBWorK/Utils/CourseManagement.pm -u -r1.43 -r1.44 --- lib/WeBWorK/Utils/CourseManagement.pm +++ lib/WeBWorK/Utils/CourseManagement.pm @@ -32,7 +32,7 @@ use String::ShellQuote; use WeBWorK::CourseEnvironment; use WeBWorK::Debug; -use WeBWorK::Utils qw(runtime_use readDirectory); +use WeBWorK::Utils qw(runtime_use readDirectory pretty_print_rh); our @EXPORT = (); our @EXPORT_OK = qw( @@ -44,6 +44,9 @@ archiveCourse unarchiveCourse dbLayoutSQLSources + checkCourseTables + updateCourseTables + checkCourseDirectories ); =head1 FUNCTIONS @@ -585,7 +588,12 @@ # fail if a course archive already exists # FIXME there could be an option to overwrite an existing archive if (-e $archive_path) { - croak "The course '$courseID' has already been archived at '$archive_path'.\n"; + unlink($archive_path) if (-w $archive_path); + unless (-e $archive_path) { + print CGI::p({-style=>'color:red; font-weight:bold'}, "The archival version of '$courseID' has been replaced'.\n"); + } else { + croak "Unable to replace the archival version of '$courseID'"; + } } #### step 1: dump tables ##### @@ -957,6 +965,14 @@ } } +=over + +=item getHelperRef($helperName, $dbLayoutName) + +Call a database-specific helper function, if a database-layout specific helper +class exists and contains a function named "${helperName}Helper". + +=cut sub getHelperRef { my ($helperName, $dbLayoutName) = @_; @@ -1147,5 +1163,151 @@ print $fh "\n\n\n"; } } +=item checkCourseDirectories($courseName) + +Checks the course files and directories to make sure they exist and have the correct permissions. + +=cut + + + +=item checkCourseTables($courseName, $dbLayoutName, $ce); + +Checks the course tables in the mysql database and insures that they are the same as the ones specified by the databaseLayout + + +=cut + +sub checkCourseTables { + my ($courseName, $dbLayoutName, $ce) = @_; + my $str=''; + my %both = (); + my %schema_only = (); + my %database_only = (); + ########################################################## + # fetch schema from course environment and search database + # for corresponding tables. + ########################################################## + my $db = new WeBWorK::DB($ce->{dbLayouts}->{$dbLayoutName}); + foreach my $table (sort keys %$db) { + next if $db->{$table}{params}{non_native}; # skip non-native tables + my $table_name = (exists $db->{$table}->{params}->{tableOverride})? $db->{$table}->{params}->{tableOverride}:$table; + my $database_table_exists = ($db->{$table}->can("delete_table")) ? 1:0; + if ($database_table_exists ) { # exists means the table could be deleted. + $both{$table_name} = checkTableFields($courseName, $dbLayoutName, $ce, $table); + } else { + $schema_only{$table_name} = 1; + } + } + ########################################################## + # fetch fetch corresponding tables in the database and + # search for corresponding schema entries. + ########################################################## + + my $dbh =$db->{key}->dbh; # grab any database handle + my $stmt = "show tables like '$courseName%'"; # mysql request + my $result = $dbh->selectall_arrayref($stmt) ; + my @tableNames = map {@$_} @$result; # drill down in the result to the table name level + foreach my $table (sort @tableNames) { + $table =~/${courseName}_(.*)/; + my $schema_name = $1; + my $exists = exists($db->{$schema_name}); + $database_only{$table}=1 unless $exists; + } + print CGI::p($str); + my $tables_ok = not ( %schema_only || %database_only ); # count number of extraneous tables; 0 means ok + return ($tables_ok,\%both, \%schema_only, \%database_only); # table in both schema & database; found in schema only; found in database only +} + +=item updateCourseTables($courseName, $dbLayoutName, $ce, $table_names); + +Adds schema tables to the database that had been missing from the database. + +=cut + +sub updateCourseTables { + my ($courseName, $dbLayoutName, $ce, $table_names) = @_; + my $db = new WeBWorK::DB($ce->{dbLayouts}->{$dbLayoutName}); + #die "Programmers: Pass reference to the array of table names to be updated." unless ref($table_names)=~/ARRAY/; + #warn "table names are ".join(" ", @$table_names); + my $str=''; + foreach my $table (sort @$table_names) { # remainder copied from db->create_table + #warn "processing $table"; + next if $table =~ /^_/; # skip non-table self fields (none yet) + #warn "not a non-table self field"; + next if $db->{$table}{params}{non_native}; # skip non-native tables + #warn "not a non_native table"; + my $schema_obj = $db->{$table}; + + if ($schema_obj->can("create_table")) { + # warn "creating table $schema_obj"; + $schema_obj->create_table; + $str .= "Table $table created".CGI::br(); + } else { + warn "Skipping creation of '$table' table: no create_table method\n"; + } + } + $str; + +} + +=cut + + + +=item checkTableFields($courseName, $dbLayoutName, $ce, $table); + +Checks the course tables in the mysql database and insures that they are the same as the ones specified by the databaseLayout + + +=cut + + +sub checkTableFields { + my ($courseName, $dbLayoutName, $ce,$table) = @_; + my $str=' '; + my %both = (); + my %schema_only = (); + my %database_only = (); + ########################################################## + # fetch schema from course environment and search database + # for corresponding tables. + ########################################################## + my $db = new WeBWorK::DB($ce->{dbLayouts}->{$dbLayoutName}); + my $table_name = (exists $db->{$table}->{params}->{tableOverride})? $db->{$table}->{params}->{tableOverride}:$table; + warn "$table_name is a non native table" if $db->{$table}{params}{non_native}; # skip non-native tables + my @fields = $db->{$table}->{record}->FIELDS; + foreach my $field (sort @fields) { + #my $database_table_exists = ($db->{$table}->can("delete_table")) ? 1:0; + my $field_name = $db->{$table}->{params}->{fieldOverride}->{$field} ||$field; + my $database_field_exists = $db->{$table}->tableFieldExists($field_name); + if ($database_field_exists) { + $str.="$field =>$field_name, "; + $both{$field}=1; + } else { + $str.="$field =>MISSING, "; + $schema_only{$field}=1; + } + + } + ########################################################## + # fetch fetch corresponding tables in the database and + # search for corresponding schema entries. + ########################################################## + +# my $dbh =$db->{key}->dbh; # grab any database handle +# my $stmt = "show tables like '$courseName%'"; # mysql request +# my $result = $dbh->selectall_arrayref($stmt) ; +# my @tableNames = map {@$_} @$result; # drill down in the result to the table name level +# foreach my $table (sort @tableNames) { +# $table =~/${courseName}_(.*)/; +# my $schema_name = $1; +# my $exists = exists($db->{$schema_name}); +# $database_only{$table}=1 unless $exists; +# } +# return (\%both, \%schema_only, \%database_only); # table in both schema & database; found in schema only; found in database only + return $str."<br/>"; +} + 1; |