[system] / trunk / webwork2 / lib / WeBWorK / Utils.pm Repository:
ViewVC logotype

View of /trunk/webwork2/lib/WeBWorK/Utils.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1045 - (download) (as text) (annotate)
Fri Jun 6 19:13:51 2003 UTC (10 years ago) by malsyned
File size: 6378 byte(s)
Took out the redundant "confirm email address" from user options.
Also, added a Util function "backtrace", which can be passed one of
"die", "warn", "print", or "return".  I'm just showing off, but it might
prove useful in debugging.
-Dennis

    1 ################################################################################
    2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
    3 # $Id$
    4 ################################################################################
    5 
    6 package WeBWorK::Utils;
    7 use base qw(Exporter);
    8 
    9 =head1 NAME
   10 
   11 WeBWorK::Utils - useful utilities used by other WeBWorK modules.
   12 
   13 =cut
   14 
   15 use strict;
   16 use warnings;
   17 use Date::Format;
   18 use Date::Parse;
   19 use DB; # DeBug, not DataBase
   20 
   21 our @EXPORT    = ();
   22 our @EXPORT_OK = qw(
   23   runtime_use
   24   backtrace
   25   readFile
   26   formatDateTime
   27   parseDateTime
   28   writeLog
   29   writeTimingLogEntry
   30   list2hash
   31   max
   32   readDirectory
   33   dbDecode
   34   dbEncode
   35   decodeAnswers
   36   encodeAnswers
   37   ref2string
   38   dequoteHere
   39   wrapText
   40 );
   41 
   42 sub runtime_use($) {
   43   return unless @_;
   44   eval "package Main; require $_[0]; import $_[0]";
   45   die $@ if $@;
   46 }
   47 
   48 sub backtrace {
   49   my ($style) = @_;
   50   $style = "warn" unless $style;
   51   my @bt = DB->backtrace;
   52   shift @bt; # Remove "backtrace" from the backtrace;
   53   if ($style eq "die") {
   54     die join "\n", @bt;
   55   } elsif ($style eq "warn") {
   56     warn join "\n", @bt;
   57   } elsif ($style eq "print") {
   58     print join "\n", @bt;
   59   } elsif ($style eq "return") {
   60     return @bt;
   61   }
   62 }
   63 
   64 sub readFile($) {
   65   my $fileName = shift;
   66   local *INPUTFILE;
   67   open INPUTFILE, "<", $fileName
   68     or die "Failed to read $fileName: $!";
   69   local $/ = undef;
   70   my $result = <INPUTFILE>;
   71   close INPUTFILE;
   72   return $result;
   73 }
   74 
   75 sub readDirectory($) {
   76   my ($dirname) = @_;
   77 
   78   opendir my $dirhandle, $dirname or die "couldn't open directory $dirname: $!";
   79   my @contents = readdir $dirhandle;
   80   closedir $dirhandle;
   81   return @contents;
   82 }
   83 
   84 sub formatDateTime($) {
   85   my $dateTime = shift;
   86   # "standard" WeBWorK date/time format (for set definition files):
   87   # %m  month number, starting with 01
   88   # %d  numeric day of the month, with leading zeros (eg 01..31)
   89   # %y  year (2 digits)
   90   # %I  hour, 12 hour clock, leading 0's)
   91   # %M  minute, leading 0's
   92   # %P  am or pm (Yes %p and %P are backwards :)
   93   return time2str("%m/%d/%y %I:%M%P", $dateTime);
   94 }
   95 
   96 sub parseDateTime($) {
   97   my $string = shift;
   98   return str2time($string);
   99 }
  100 
  101 sub writeLog($$@) {
  102   my ($ce, $facility, @message) = @_;
  103   unless ($ce->{webworkFiles}->{logs}->{$facility}) {
  104     warn "There is no log file for the $facility facility defined.\n";
  105     return;
  106   }
  107   my $logFile = $ce->{webworkFiles}->{logs}->{$facility};
  108   local *LOG;
  109   if (open LOG, ">>", $logFile) {
  110     print LOG "[", time2str("%a %b %d %H:%M:%S %Y", time), "] @message\n";
  111     close LOG;
  112   } else {
  113     warn "failed to open $logFile for writing: $!";
  114   }
  115 }
  116 
  117 # $ce - a WeBWork::CourseEnvironment object
  118 # $function - fully qualified function name
  119 # $details - any information, do not use the characters '[' or ']'
  120 # $beginEnd - the string "begin", "intermediate", or "end"
  121 # use the intermediate step begun or completed for INTERMEDIATE
  122 # use an empty string for $details when calling for END
  123 sub writeTimingLogEntry($$$$) {
  124   my ($ce, $function, $details, $beginEnd) = @_;
  125   return unless defined $ce->{webworkFiles}->{logs}->{timing};
  126   $beginEnd = ($beginEnd eq "begin") ? ">" : ($beginEnd eq "end") ? "<" : "-";
  127   writeLog($ce, "timing", "$$ ".time." $beginEnd $function [$details]");
  128 }
  129 
  130 sub list2hash {
  131   map {$_ => "0"} @_;
  132 }
  133 
  134 sub max {
  135   my $soFar;
  136   foreach my $item (@_) {
  137     $soFar = $item unless defined $soFar;
  138     if ($item > $soFar) {
  139       $soFar = $item;
  140     }
  141   }
  142   return defined $soFar ? $soFar : 0;
  143 }
  144 
  145 # -----
  146 
  147 sub dbDecode($) {
  148   my $string = shift;
  149   return unless defined $string and $string;
  150   my %hash = $string =~ /(.*?)(?<!\\)=(.*?)(?:(?<!\\)&|$)/g;
  151   $hash{$_} =~ s/\\(&|=)/$1/g foreach keys %hash; # unescape & and =
  152   return %hash;
  153 }
  154 
  155 sub dbEncode(@) {
  156   my %hash = @_;
  157   my $string;
  158   foreach (keys %hash) {
  159     $hash{$_} = "" unless defined $hash{$_}; # promote undef to ""
  160     $hash{$_} =~ s/(=|&)/\\$1/g; # escape & and =
  161     $string .= "$_=$hash{$_}&";
  162   }
  163   chop $string; # remove final '&' from string for old code :p
  164   return $string;
  165 }
  166 
  167 sub decodeAnswers($) {
  168   my $string = shift;
  169   return unless defined $string and $string;
  170   my @array = split m/##/, $string;
  171   $array[$_] =~ s/\\#\\/#/g foreach 0 .. $#array;
  172   push @array, "" if @array%2;
  173   return @array; # it's actually a hash ;)
  174 }
  175 
  176 sub encodeAnswers(\%\@) {
  177   my %hash = %{ shift() };
  178   my @order = @{ shift() };
  179   my $string;
  180   foreach my $name (@order) {
  181     my $value = defined $hash{$name} ? $hash{$name} : "";
  182     $name  =~ s/#/\\#\\/g; # this is a WEIRD way to escape things
  183     $value =~ s/#/\\#\\/g; # and it's not my fault!
  184     $string .= "$name##$value##"; # this is also not my fault
  185   }
  186   $string =~ s/##$//; # remove last pair of hashs
  187   return $string;
  188 }
  189 
  190 # -----
  191 
  192 sub ref2string($;$);
  193 sub ref2string($;$) {
  194   my $ref = shift;
  195   my $dontExpand = shift || {};
  196   my $refType = ref $ref;
  197   my $result;
  198   if ($refType and not $dontExpand->{$refType}) {
  199     my $baseType = refBaseType($ref);
  200     $result .= '<font size="1" color="grey">' . $refType;
  201     $result .= " ($baseType)" if $baseType and $refType ne $baseType;
  202     $result .= ":</font><br>";
  203     $result .= '<table border="1" cellpadding="2">';
  204     if ($baseType eq "HASH") {
  205       my %hash = %$ref;
  206       foreach (sort keys %hash) {
  207         $result .= '<tr valign="top">';
  208         $result .= "<td>$_</td>";
  209         $result .= "<td>" . ref2string($hash{$_}, $dontExpand) . "</td>";
  210         $result .= "</tr>";
  211       }
  212     } elsif ($baseType eq "ARRAY") {
  213       my @array = @$ref;
  214       # special case for Problem, Set, and User objects, which are defined
  215       # using lists and contain a @FIELDS package variable:
  216       no strict 'refs';
  217       my @FIELDS = eval { @{$refType."::FIELDS"} };
  218       use strict 'refs';
  219       undef @FIELDS unless scalar @FIELDS == scalar @array and not $@;
  220       foreach (0 .. $#array) {
  221         $result .= '<tr valign="top">';
  222         $result .= "<td>$_</td>";
  223         $result .= "<td>".$FIELDS[$_]."</td>" if @FIELDS;
  224         $result .= "<td>" . ref2string($array[$_], $dontExpand) . "</td>";
  225         $result .= "</tr>";
  226       }
  227     } elsif ($baseType eq "SCALAR") {
  228       my $scalar = $$ref;
  229       $result .= '<tr valign="top">';
  230       $result .= "<td>$scalar</td>";
  231       $result .= "</tr>";
  232     } else {
  233       # perhaps a coderef? in any case, i don't feel like dealing with it!
  234       $result .= '<tr valign="top">';
  235       $result .= "<td>$ref</td>";
  236       $result .= "</tr>";
  237     }
  238     $result .= "</table>"
  239   } else {
  240     $result .= defined $ref ? $ref : '<font color="red">undef</font>';
  241   }
  242 }
  243 
  244 sub refBaseType($) {
  245   my $ref = shift;
  246   $ref =~ m/(\w+)\(/; # this might not be robust...
  247   return $1;
  248 }
  249 
  250 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9