[system] / branches / rel-2-3-dev / webwork-modperl / lib / WeBWorK / ContentGenerator / Instructor / SendMail.pm Repository:
ViewVC logotype

View of /branches/rel-2-3-dev/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1372 - (download) (as text) (annotate)
Sun Jul 13 17:08:49 2003 UTC (9 years, 10 months ago) by gage
Original Path: trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm
File size: 35889 byte(s)
Preview now works fairly well.  Only the actual send mail action
needs to be implemented
Followed by bug fixes and assignments.
--Mike

    1 package WeBWorK::ContentGenerator::Instructor::SendMail;
    2 use base qw(WeBWorK::ContentGenerator::Instructor);
    3 
    4 =head1 NAME
    5 
    6 WeBWorK::ContentGenerator::Instructor::SendMail - Entry point for User-specific data editing
    7 
    8 =cut
    9 
   10 use strict;
   11 use warnings;
   12 use CGI qw();
   13 use HTML::Entities;
   14 
   15 sub initialize {
   16   my ($self) = @_;
   17   my $r = $self->{r};
   18   my $db = $self->{db};
   19   my $ce = $self->{ce};
   20   my $authz = $self->{authz};
   21   my $user = $r->param('user');
   22 
   23   unless ($authz->hasPermissions($user, "send_mail")) {
   24     $self->{submitError} = "You are not authorized to send mail to students.";
   25     return;
   26   }
   27 #############################################################################################
   28 # gather directory data
   29 #############################################################################################
   30   my $emailDirectory    =    $ce->{courseDirs}->{email};
   31   my $scoringDirectory  =    $ce->{courseDirs}->{scoring};
   32   my $templateDirectory =    $ce->{courseDirs}->{templates};
   33 
   34   my $action            =    $r->param('action');
   35   my $openfilename      =    $r->param('openfilename');
   36   my $savefilename      =    $r->param('savefilename');
   37 
   38 
   39   #FIXME  get these values from global course environment (see subroutines as well)
   40   my $default_msg_file       =    'default.msg';
   41   my $old_default_msg_file   =    'old_default.msg';
   42 
   43 
   44   # store data
   45   $self->{defaultFrom}            =   'FIXME from';
   46   $self->{defaultReply}           =   'FIXME reply';
   47   $self->{rows}                   =   (defined($r->param('rows'))) ? $r->param('rows') : $ce->{mail}->{editor_window_rows};
   48   $self->{columns}                =   (defined($r->param('columns'))) ? $r->param('columns') : $ce->{mail}->{editor_window_columns};
   49   $self->{default_msg_file}     =   $default_msg_file;
   50   $self->{old_default_msg_file}   =   $old_default_msg_file;
   51   $self->{merge_file}             =   (defined($r->param('merge_file'  )))    ? $r->param('merge_file')   : 'None';
   52   $self->{preview_user}           =   (defined($r->param('preview_user')))    ? $r->param('preview_user') : 'Yourself';
   53 
   54 
   55 #############################################################################################
   56 # gather database data
   57 #############################################################################################
   58   # FIXME  this might be better done in body? We don't always need all of this data. or do we?
   59   my @users = sort $db->listUsers;
   60   my @user_records = ();
   61   push(@user_records,$db->getUser($_)) foreach  (@users);
   62 
   63   # store data
   64   $self->{ra_users}              =   \@users;
   65   $self->{ra_user_records}       =   \@user_records;
   66 
   67 #############################################################################################
   68 # gather list of recipients
   69 #############################################################################################
   70   my @send_to                    =   ();
   71   #FIXME  this (radio) is a lousy name
   72   my $recipients                 = $r->param('radio');
   73   if ($recipients eq 'all_students') {  #only active students #FIXME status check??
   74     foreach my $ur (@user_records) {
   75       push(@send_to,$ur->user_id) if $ur->status eq 'C' and not($ur->user_id =~ /practice/);
   76     }
   77   } elsif ($recipients eq 'studentID' ) {
   78     @send_to                   = $r->param('classList');
   79   } else {
   80     warn "Don't understand recipient list |$recipients|";
   81   }
   82   $self->{ra_send_to}               = \@send_to;
   83 #################################################################
   84 # Check the validity of the input file name
   85 #################################################################
   86   my $input_file = '';
   87   #make sure an input message file was submitted and exists
   88   #else use the default message
   89   if ( defined($openfilename) ) {
   90     if ( -e "${emailDirectory}/$openfilename") {
   91       if ( -R "${emailDirectory}/$openfilename") {
   92         $input_file = $openfilename;
   93       } else {
   94         warn join("",
   95           "The file ${emailDirectory}/$openfilename is not readable by the webserver.",CGI::br(),
   96           "Check that it's permissions are set correctly.",
   97         );
   98       }
   99     } else {
  100       $input_file = $default_msg_file;
  101       warn join("",
  102           "The file ${emailDirectory}/$openfilename cannot be found.",CGI::br(),
  103           "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(),
  104           "Using contents of the default message $default_msg_file instead.",
  105       );
  106     }
  107   } else {
  108     $input_file     = $default_msg_file;
  109   }
  110   $self->{input_file} =$input_file;
  111 
  112 #################################################################
  113 # Determine the file name to save message into
  114 #################################################################
  115   my $output_file      = 'FIXME no output file specified';
  116   if (defined($action) and $action eq 'Save as Default') {
  117     $output_file  = $default_msg_file;
  118   } elsif ( defined($action) and ($action =~/save/i) and defined($savefilename) ){
  119     $output_file  = $savefilename;
  120   } elsif ( defined($input_file) ) {
  121     $output_file  = $input_file;
  122   }
  123 # warn "FIXME savefilename $savefilename  output file $output_file";
  124   #################################################################
  125   # Sanity check on save file name
  126   #################################################################
  127 
  128   if ($output_file =~ /^[~.]/ || $output_file =~ /\.\./) {
  129     $self->submission_error("For security reasons, you cannot specify a merge file from a directory",
  130                 "higher than the email directory (you can't use ../blah/blah). ",
  131                 "Please specify a different file or move the needed file to the email directory",
  132     );
  133   }
  134   unless ($output_file =~ m|\.msg$| ) {
  135     $self->submission_error("Invalid file name.",
  136                             "The file name \"$output_file\" does not have a \".msg\" extension",
  137                 "All email file names must end in the extension \".msg\"",
  138                 "choose a file name with a \".msg\" extension.",
  139                 "The message was not saved.",
  140     );
  141   }
  142   $self->{output_file} = $output_file;  # this is ok.  It will be put back in the text input box for re-editing.
  143     # FIXME $output_file can be blank if there was no savefilename
  144 
  145 #############################################################################################
  146 # Determine input source
  147 #############################################################################################
  148   my $input_source =  ( defined( $r->param('body') ) and $action ne 'Open' ) ? 'form' : 'file';
  149 # warn "FIXME input source is $input_source from $input_file";
  150 #############################################################################################
  151 # Get inputs
  152 #############################################################################################
  153   my($from, $replyTo, $r_text, $subject);
  154   if ($input_source eq 'file') {
  155 #   warn "FIXME obtaining source from $emailDirectory/$input_file";
  156     ($from, $replyTo,$subject,$r_text) = $self->read_input_file("$emailDirectory/$input_file");
  157 #   warn "FIXME Done reading source";
  158 
  159   } elsif ($input_source eq 'form') {
  160     # read info from the form
  161     # bail if there is no message body
  162 
  163     $from              =    $r->param('from');
  164     $replyTo           =    $r->param('replyTo');
  165     $subject           =    $r->param('subject');
  166     my $body              =    $r->param('body');
  167     # Sanity check: body must contain non-white space
  168     $self->submission_error('You didn\'t enter any message.') unless ($r->param('body') =~ /\S/);
  169     $r_text               =    \$body;
  170 
  171   }
  172   # store data
  173   $self->{from}                   =    $from;
  174   $self->{replyTo}                =    $replyTo;
  175   $self->{subject}                =    $subject;
  176   $self->{r_text}                 =    $r_text;
  177 
  178 
  179 
  180 ###################################################################################
  181 #Determine the appropriate script action from the buttons
  182 ###################################################################################
  183 #     first time actions
  184 #          open new file
  185 #          open default file
  186 #     choose merge file actions
  187 #          chose merge button
  188 #     option actions
  189 #       'reset rows'
  190 
  191 #     save actions
  192 #   "save" button
  193 #   "save as" button
  194 #   "save as default" button
  195 #     preview actions
  196 #   'preview' button
  197 #     email actions
  198 #   'entire class'
  199 #   'selected studentIDs'
  200 #     error actions (various)
  201 
  202 
  203 #############################################################################################
  204 # if no form is submitted, gather data needed to produce the mail form and return
  205 #############################################################################################
  206   my $to                =    $r->param('To');
  207   my $script_action     = '';
  208 
  209 
  210   if(not defined($action) or $action eq 'Open' or $action eq 'Resize message window'
  211      or $action eq 'Choose merge file' ){
  212 #   warn "FIXME action is |$action| no further initialization required";
  213     return '';
  214   }
  215 
  216 
  217 
  218 
  219 
  220 #############################################################################################
  221 # If form is submitted deal with filled out forms
  222 # and various actions resulting from different buttons
  223 #############################################################################################
  224 
  225 
  226 
  227   # user_errors
  228   # save
  229   # save as
  230   # save as default
  231   # send mail
  232   # set defaults
  233 
  234   if ($action eq 'Save' or $action eq 'Save as:' or $action eq 'Save as Default') {
  235 
  236 #   warn "FIXME Saving files  action = $action  outputFileName=$output_file";
  237 
  238     #################################################################
  239     # construct message body
  240     #################################################################
  241     my $temp_body = ${ $r_text };
  242     $temp_body =~ s/\r\n/\n/g;
  243     $temp_body = join("",
  244            "From: $from \nReply-To: $replyTo\n" ,
  245            "Subject: $subject\n" ,
  246            "Message: \n    $temp_body");
  247 #   warn "FIXME from $from | subject $subject |reply $replyTo|msg $temp_body";
  248     #################################################################
  249     # overwrite protection
  250     #################################################################
  251     if ($action eq 'Save as:' and -e "$emailDirectory/$output_file") {
  252       $self->submission_error("The file $emailDirectory/$output_file already exists and cannot be overwritten",
  253                                "The message was not saved");
  254       return;
  255     }
  256 
  257     #################################################################
  258       # Back up existing file?
  259       #################################################################
  260       if ($action eq 'Save as Default' and -e "$emailDirectory/$default_msg_file") {
  261         rename("$emailDirectory/$default_msg_file","$emailDirectory/$old_default_msg_file") or
  262                die "Can't rename $emailDirectory/$default_msg_file to $emailDirectory/$old_default_msg_file ",
  263                    "Check permissions for webserver on directory $emailDirectory. $!";
  264         $self->{message} .= "Backup file <code>$emailDirectory/$old_default_msg_file</code> created.".CGI::br();
  265       }
  266       #################################################################
  267       # Save the message
  268     #################################################################
  269     $self->saveProblem($temp_body, "${emailDirectory}/$output_file" );
  270     $self->{message}         .= "Message saved to file <code>${emailDirectory}/$output_file</code>.";
  271 #   warn "FIXME saving to ${emailDirectory}/$output_file";
  272   } elsif ($action eq 'Preview') {
  273     $self->{response}         = 'preview';
  274 
  275   } elsif ($action eq 'Send Email') {
  276 
  277 
  278 
  279 
  280   } else {
  281     warn "Don't recognize button $action";
  282   }
  283 
  284   #if Save button was clicked
  285   if (( $r->param('action') eq 'Save') && defined($r->param('body')) && defined($r->param('savefilename'))) {
  286 
  287 
  288   #if Save As button was clicked
  289   } elsif (( $r->param('action') eq 'Save as:') && defined($r->param('body')) && defined($r->param('savefilename'))) {
  290 
  291 
  292   } elsif (( $r->param('action') eq 'save_as_default') && defined($r->param('body'))) {
  293 
  294 
  295   } elsif ( $r->param('action') eq 'Send Email' ) {
  296 
  297     my @studentID = ();
  298 
  299     if ($r->param('To') eq 'classList' && defined($r->param('classList')) && $r->param('classList') ne 'None') {
  300 #         my $classlist = $r->param('classList');
  301 #         my $classListFile = "$templateDirectory$classlist";
  302 #         my @classList = ();
  303 #         #FIXME checkClasslistFile($Global::noOfFieldsInClasslist,$classListFile);
  304 #         open(FILE, "$classListFile") || die "can't open $classListFile";
  305 #         @classList=<FILE>;
  306 #         close(FILE);
  307 #
  308 #         foreach (@classList)   {                        ## read through classlist and send e-mail
  309 #                                                        ## message to all active students
  310 #             unless ($_ =~ /\S/)  {next;}                    ## skip blank lines
  311 #             chomp;
  312 #             my @classListRecord=&getRecord($_);
  313 #             my ($studentID, $lastName, $firstName, $status, $comment,  $section, $recitation, $email_address, $login_name)
  314 #                 = @classListRecord;
  315 #             unless (&dropStatus($status)) {
  316 #               push (@studentID, $studentID);
  317 #               $fn{$studentID} = $firstName;
  318 #             $ln{$studentID} = $lastName;
  319 #             $section{$studentID} = $section;
  320 #             $recitation{$studentID} = $recitation;
  321 #             $status{$studentID} = $status;
  322 #             $email{$studentID} = $email_address;
  323 #             $login{$studentID} = $login_name;
  324 #             }
  325 #         }
  326     }   elsif ($r->param('To') eq 'studentID' && defined($r->param('studentID'))) {
  327       @studentID = $r->param('studentID');
  328       my ($studentID, $login_name);
  329 #
  330 #         foreach $studentID (@studentID) {
  331 #           $login_name = $studentID_LoginName_Hash{$studentID};
  332 #           &attachCLRecord($login_name);
  333 #           $fn{$studentID}     = CL_getStudentFirstName($login_name);
  334 #           $ln{$studentID}     = CL_getStudentLastName($login_name);
  335 #           $section{$studentID}  = CL_getClassSection($login_name);
  336 #           $recitation{$studentID} = CL_getClassRecitation($login_name);
  337 #           $status{$studentID}   = CL_getStudentStatus($login_name);
  338 #           $email{$studentID}    = CL_getStudentEmailAddress($login_name);
  339 #           $login{$studentID}    = $login_name;
  340 #         }
  341 
  342     } elsif ($r->param('To') eq 'all_students') {
  343       @studentID = ();
  344       my ($studentID, $login_name, $status);
  345 
  346 #         foreach $login_name (@availableStudents) {
  347 #           &attachCLRecord($login_name);
  348 #           $status     = CL_getStudentStatus($login_name);
  349 #           next if &dropStatus($status);
  350 #           $studentID    = CL_getStudentID($login_name);
  351 #           push(@studentID,$studentID);
  352 #
  353 #           $fn{$studentID}     = CL_getStudentFirstName($login_name);
  354 #           $ln{$studentID}     = CL_getStudentLastName($login_name);
  355 #           $section{$studentID}  = CL_getClassSection($login_name);
  356 #           $recitation{$studentID} = CL_getClassRecitation($login_name);
  357 #           $status{$studentID}   = CL_getStudentStatus($login_name);
  358 #           $email{$studentID}    = CL_getStudentEmailAddress($login_name);
  359 #           $login{$studentID}    = $login_name;
  360 #         }
  361     } else {
  362       $self->submission_error('You didn\'t select any recipients.  Make sure you select either all student in the course, individual students or a whole classlist.');
  363     }
  364 
  365 #     my $mergeFile = '';
  366 #
  367 #     #the radio button named 'merge' determines whether to take the selected mergefile
  368 #     #or one that was typed in.  A error message is given if select one and use the other
  369 #     $mergeFile = $scoringDirectory . $r->param('mergeFiles')
  370 #       if ($r->param('merge') eq 'mergeFiles' && defined($r->param('mergeFiles')) && $r->param('mergeFiles') ne 'None');
  371 #
  372 #     $mergeFile = $templateDirectory . $r->param('mergeFile')
  373 #       if ($r->param('merge') eq 'mergeFile' && defined($r->param('mergeFile')) && $r->param('mergeFile') !~ m|/$|); #does not end in a /
  374 #
  375 #     if ($mergeFile =~ /^[~.]/ || $mergeFile =~ /\.\./) {
  376 #       $self->submission_error("For security reasons, you cannot specify a merge file from a directory higher than the email directory.  Please specify a different file or move the needed file to the email directory");
  377 #     }
  378 #     if ($r->param('body') =~ /(\$COL\[.*?\])/ && !(-e $mergeFile)) {
  379 #       $self->submission_error("In order to use the \$COL[] you must specify a merge file. The file you specified does not exist.  Also, make sure you selected the right checkbox.");
  380 #     }
  381 #
  382 
  383     my %mergeAArray = ();
  384 #       unless ($mergeFile eq '') {%mergeAArray = &delim2aa($mergeFile);}
  385 #
  386 
  387 #
  388 #       foreach  my $studentID (@studentID) {
  389 #         @COL =();
  390 #         $SID = $studentID;
  391 #         $LN = defined $ln{$studentID} ? $ln{$studentID} :'';
  392 #         $FN = defined $fn{$studentID} ? $fn{$studentID} :'';
  393 #         $SECTION = defined $section{$studentID} ? $section{$studentID} :'';
  394 #         $RECITATION = defined $recitation{$studentID} ? $recitation{$studentID} :'';
  395 #         $EMAIL = defined $email{$studentID} ? $email{$studentID} :'';
  396 #         $STATUS =defined $status{$studentID} ?  $status{$studentID} :'';
  397 #         $LOGIN = $login{$studentID};
  398 #
  399 #         next if ($LOGIN =~ /^$practiceUser/); ## skip practice users
  400 #
  401 #         if ($timeout_attempts >= $max_timeout_attempts) {   ## have attemped to connect to smtp server
  402 #                                   ## the max allowed times.  Now just collect
  403 #                                   ## data on emails not sent and exit
  404 #           ++$emails_not_sent;
  405 #           &log_error(\@exceeded_max_timeout,$FN,$LN,$EMAIL);
  406 #           next;
  407 #         }
  408 #
  409 #         unless ((defined $mergeAArray{$studentID}) or ($mergeFile eq '')) {
  410 #           if ($cgi->param('no_record')) {
  411 #             ++$emails_not_sent;
  412 #             &log_error(\@no_record,$FN,$LN,$EMAIL);
  413 #             next;
  414 #           }
  415 #         }
  416 
  417 #         my ($dbString, @dbArray);
  418 #         if (defined $mergeAArray{$SID}) {
  419 #           $dbString = $mergeAArray{$SID}; ## get sid record from merge file
  420 #           @dbArray = &getRecord($dbString);
  421 #           unshift(@dbArray,$SID);
  422 #           unshift(@dbArray,"");     ## note COL[1] is the first column
  423 #           @COL= @dbArray;       ## put merge fields in COL array
  424 #           $endCol = @COL;       ## \endCol-1 gives last field, etc
  425 #         }
  426 #         my $smtp;
  427 #         if ($smtp = Net::SMTP->new($Global::smtpServer, Timeout => $timeout_sec)) {} else {
  428 # #         &internal_error("Couldn't contact SMTP server.");
  429 #           ++$emails_not_sent;
  430 #           &log_error(\@timeout_problem,$FN,$LN,$EMAIL);
  431 #           ++$timeout_attempts;
  432 #           next;
  433 #         }
  434 #
  435 #         $smtp->mail($smtpSender);
  436 #
  437 #         if ( $smtp->recipient($EMAIL)) {  # this one's okay, keep going
  438 #           if ( $smtp->data("To: $EMAIL\n" . output() ) ) {
  439 #             ++$emails_sent;
  440 #           } else {
  441 #             ++$emails_not_sent;
  442 #             &log_error(\@unknown_problem,$FN,$LN,$EMAIL);
  443 #             next;
  444 #           }
  445 # #         &internal_error("Unknown problem sending message data to SMTP server.");
  446 #         } else {      # we have a problem with this address
  447 #           $smtp->reset;
  448 #           #&internal_error("SMTP server doesn't like this address: <$EMAIL>.");
  449 #           ++$emails_not_sent;
  450 #           &log_error(\@bad_email_addresses,$FN,$LN,$EMAIL);
  451 #         }
  452 #         $smtp->quit;
  453 #       }
  454 #       &success;
  455     }
  456 
  457 
  458 
  459 
  460 }  #end initialize
  461 
  462 # sub fieldEditHTML {
  463 #   my ($self, $fieldName, $value, $properties) = @_;
  464 #   my $size = $properties->{size};
  465 #   my $type = $properties->{type};
  466 #   my $access = $properties->{access};
  467 #   my $items = $properties->{items};
  468 #   my $synonyms = $properties->{synonyms};
  469 #
  470 #
  471 #   if ($access eq "readonly") {
  472 #     return $value;
  473 #   }
  474 #   if ($type eq "number" or $type eq "text") {
  475 #     return CGI::input({type=>"text", name=>$fieldName, value=>$value, size=>$size});
  476 #   }
  477 #   if ($type eq "enumerable") {
  478 #     my $matched = undef; # Whether a synonym match has occurred
  479 #
  480 #     # Process synonyms for enumerable objects
  481 #     foreach my $synonym (keys %$synonyms) {
  482 #       if ($synonym ne "*" and $value =~ m/$synonym/) {
  483 #         $value = $synonyms->{$synonym};
  484 #         $matched = 1;
  485 #       }
  486 #     }
  487 #     if (!$matched and exists $synonyms->{"*"}) {
  488 #       $value = $synonyms->{"*"};
  489 #     }
  490 #     return CGI::popup_menu({
  491 #       name => $fieldName,
  492 #       values => [keys %$items],
  493 #       default => $value,
  494 #       labels => $items,
  495 #     });
  496 #   }
  497 # }
  498 
  499 sub title {
  500   my $self = shift;
  501   return 'Send mail to ' .$self->{ce}->{courseName};
  502 }
  503 
  504 sub path {
  505   my $self          = shift;
  506   my $args          = $_[-1];
  507 
  508   my $ce = $self->{ce};
  509   my $root = $ce->{webworkURLs}->{root};
  510   my $courseName = $ce->{courseName};
  511   return $self->pathMacro($args,
  512     "Home"          => "$root",
  513     $courseName     => "$root/$courseName",
  514     'instructor'    => "$root/$courseName/instructor",
  515     "Send Mail to: $courseName"      => '',
  516   );
  517 }
  518 
  519 sub body {
  520   my ($self, $setID)  = @_;
  521   my $response        = (defined($self->{response}))? $self->{response} : '';
  522   if ($response eq 'preview') {
  523     $self->print_preview($setID);
  524   } else {
  525     $self->print_form($setID);
  526   }
  527 
  528 }
  529 sub print_preview {
  530   my ($self, $setID)  = @_;
  531   #  get preview user
  532   my $ur      = $self->{db}->getUser($self->{preview_user});
  533 
  534   #  get merge file
  535   my $merge_file      = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
  536   my $delimiter       = ',';
  537   my $rh_merge_data   = $self->read_merge_file("$merge_file", "$delimiter");
  538 
  539   my ($msg, $preview_header) = $self->process_message($ur,$rh_merge_data);
  540 
  541   my $recipients  = join(" ",@{$self->{ra_send_to} });
  542 
  543   return join("", '<pre>',$preview_header,$msg,"\n","\n",
  544            '</pre>',
  545            CGI::p('Use browser back button to return from preview mode'),
  546            CGI::h3('Emails to be sent to the following:'),
  547            $recipients, "\n",
  548 
  549   );
  550 
  551 }
  552 sub print_form {
  553   my ($self, $setID) = @_;
  554   my $r = $self->{r};
  555   my $authz = $self->{authz};
  556   my $user = $r->param('user');
  557   my $db = $self->{db};
  558   my $ce = $self->{ce};
  559   my $root = $ce->{webworkURLs}->{root};
  560   my $courseName = $ce->{courseName};
  561 
  562         return CGI::em("You are not authorized to access the Instructor tools.") unless $authz->hasPermissions($user, "access_instructor_tools");
  563 
  564   my $userTemplate = $db->newUser;
  565   my $permissionLevelTemplate = $db->newPermissionLevel;
  566 
  567   # This code will require changing if the permission and user tables ever have different keys.
  568   my @users                 = @{ $self->{ra_users} };
  569   my $ra_user_records       = $self->{ra_user_records};
  570   my %classlistLabels       = ();#  %$hr_classlistLabels;
  571   foreach my $ur (@{ $ra_user_records }) {
  572     $classlistLabels{$ur->user_id} = $ur->user_id.' '.$ur->last_name. ', '. $ur->first_name.' - '.$ur->section;
  573   }
  574 
  575 
  576 ##############################################################################################################
  577 
  578 
  579   my $from            = $self->{from};
  580   my $subject         = $self->{subject};
  581   my $replyTo         = $self->{replyTo};
  582   my $columns         = $self->{columns};
  583   my $rows            = $self->{rows};
  584   my $text            = defined($self->{r_text}) ? ${ $self->{r_text} }: 'FIXME no text was produced by initialization!!';
  585   my $input_file      = $self->{input_file};
  586   my $output_file     = $self->{output_file};
  587   my @sorted_messages = $self->get_message_file_names;
  588   my @sorted_merge_files = $self->get_merge_file_names;
  589   my $merge_file      = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
  590   my $delimiter       = ',';
  591   my $rh_merge_data   = $self->read_merge_file("$merge_file", "$delimiter");
  592   my @merge_keys      = keys %$rh_merge_data;
  593   my $preview_user    = $self->{preview_user};
  594   my $preview_record   = $db->getUser($preview_user);
  595 
  596 #############################################################################################
  597 
  598   print CGI::start_form({method=>"post", action=>$r->uri()});
  599   print $self->hidden_authen_fields();
  600 #############################################################################################
  601 # begin upper table
  602 #############################################################################################
  603 
  604     print CGI::start_table({-border=>'2', -cellpadding=>'4'});
  605   print CGI::Tr({-align=>'left',-valign=>'VCENTER'},
  606 #############################################################################################
  607 # first column
  608 #############################################################################################
  609 
  610        CGI::td("Message file: $input_file","\n",CGI::br(),
  611          CGI::submit(-name=>'action', -value=>'Open'), '&nbsp;&nbsp;&nbsp;&nbsp;',"\n",
  612          CGI::popup_menu(-name=>'openfilename',
  613                          -values=>\@sorted_messages,
  614                          -default=>$input_file
  615          ), "\n",CGI::br(),
  616 
  617          "Save file to: $output_file","\n",CGI::br(),
  618          "\n", 'From:','&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',  CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1),
  619          "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1),
  620          "\n", CGI::br(),'Subject:  ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>35, -override=>1),
  621       ),
  622 #############################################################################################
  623 # second column
  624 #############################################################################################
  625       CGI::td({-align=>'left'},
  626         CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'],
  627           -labels=>{all_students=>'All active students',studentID => 'Select recipients'},
  628           -default=>'studentID',
  629           -linebreak=>1),
  630           CGI::br(),
  631           CGI::popup_menu(-name=>'classList',
  632                  -values=>\@users,
  633                  -labels=>\%classlistLabels,
  634                  -size  => 10,
  635                  -multiple => 1,
  636                  -default=>$user
  637           ),
  638 
  639 
  640       ),
  641 #############################################################################################
  642 # third column
  643 #############################################################################################
  644       CGI::td({align=>'left'},
  645            "Merge file is: $merge_file", CGI::br(),
  646          CGI::submit(-name=>'action', -value=>'Choose merge file'),CGI::br(),
  647          CGI::popup_menu(-name=>'merge_file',
  648                          -values=>\@sorted_merge_files,
  649                          -default=>$merge_file,
  650          ), "\n",CGI::hr(),CGI::br(),
  651         CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview')," email to ",
  652         CGI::popup_menu(-name=>'preview_user',
  653                  -values=>\@users,
  654                  #-labels=>\%classlistLabels,
  655                  -default=>$preview_user,
  656         ),
  657         CGI::hr(),
  658         CGI::submit(-name=>'action', -value=>'resize', -label=>'Resize message window'),CGI::br(),
  659         " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows),
  660         " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns),
  661         CGI::br(),CGI::br(),
  662       #show available macros
  663         CGI::popup_menu(
  664             -name=>'dummyName',
  665             -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'],
  666             -labels=>{''=>'list of insertable macros',
  667               '$SID'=>'$SID - Student ID',
  668               '$FN'=>'$FN - First name',
  669               '$LN'=>'$LN - Last name',
  670               '$SECTION'=>'$SECTION',
  671               '$RECITATION'=>'$RECITATION',
  672               '$STATUS'=>'$STATUS - C, Audit, Drop, etc.',
  673               '$EMAIL'=>'$EMAIL - Email address',
  674               '$LOGIN'=>'$LOGIN - Login',
  675               '$COL[3]'=>'$COL[3] - 3rd col',
  676               '$COL[-1]'=>'$COL[-1] - Last column'
  677               }
  678         ), "\n",
  679       ),
  680 
  681   ); # end Tr
  682   print CGI::end_table();
  683 #############################################################################################
  684 # end upper table
  685 #############################################################################################
  686 
  687 # show merge file
  688 #         print  "<pre>",(map {$_ =~s/\s/\./g;$_}     map {sprintf('%-8.8s',$_);}  0..8),"</pre>";
  689 #     print  CGI::popup_menu(
  690 #             -name=>'dummyName2',
  691 #             -values=>\@merge_keys,
  692 #             -labels=>$rh_merge_data,
  693 #             -multiple=>1,
  694 #             -size    =>2,
  695 #
  696 #         ), "\n",CGI::br();
  697 #       warn "merge keys ", join( " ",@merge_keys);
  698 #############################################################################################
  699 # merge file fragment and message text area field
  700 #############################################################################################
  701 
  702         my @tmp2= @{$rh_merge_data->{ $db->getUser($preview_user)->student_id  }  };
  703     print CGI::pre("",data_format(0..($#tmp2)),"\n", data_format(@tmp2));
  704 #create a textbox with the subject and a textarea with the message
  705 #print actual body of message
  706 
  707   print  "\n", CGI::p( $self->{message}) if defined($self->{message});
  708     print  "\n", CGI::p( CGI::textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1));
  709 
  710 #############################################################################################
  711 # action button table
  712 #############################################################################################
  713   print    CGI::table( { -border=>2,-cellpadding=>4},
  714          CGI::Tr(
  715            CGI::td( CGI::submit(-name=>'action', -value=>'Send Email') ), "\n",
  716            CGI::td(CGI::submit(-name=>'action', -value=>'Save')," to $output_file"), " \n",
  717            CGI::td(CGI::submit(-name=>'action', -value=>'Save as:'),
  718                    CGI::textfield(-name=>'savefilename', -size => 20, -value=> "$output_file", -override=>1)
  719            ), "\n",
  720            CGI::td(CGI::submit(-name=>'action', -value=>'Save as Default')),
  721         )
  722   );
  723 
  724 ##############################################################################################################
  725 
  726   print CGI::end_form();
  727   return "";
  728 }
  729 
  730 ##############################################################################
  731 # Utility methods
  732 ##############################################################################
  733 sub submission_error {
  734   my $self = shift;
  735     my $msg = join( " ", @_);
  736   $self->{submitError}= $msg; #CGI::b(HTML::Entities::encode($msg));
  737 #     qq{Please hit the &quot;<B>Back</B>&quot; button on your browser to
  738 #     try again, or notify your web master
  739 #     if you believe this message is in error.
  740 #     };
  741     return;
  742 }
  743 
  744 sub saveProblem {
  745     my $self      = shift;
  746   my ($body, $probFileName)= @_;
  747   local(*PROBLEM);
  748   open (PROBLEM, ">$probFileName") ||
  749     $self->submission_error("Could not open $probFileName for writing.
  750     Check that the  permissions for this problem are 660 (-rw-rw----)");
  751   print PROBLEM $body;
  752   close PROBLEM;
  753   chmod 0660, "$probFileName" ||
  754                $self->submission_error("
  755                       CAN'T CHANGE PERMISSIONS ON FILE $probFileName");
  756 }
  757 
  758 sub read_input_file {
  759   my $self         = shift;
  760   my $filePath     = shift;
  761   my ($text, @text);
  762   my $header = '';
  763   my ($subject, $from, $replyTo);
  764   local(*FILE);
  765   if (-e "$filePath" and -r "$filePath") {
  766     open FILE, "$filePath" || do { $self->submission_error("Can't open $filePath"); return};
  767     while ($header !~ s/Message:\s*$//m and not eof(FILE)) {
  768       $header .= <FILE>;
  769     }
  770     $text = join( '', <FILE>);
  771     $text =~ s/^\s*//; # remove initial white space if any.
  772     $header         =~ /^From:\s(.*)$/m;
  773     $from           = $1 or $from = $self->{defaultFrom};
  774 
  775     $header         =~ /^Reply-To:\s(.*)$/m;
  776     $replyTo        = $1 or $replyTo = $self->{defaultReply};
  777 
  778     $header         =~ /^Subject:\s(.*)$/m;
  779     $subject        = $1;
  780 
  781   } else {
  782     $from           = $self->{defaultFrom};
  783     $replyTo        = $self->{defaultReply};
  784     $text           =  (-e "$filePath") ? "FIXME file $filePath can't be read" :"FIXME file $filePath doesn't exist";
  785     $subject        = "FIXME default subject";
  786   }
  787   return ($from, $replyTo, $subject, \$text);
  788 }
  789 
  790 sub get_message_file_names {
  791   my $self             = shift;
  792   my $emailDirectory   = $self->{ce}->{courseDirs}->{email};
  793   #get all message files and create a list
  794   local(*EMAILDIR);
  795   opendir( EMAILDIR, $emailDirectory )|| die "Can't access directory $emailDirectory. Please check that webserver has permission to read this directory.";
  796     my @messageFiles = grep /\.msg$/, readdir EMAILDIR; #all message files
  797   closedir EMAILDIR;
  798 
  799   return sort @messageFiles;
  800 }
  801 sub get_merge_file_names {
  802   my $self             = shift;
  803   my $scoringDirectory   = $self->{ce}->{courseDirs}->{scoring};
  804   #get all message files and create a list
  805   local(*SCORINGDIR);
  806   opendir( SCORINGDIR, $scoringDirectory )|| die "Can't access directory $scoringDirectory.",
  807                                              "Please check that webserver has permission to read this directory.";
  808   my @mergeFiles = grep( /\.csv$/, readdir SCORINGDIR); #all message files
  809   closedir SCORINGDIR;
  810   @mergeFiles    = sort @mergeFiles;
  811 # warn "FIXME scoring directory $scoringDirectory merge Files", join(" ", @mergeFiles);
  812   unshift(@mergeFiles, 'None');
  813   return @mergeFiles;
  814 }
  815 
  816 sub read_merge_file    {
  817   my $self            = shift;
  818   my $fileName        = shift;
  819   my $delimiter       = shift;
  820   $delimiter          = ',' unless defined($delimiter);
  821   my $scoringDirectory= $self->{ce}->{courseDirs}->{scoring};
  822   my $filePath        = "$scoringDirectory/$fileName";
  823         #       Takes a delimited file as a parameter and returns an
  824         #       associative array with the first field as the key.
  825         #       Blank lines are skipped. White space is removed
  826     my(@dbArray,$key,%assocArray,$dbString);
  827     local(*FILE);
  828     open(FILE, "$filePath") or $self->submission_error("Can't open file $filePath");
  829     my $index=0;
  830   while (<FILE>){
  831     unless ($_ =~ /\S/)  {next;}               ## skip blank lines
  832     chomp;
  833     @{$dbArray[$index]} =$self->getRecord($_,$delimiter);
  834     $key    =$dbArray[$index][0];
  835     #@dbArray    =  map {$_ =~s/\s/\./g;$_}     map {sprintf('%-8.8s',$_);}  @dbArray;
  836     #$dbString   = join(" | ",@dbArray);
  837     $assocArray{$key}=$dbArray[$index];
  838     $index++;
  839   }
  840         close(FILE);
  841         return \%assocArray;
  842 }
  843 sub getRecord {
  844   my $self    = shift;
  845   my $line    = shift;
  846   my $delimiter   = shift;
  847   $delimiter       = ',' unless defined($delimiter);
  848 
  849         #       Takes a delimited line as a parameter and returns an
  850         #       array.  Note that all white space is removed.  If the
  851         #       last field is empty, the last element of the returned
  852         #       array is also empty (unlike what the perl split command
  853         #       would return).  E.G. @lineArray=&getRecord(\$delimitedLine).
  854 
  855         my(@lineArray);
  856         $line.=$delimiter;                              # add 'A' to end of line so that
  857                                                         # last field is never empty
  858         @lineArray = split(/\s*${delimiter}\s*/,$line);
  859         $lineArray[0] =~s/^\s*//;                       # remove white space from first element
  860         @lineArray;
  861 }
  862 
  863 sub process_message {
  864   my $self          = shift;
  865   my $ur            = shift;
  866   my $rh_merge_data = shift;
  867   my $text          = defined($self->{r_text}) ? ${ $self->{r_text} }:
  868                           'FIXME no text was produced by initialization!!';
  869   #user macros that can be used in the email message
  870   my $SID           = $ur->student_id;
  871   my $FN            = $ur->first_name;
  872   my $LN            = $ur->last_name;
  873   my $SECTION       = $ur->section;
  874   my $RECITATION    = $ur->recitation;
  875   my $STATUS        = $ur->status;
  876   my $EMAIL         = $ur->email_address;
  877   my $LOGIN         = $ur->user_id;
  878   # get record from merge file
  879   # FIXME this is inefficient.  The info should be cached
  880   my @COL            = @{$rh_merge_data->{$SID} };
  881 
  882   my $endCol = @COL;
  883   # for safety, only evaluate special variables
  884   my $tmp = $text;
  885   $tmp =~ s/(\$SID)/eval($1)/ge;
  886   $tmp =~ s/(\$LN)/eval($1)/ge;
  887   $tmp =~ s/(\$FN)/eval($1)/ge;
  888   $tmp =~ s/(\$STATUS)/eval($1)/ge;
  889   $tmp =~ s/(\$SECTION)/eval($1)/ge;
  890   $tmp =~ s/(\$RECITATION)/eval($1)/ge;
  891   $tmp =~ s/(\$EMAIL)/eval($1)/ge;
  892   $tmp =~ s/(\$LOGIN)/eval($1)/ge;
  893   $tmp =~ s/\$COL\[ *-/\$COL\[$endCol-/g;
  894   $tmp =~ s/(\$COL\[.*?\])/eval($1)/ge;
  895 
  896   my $preview_header =  CGI::pre("",data_format(0..($#COL)),"\n", data_format(@COL)).
  897                         CGI::h3( "This sample mail would be sent to $EMAIL");
  898 
  899 
  900   my $msg = join("",
  901      "To: "             , $ur->email_address,"\n",
  902        "From: "           , $self->{from} , "\n" ,
  903        "Reply-To: "       , $self->{replyTo} , "\n" ,
  904        "Subject:  "       , $self->{subject} , "\n" ,"\n" ,
  905      $tmp , "\n"
  906   );
  907 
  908   $msg =~ s/\r//g;
  909   return $msg, $preview_header;
  910 }
  911  sub data_format {
  912   map {$_ =~s/\s/\./g;$_}     map {sprintf('%-8.8s',$_);}  @_;
  913  }
  914 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9