package WeBWorK::ContentGenerator::Instructor::PGProblemEditor; use base qw(WeBWorK::ContentGenerator::Instructor); =head1 NAME WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list =cut use strict; use warnings; use CGI qw(); use WeBWorK::Utils qw(readFile); use Apache::Constants qw(:common REDIRECT); our $libraryName; our $rowheight; sub title { my $self = shift; #FIXME don't need the entire path ?? return "Instructor Tools - PG Problem Editor for ". $self->{ce}->{problemPath}; } sub go { my $self = shift; my ($setName, $problemNumber) = @_; my $r = $self->{r}; my $ce = $self->{ce}; my $submit_button = $r->param('submit'); # obtain submit command from form # various actions depending on state. if ( defined($submit_button) and ($submit_button eq 'Save' or $submit_button eq 'Refresh') ) { $self->initialize($setName,$problemNumber); # write the necessary files # return file path for viewing problem # in $self->{ce}->{currentSourceFilePath} #redirect to view the problem my $hostname = $r->hostname(); my $port = $r->get_server_port(); my $uri = $r->uri; my $courseName = $self->{ce}->{courseName}; my $editFileSuffix = $self->{ce}->{editFileSuffix}; my $problemSeed = ($r->param('problemSeed')) ? $r->param('problemSeed') : ''; my $displayMode = ($r->param('displayMode')) ? $r->param('displayMode') : ''; my $viewURL = "http://$hostname:$port"; $viewURL .= "/webwork/$courseName/$setName/$problemNumber/?"; $viewURL .= $self->url_authen_args; $viewURL .= "&displayMode=$displayMode&problemSeed=$problemSeed"; # optional displayMode and problemSeed overrides $viewURL .= "&editMode=temporaryFile"; $viewURL .= '&sourceFilePath='.$self->{ce}->{currentSourceFilePath}; # path to pg text for viewing $viewURL .= "&submit_button=$submit_button"; # allows Problem.pg to recognize state $viewURL .= '&editErrors='.$self->{ce}->{editErrors}; # of problem being viewed. $r->header_out(Location => $viewURL ); return REDIRECT; } else { # initialize and # display the editing window $self->SUPER::go(@_); } } sub initialize { my ($self, $setName, $problemNumber) = @_; my $ce = $self->{ce}; my $r = $self->{r}; my $path_info = $r->path_info || ""; my $db = $self->{db}; my $user = $r->param('user'); my $effectiveUserName = $r->param('effectiveUser'); my $courseName = $ce->{courseName}; # FIXME -- sometimes this doesn't find a set # my $set = $db->getGlobalUserSet($effectiveUserName, $setName); # my $setID = $set->set_id; # Find URL for viewing problem # find path to pg file for the problem # FIXME there is a discrepancy in the way that the problems are found. # FIXME more error checking is needed in case the problem doesn't exist. # my $problem_record = $db->getUserProblem($user,$setID,1); my $problem_record = $db->getGlobalUserProblem($effectiveUserName, $setName, $problemNumber); my $templateDirectory = $ce->{courseDirs}->{templates}; my $problemPath = $templateDirectory."/".$problem_record->source_file; my $editFileSuffix = 'tmp'; my $submit_button = $r->param('submit'); my $displayMode = ( defined($r->param('displayMode')) ) ? $r->param('displayMode') : $ce->{pg}->{options}->{displayMode}; my $problemSeed = ( defined($r->param('problemSeed')) ) ? $r->param('problemSeed') : $problem_record->problem_seed; $problemSeed = '1234' unless defined($problemSeed) and $problemSeed =~/\S/; my $problemContents = ''; my $currentSourceFilePath = ''; # update the .pg and .pg.tmp files in the directory if (not defined($submit_button) ) { # this is a fresh editing job # copy the pg file to a new file with the same name with .tmp added # store this name in the $ce->currentSourceFilePath for use in body eval { $problemContents = WeBWorK::Utils::readFile($problemPath) }; # try to read file $problemContents = $@ if $@; $currentSourceFilePath = "$problemPath.$editFileSuffix"; $ce->{currentSourceFilePath} = $currentSourceFilePath; } elsif ($submit_button eq 'Refresh' ) { # grab the problemContents from the form and save it to the tmp file # store tmp file name in the $ce->currentSourceFilePath for use in body $problemContents = $r->param('problemContents'); $currentSourceFilePath = "$problemPath.$editFileSuffix"; $ce->{currentSourceFilePath} = $currentSourceFilePath; } elsif ($submit_button eq 'Save') { # grab the problemContents from the form and save it to the permanent file # unlink (delete) the temporary file # store the permanent file name in the $ce->problemContents for use in body $problemContents = $r->param('problemContents'); $currentSourceFilePath = "$problemPath"; $ce->{currentSourceFilePath} = $currentSourceFilePath; } else { # give a warning die "Unrecognized submit command $submit_button"; } # print changed pg files # FIXME make sure that the permissions are set correctly!!! # Make sure that the warning is being transmitted properly. eval { local *OUTPUTFILE; open OUTPUTFILE, ">", $currentSourceFilePath or die "Failed to write to $currentSourceFilePath: $!"; print OUTPUTFILE $problemContents; close OUTPUTFILE; }; my $errors = $@ if $@; if ( $errors) { $ce->{editErrors} = "Unable to write to $currentSourceFilePath: $errors"; } else { # unlink the temporary file if there are no errors. $ce->{editErrors} = ''; unlink("$problemPath.$editFileSuffix") if defined($submit_button) and $submit_button eq 'Save'; }; # return values. FIXME -- is this the right way to pass the values to body?? # Should temporary results be passed in self or in ce?? # $ce->{viewProblemURL} = $viewProblemURL; $ce->{problemPath} = $problemPath; $self->{displayMode} = $displayMode; $self->{problemSeed} = $problemSeed; # $ce->{path_components} = join("/",$setID,$problemNumber); # FIXME there is no way to edit in a temporary file -- all editing takes place on disk!!! } sub body { my $self = shift; # test area my $r = $self->{r}; my $db = $self->{db}; my $ce = $self->{ce}; my $user = $r->param('user'); my $key = $db->getKey($user)->key(); ################ # Gathering info # What is needed # $problemPath -- # $formURL -- given by $r->uri # $tmpProblemPath #my ($problemPath,$formURL,$tmpProblemPath) = $self->initialize(); my $problemPath = $ce->{problemPath}; #my $tmpProblemPath = $ce->{tmpProblemPath}; my $header = "Problem Editor: $problemPath"; ######################################################################### # Find the text for the problem, either in the tmp file, if it exists # or in the original file in the template directory ######################################################################### my $problemContents = ''; # my $editMode = (defined($r->param('problemContents')))? # 'tmpMode':'startMode'; # # if ( $editMode eq 'tmpMode') { # $problemContents = $r->param('problemContents'); # # } else{ eval { $problemContents = WeBWorK::Utils::readFile($problemPath) }; # try to read file $problemContents = $@ if $@; # } # save Action FIXME -- is this the write place for this? # my $actionString = ''; # if ($r->param('submit') eq 'Save') { # $actionString = "File saved to $problemPath"; # #FIXME it would be MUCH better to work with temporary files # open(FILE,">$problemPath") or die "Can't open $problemPath"; # print FILE $problemContents; # close(FILE); # # } ######################################################################### # Format the page ######################################################################### # Define parameters for textarea # FIXME # Should the seed be set from some particular user instance?? # The mode list should be obtained from global.conf ultimately my $rows = 20; my $columns = 80; my $mode_list = ['plainText','formattedText','images']; my $displayMode = $self->{displayMode}; my $problemSeed = $self->{problemSeed}; my $uri = $r->uri; ######################################################################## # Define a link to view the problem #FIXME ######################################################################### return CGI::p($header), #CGI::start_form("POST",$r->uri,-target=>'_problem'), doesn't pass on the target parameter??? qq!