[system] / trunk / webwork-modperl / lib / WeBWorK / ContentGenerator / Instructor / PGProblemEditor.pm Repository:
ViewVC logotype

View of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/PGProblemEditor.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1663 - (download) (as text) (annotate)
Tue Dec 9 01:12:32 2003 UTC (9 years, 5 months ago) by sh002i
File size: 13778 byte(s)
Normalized headers. All files now contain the text below as a header.
This is important since all files now (a) use the full name of the
package, (b) assign copyright to "The WeBWorK Project", (c) give the
full path of the file (relative to CVSROOT) instead of simply the file
name, and (d) include license and warranty information.

Here is the new header:

################################################################################
# WeBWorK Online Homework Delivery System
# Copyright © 2000-2003 The WeBWorK Projcct, http://openwebwork.sf.net/
# $CVSHeader$
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of either: (a) the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version, or (b) the "Artistic License" which comes with this package.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
# Artistic License for more details.
################################################################################

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader$
    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::Instructor::PGProblemEditor;
   18 use base qw(WeBWorK::ContentGenerator::Instructor);
   19 
   20 
   21 =head1 NAME
   22 
   23 WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list
   24 
   25 =cut
   26 
   27 use strict;
   28 use warnings;
   29 use CGI qw();
   30 use WeBWorK::Utils qw(readFile);
   31 use Apache::Constants qw(:common REDIRECT);
   32 
   33 
   34 our $libraryName;
   35 our $rowheight;
   36 
   37 sub title {
   38   my $self = shift;
   39   #FIXME  don't need the entire path  ??
   40   return "Instructor Tools - PG Problem Editor ";
   41 }
   42 sub go {
   43   my $self      = shift;
   44   my ($setName, $problemNumber) = @_;
   45   my $r         =   $self->{r};
   46   my $ce        = $self->{ce};
   47   my $submit_button   = $r->param('submit');  # obtain submit command from form
   48 
   49   # various actions depending on state.
   50   if (     defined($submit_button) and ($submit_button eq 'Save' or $submit_button eq 'Refresh')    ) {
   51 
   52     $self->initialize($setName,$problemNumber);  # write the necessary files
   53                            # return file path for viewing problem
   54                            # in $self->{currentSourceFilePath}
   55     #redirect to view the problem
   56 
   57     my $hostname    =   $r->hostname();
   58     my $port        =   $r->get_server_port();
   59     my $uri       =   $r->uri;
   60     my $courseName    = $self->{ce}->{courseName};
   61     my $problemSeed   =   ($r->param('problemSeed')) ? $r->param('problemSeed') : '';
   62     my $displayMode   = ($r->param('displayMode')) ? $r->param('displayMode') : '';
   63         my $viewURL         =   '';
   64         if ($self->{file_type} eq 'problem') {
   65           # redirect to have problem read by Problem.pm
   66       $viewURL      =   "http://$hostname:$port";
   67       $viewURL       .=   $ce->{webworkURLs}->{root}."/$courseName/$setName/$problemNumber/?";
   68       $viewURL       .= $self->url_authen_args;
   69       $viewURL       .=   "&displayMode=$displayMode&problemSeed=$problemSeed";   # optional displayMode and problemSeed overrides
   70       if ($submit_button eq 'Save') {
   71         $viewURL       .= "&editMode=savedFile";
   72       } else {
   73         $viewURL       .= "&editMode=temporaryFile";
   74       }
   75       $viewURL       .= '&sourceFilePath='. $self->{currentSourceFilePath}; # path to pg text for viewing
   76                                                                                   # allows Problem.pg to recognize state
   77                                                                                       # of problem being viewed.
   78       } elsif ($self->{file_type} eq 'set_header') {
   79         # redirect set headers to ProblemList page
   80         $viewURL      =   "http://$hostname:$port";
   81       $viewURL       .=   $ce->{webworkURLs}->{root}."/$courseName/$setName/?";
   82       $viewURL       .= $self->url_authen_args;
   83       $viewURL       .=   "&displayMode=$displayMode&problemSeed=$problemSeed";   # optional displayMode and problemSeed overrides
   84       if ($submit_button eq 'Save') {
   85         $viewURL       .= "&editMode=savedFile";
   86       }
   87     }
   88     $r->header_out(Location => $viewURL );
   89     return REDIRECT;
   90   } else {
   91     # initialize and
   92     # display the editing window
   93 
   94     $self->SUPER::go(@_);
   95   }
   96 
   97 }
   98 
   99 sub initialize {
  100 
  101   my ($self, $setName, $problemNumber) = @_;
  102   my $ce            =   $self->{ce};
  103   my $r           = $self->{r};
  104   my $path_info         =   $r->path_info || "";
  105   my $db            = $self->{db};
  106   my $user          = $r->param('user');
  107   my $effectiveUserName   = $r->param('effectiveUser');
  108   my $courseName        = $ce->{courseName};
  109 
  110 
  111   # Find URL for viewing problem
  112 
  113   # find path to pg file for the problem
  114 
  115   my $templateDirectory   = $ce->{courseDirs}->{templates};
  116   my $problemPath             =   $templateDirectory;
  117   my $problem_record          =   undef;
  118     # FIXME  there is a discrepancy in the way that the problems are found.
  119     # FIXME  more error checking is needed in case the problem doesn't exist.
  120   if (defined($problemNumber) and $problemNumber) {
  121     $problem_record   = $db->getMergedProblem($effectiveUserName, $setName, $problemNumber);
  122     # If there is no global_user defined problem, (i.e. the sets haven't been assigned yet),
  123     # look for a global version of the problem.
  124     $problem_record     = $db->getGlobalProblem($setName, $problemNumber) unless defined($problem_record);
  125     # bail if no problem is found
  126     die "Cannot find a problem record for set $setName / problem $problemNumber"
  127       unless defined($problem_record);
  128     $problemPath           .=   '/'.$problem_record->source_file;
  129     $self->{file_type}      =   'problem';
  130   } elsif (defined($problemNumber) and $problemNumber==0) { # we are editing a header file
  131     my $set_record          =   $db->getMergedSet($effectiveUserName, $setName);
  132     die "Cannot find a set record for set $setName" unless defined($set_record);
  133     $problemPath           .=   '/'.$set_record->set_header;
  134     $self->{file_type}      =   'set_header';
  135   }
  136 
  137   my $editFileSuffix      = $user.'.tmp';
  138   my $submit_button     =   $r->param('submit');
  139 
  140   my $displayMode         =   ( defined($r->param('displayMode'))   ) ? $r->param('displayMode') : $ce->{pg}->{options}->{displayMode};
  141   # try to get problem seed from the input parameter, or from the problem record
  142   my $problemSeed;
  143   if ( defined($r->param('problemSeed'))  ) {
  144     $problemSeed            =   $r->param('problemSeed');
  145   } elsif (defined($problem_record) and  $problem_record->can('problem_seed')) {
  146     $problemSeed            =   $problem_record->problem_seed;
  147   }
  148   # make absolutely sure that the problem seed is defined, if it hasn't been.
  149   $problemSeed        = '123456' unless defined($problemSeed) and $problemSeed =~/\S/;
  150 
  151   my $problemContents = '';
  152   my $currentSourceFilePath = '';
  153   my $editErrors = '';
  154 
  155   # update the .pg and .pg.tmp files in the directory
  156   # if a .tmp file already exists use that, unless the revert button has been pressed.
  157   # These .tmp files are
  158   # removed when the file is finally saved.
  159   my $inputFilePath           =  (-r "$problemPath.$editFileSuffix")?"$problemPath.$editFileSuffix" : $problemPath;
  160   $inputFilePath              =   $problemPath  if defined($submit_button) and $submit_button eq 'Revert';
  161 
  162   if (not defined($submit_button) or $submit_button eq 'Revert' ) {
  163     # this is a fresh editing job
  164     # copy the pg file to a new file with the same name with .tmp added
  165     # store this name in the $self->currentSourceFilePath for use in body
  166     eval { $problemContents     = WeBWorK::Utils::readFile($inputFilePath)    };
  167     # try to read file
  168     $problemContents = $@ if $@;
  169     $editErrors .= $problemContents;
  170     $currentSourceFilePath      = "$problemPath.$editFileSuffix";
  171     $self->{currentSourceFilePath}  = $currentSourceFilePath;
  172   } elsif ($submit_button eq 'Refresh' ) {
  173     # grab the problemContents from the form in order to save it to the tmp file
  174     # store tmp file name in the $self->currentSourceFilePath for use in body
  175 
  176     $problemContents        = $r->param('problemContents');
  177     $currentSourceFilePath      = "$problemPath.$editFileSuffix";
  178     $self->{currentSourceFilePath}  = $currentSourceFilePath;
  179   } elsif ($submit_button eq 'Save') {
  180     # grab the problemContents from the form in order to save it to the permanent file
  181     # later we will unlink (delete) the temporary file
  182     # store permanent file name in the $self->currentSourceFilePath for use in body
  183 
  184     $problemContents        = $r->param('problemContents');
  185     $currentSourceFilePath      = "$problemPath";
  186     $self->{currentSourceFilePath}  = $currentSourceFilePath;
  187   } else {
  188     # give a warning
  189     die "Unrecognized submit command $submit_button";
  190   }
  191 
  192   # Handle the problem of line endings.  Make sure that all of the line endings.  Convert \r\n to \n
  193   $problemContents    =~    s/\r\n/\n/g;
  194   $problemContents    =~    s/\r/\n/g;
  195 
  196   # print changed pg files
  197   # FIXME  make sure that the permissions are set correctly!!!
  198   # Make sure that the warning is being transmitted properly.
  199 
  200   eval {
  201     local *OUTPUTFILE;
  202     open OUTPUTFILE, ">", $currentSourceFilePath
  203         or die "Failed to write to $currentSourceFilePath.
  204         It is likely that the permissions in the template directory have not been set correctly.".
  205         "The web server must be able to create and write to files in the directory containing the problem.
  206         $!";
  207     print OUTPUTFILE $problemContents;
  208     close OUTPUTFILE;
  209   };
  210   # record an error string for later use if there was a difficulty in writing to the file
  211   # FIXME is this string every inspected?
  212 
  213   my $openTempFileErrors = $@ if $@;
  214 
  215   if (  $openTempFileErrors)   {
  216 
  217     $self->{openTempFileErrors} = "Unable to write to $currentSourceFilePath: $openTempFileErrors";
  218     #diagnose errors:
  219     warn "Editing errors: $openTempFileErrors\n";
  220     warn "The file $currentSourceFilePath exists. \n " if -e $currentSourceFilePath; #FIXME
  221     warn "The file $currentSourceFilePath cannot be found. \n " unless -e $currentSourceFilePath;
  222     warn "The file $currentSourceFilePath does not have write permissions. \n"
  223                      if -e $currentSourceFilePath and not -w $currentSourceFilePath;
  224 
  225 
  226 
  227   } else {
  228     # unlink the temporary file if there are no errors and the save button has been pushed
  229 
  230     $self->{openTempFileErrors} = '';
  231     unlink("$problemPath.$editFileSuffix") if defined($submit_button) and $submit_button eq 'Save';
  232   };
  233 
  234 
  235   # return values for use in the body subroutine
  236   $self->{problemPath}              =   $problemPath;
  237   $self->{inputFilePath}            =   $inputFilePath;
  238   $self->{displayMode}              =   $displayMode;
  239   $self->{problemSeed}              =   $problemSeed;
  240   $self->{r_problemContents}        =   \$problemContents;
  241   # FIXME  there is no way to edit in a temporary file -- all editing takes place on disk!!!
  242 
  243 
  244 
  245 }
  246 
  247 sub path {
  248   my $self          = shift;
  249   my $set_id        = shift;
  250   my $problem_id    = shift;
  251   my $args          = $_[-1];
  252 
  253   my $ce = $self->{ce};
  254   my $root = $ce->{webworkURLs}->{root};
  255   my $courseName = $ce->{courseName};
  256   return $self->pathMacro($args,
  257     "Home"          => "$root",
  258     $courseName     => "$root/$courseName",
  259     'instructor'    => "$root/$courseName/instructor",
  260     'sets'          => "$root/$courseName/instructor/sets/",
  261     "$set_id"       => "$root/$courseName/instructor/sets/$set_id/",
  262     "problems"      => "$root/$courseName/instructor/sets/$set_id/problems",
  263     "$problem_id"   => ''
  264   );
  265 }
  266 sub body {
  267   my $self = shift;
  268 
  269   # test area
  270   my $r       =   $self->{r};
  271   my $db      =   $self->{db};
  272   my $ce      =   $self->{ce};
  273   my $user    =   $r->param('user');
  274   my $key     =   $db->getKey($user)->key();
  275 
  276 
  277   ################
  278   # Gathering info
  279   # What is needed
  280   #     $problemPath  --
  281   #     $formURL -- given by $r->uri
  282   #     $tmpProblemPath
  283   my $problemPath            =   $self->{problemPath};
  284   my $inputFilePath            =   $self->{inputFilePath};
  285 
  286 
  287 
  288 
  289 
  290 
  291   my $header = CGI::i("Editing problem:  $inputFilePath");
  292 
  293   #########################################################################
  294   # Find the text for the problem, either in the tmp file, if it exists
  295   # or in the original file in the template directory
  296   #########################################################################
  297   my $problemContents = ${$self->{r_problemContents}};
  298 
  299 # eval { $problemContents = WeBWorK::Utils::readFile($problemPath)  };  # try to read file
  300 # $problemContents = $@ if $@;
  301 
  302 
  303 
  304   #########################################################################
  305   # Format the page
  306   #########################################################################
  307   # Define parameters for textarea
  308   # FIXME
  309   # Should the seed be set from some particular user instance??
  310   # The mode list should be obtained from global.conf ultimately
  311   my $rows    =   20;
  312   my $columns   =   80;
  313   my $mode_list   =   ['plainText','formattedText','images'];
  314   my $displayMode =   $self->{displayMode};
  315   my $problemSeed = $self->{problemSeed};
  316   my $uri     = $r->uri;
  317   ########################################################################
  318   # Define a link to view the problem
  319   #FIXME
  320 
  321   #########################################################################
  322 
  323 
  324   warn "Errors in the problem ".CGI::br().$self->{editErrors} if $self->{editErrors};
  325 
  326 
  327   return CGI::p($header),
  328     #CGI::start_form("POST",$r->uri,-target=>'_problem'),  doesn't pass on the target parameter???
  329     qq!<form method="POST" action="$uri" enctype="application/x-www-form-urlencoded", target="_problem">!,
  330     $self->hidden_authen_fields,
  331     CGI::hidden(-name=>'file_type',-default=>$self->{file_type}),
  332     CGI::div(
  333     'Seed: ',
  334     CGI::textfield(-name=>'problemSeed',-value=>$problemSeed),
  335     'Mode: ',
  336     CGI::popup_menu(-name=>'displayMode', -'values'=>$mode_list,
  337                            -default=>$displayMode),
  338     CGI::a(
  339       {-href=>'http://webwork.math.rochester.edu/docs/docs/pglanguage/manpages/',-target=>"manpage_window"},
  340       'Manpages',
  341       )
  342     ),
  343     CGI::p(
  344       CGI::textarea(-name => 'problemContents', -default => $problemContents,
  345               -rows => $rows, -columns => $columns, -override => 1,
  346       ),
  347     ),
  348     CGI::p(
  349       ( ($self->{file_type} eq 'problem') ? CGI::submit(-value=>'Refresh',-name=>'submit') : ''   ),
  350       CGI::submit(-value=>'Save',-name=>'submit'),
  351       CGI::submit(-value=>'Revert',-name=>'submit'),
  352     ),
  353     CGI::end_form(),
  354 
  355 
  356 }
  357 
  358 
  359 
  360 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9