version 1.16, 2003/02/28 23:47:37
|
version 1.20, 2003/03/23 07:22:58
|
Line 19 All classes are in the Apache::lonwizard
|
Line 19 All classes are in the Apache::lonwizard
|
|
|
=cut |
=cut |
|
|
# To prevent runaway file counts, this file has lonwizard, |
|
# lonwizstate, and other wizard classes. |
|
use strict; |
use strict; |
|
|
use HTML::Entities; |
use HTML::Entities; |
use Apache::loncommon; |
use Apache::loncommon; |
|
use Digest::MD5 qw(md5_hex); |
|
use Apache::File; |
|
|
=pod |
=pod |
|
|
Line 76 sub new {
|
Line 76 sub new {
|
$self->{STATE} = "START"; |
$self->{STATE} = "START"; |
} |
} |
|
|
|
$self->{TOKEN} = $ENV{'form.TOKEN'}; |
|
# If a token was passed, we load that in. Otherwise, we need to create a |
|
# new storage file |
|
# Tried to use standard Tie'd hashes, but you can't seem to take a |
|
# reference to a tied hash and write to it. I'd call that a wart. |
|
if ($self->{TOKEN}) { |
|
# Validate the token before trusting it |
|
if ($self->{TOKEN} !~ /^[a-f0-9]{32}$/) { |
|
# Not legit. Return nothing and let all hell break loose. |
|
# User shouldn't be doing that! |
|
return undef; |
|
} |
|
|
|
# Get the hash. |
|
$self->{FILENAME} = $Apache::lonnet::tmpdir . md5_hex($self->{TOKEN}); # Note the token is not the literal file |
|
|
|
my $file = Apache::File->new($self->{FILENAME}); |
|
my $contents = <$file>; |
|
&Apache::loncommon::get_unprocessed_cgi($contents); |
|
$file->close(); |
|
|
|
# Marks whether this is a new wizard. |
|
$self->{NEW_WIZARD} = 0; |
|
} else { |
|
# Only valid if we're just starting. |
|
if ($self->{STATE} ne 'START') { |
|
return undef; |
|
} |
|
# Must create the storage |
|
$self->{TOKEN} = md5_hex($ENV{'user.name'} . $ENV{'user.domain'} . |
|
time() . rand()); |
|
$self->{FILENAME} = $Apache::lonnet::tmpdir . md5_hex($self->{TOKEN}); |
|
|
|
# Marks whether this is a new wizard. |
|
$self->{NEW_WIZARD} = 1; |
|
} |
|
|
|
# OK, we now have our persistent storage. |
|
|
if (defined $ENV{"form.RETURN_PAGE"}) |
if (defined $ENV{"form.RETURN_PAGE"}) |
{ |
{ |
$self->{RETURN_PAGE} = $ENV{"form.RETURN_PAGE"}; |
$self->{RETURN_PAGE} = $ENV{"form.RETURN_PAGE"}; |
Line 86 sub new {
|
Line 125 sub new {
|
} |
} |
|
|
$self->{STATES} = {}; |
$self->{STATES} = {}; |
$self->{VARS} = {}; |
|
$self->{HISTORY} = {}; |
$self->{HISTORY} = {}; |
$self->{DONE} = 0; |
$self->{DONE} = 0; |
|
|
Line 129 sub declareVars {
|
Line 167 sub declareVars {
|
foreach my $element ( @{$varlist} ) |
foreach my $element ( @{$varlist} ) |
{ |
{ |
# assign the var the default of "" |
# assign the var the default of "" |
$self->{VARS}{$element} = ""; |
$self->{VARS}->{$element} = ""; |
|
|
# if there's a form in the env, use that instead |
my $envname; |
my $envname = "form." . $element; |
|
if (defined ($ENV{$envname})) { |
|
$self->{VARS}->{$element} = $ENV{$envname}; |
|
} |
|
|
|
|
$envname = "form." . $element; |
|
if (defined ($ENV{$envname})) { |
|
$self->{VARS}->{$element} = $ENV{$envname}; |
|
} |
|
|
# If there's an incoming form submission, use that |
# If there's an incoming form submission, use that |
$envname = "form." . $element . ".forminput"; |
$envname = "form." . $element . ".forminput"; |
if (defined ($ENV{$envname})) { |
if (defined ($ENV{$envname})) { |
Line 145 sub declareVars {
|
Line 184 sub declareVars {
|
} |
} |
} |
} |
|
|
# Private function; takes all of the declared vars and returns a string |
# Private function; returns a string to construct the hidden fields |
# corresponding to the hidden input fields that will re-construct the |
# necessary to have the wizard track state. |
# variables. |
|
sub _saveVars { |
sub _saveVars { |
my $self = shift; |
my $self = shift; |
my $result = ""; |
my $result = ""; |
foreach my $varname (keys %{$self->{VARS}}) |
|
{ |
|
$result .= '<input type="hidden" name="' . |
|
HTML::Entities::encode($varname) . '" value="' . |
|
HTML::Entities::encode($self->{VARS}{$varname}) . |
|
"\" />\n"; |
|
} |
|
|
|
# also save state & return page |
|
$result .= '<input type="hidden" name="CURRENT_STATE" value="' . |
$result .= '<input type="hidden" name="CURRENT_STATE" value="' . |
HTML::Entities::encode($self->{STATE}) . '" />' . "\n"; |
HTML::Entities::encode($self->{STATE}) . "\" />\n"; |
|
$result .= '<input type="hidden" name="TOKEN" value="' . |
|
$self->{TOKEN} . "\" />\n"; |
$result .= '<input type="hidden" name="RETURN_PAGE" value="' . |
$result .= '<input type="hidden" name="RETURN_PAGE" value="' . |
HTML::Entities::encode($self->{RETURN_PAGE}) . '" />' . "\n"; |
HTML::Entities::encode($self->{RETURN_PAGE}) . "\" />\n"; |
|
|
return $result; |
return $result; |
} |
} |
|
|
|
# Private function: Create the querystring-like representation of the stored |
|
# data to write to disk. |
|
sub _varsInFile { |
|
my $self = shift; |
|
my @vars = (); |
|
for my $key (keys %{$self->{VARS}}) { |
|
push @vars, &Apache::lonnet::escape($key) . '=' . |
|
&Apache::lonnet::escape($self->{VARS}->{$key}); |
|
} |
|
return join ('&', @vars); |
|
} |
|
|
=pod |
=pod |
|
|
=item B<registerState>(referenceToStateObj): Registers a state as part of the wizard, so the wizard can use it. The 'referenceToStateObj' should be a reference to an instantiated lonwizstate object. This is normally called at the end of the lonwizard::state constructor, so you should not normally need it as a user. |
=item B<registerState>(referenceToStateObj): Registers a state as part of the wizard, so the wizard can use it. The 'referenceToStateObj' should be a reference to an instantiated lonwizstate object. This is normally called at the end of the lonwizard::state constructor, so you should not normally need it as a user. |
Line 195 sub changeState {
|
Line 238 sub changeState {
|
|
|
=pod |
=pod |
|
|
=item B<display>(): This is the main method that the handler using the wizard calls. |
=item B<display>(): This is the main method that the handler using the wizard calls. It must always be called, and called last, because it takes care of closing a hash that needs to be closed. |
|
sxsd |
=cut |
=cut |
|
|
# Done in four phases |
# Done in four phases |
Line 291 HEADER
|
Line 334 HEADER
|
</html> |
</html> |
FOOTER |
FOOTER |
|
|
|
# Handle writing out the vars to the file |
|
my $file = Apache::File->new('>'.$self->{FILENAME}); |
|
print $file $self->_varsInFile(); |
|
|
return $result; |
return $result; |
} |
} |
|
|
Line 324 sub getVars {
|
Line 371 sub getVars {
|
|
|
=cut |
=cut |
|
|
# This may look trivial, but it's here as a hook for possible later processing |
|
sub setVar { |
sub setVar { |
my $self = shift; |
my $self = shift; |
my $key = shift; |
my $key = shift; |
my $val = shift; |
my $val = shift; |
$self->{VARS}{$key} = $val; |
$self->{VARS}->{$key} = $val; |
} |
} |
|
|
=pod |
=pod |
Line 341 sub setVar {
|
Line 387 sub setVar {
|
sub queryStringVars { |
sub queryStringVars { |
my $self = shift; |
my $self = shift; |
|
|
|
my @storedVars = ('STATE', 'TOKEN', 'RETURN_PAGE'); |
my @queryString = (); |
my @queryString = (); |
|
|
for my $varname (keys %{$self->{VARS}}) { |
push @queryString, 'TOKEN=' . |
push @queryString, Apache::lonnet::escape($varname) . "=" . |
Apache::lonnet::escape($self->{TOKEN}); |
Apache::lonnet::escape($self->{VARS}{$varname}); |
|
} |
|
push @queryString, 'CURRENT_STATE=' . Apache::lonnet::escape($self->{STATE}); |
push @queryString, 'CURRENT_STATE=' . Apache::lonnet::escape($self->{STATE}); |
push @queryString, 'RETURN_PAGE=' . Apache::lonnet::escape($self->{RETURN_PAGE}); |
push @queryString, 'RETURN_PAGE=' . Apache::lonnet::escape($self->{RETURN_PAGE}); |
|
|
Line 359 sub queryStringVars {
|
Line 404 sub queryStringVars {
|
|
|
=cut |
=cut |
|
|
|
|
# A temp function for debugging |
# A temp function for debugging |
sub handler { |
sub handler { |
my $r = shift; |
my $r = shift; |
Line 806 sub render {
|
Line 850 sub render {
|
$result .= "<tr>\n<td width='20'> </td>\n<td>"; |
$result .= "<tr>\n<td width='20'> </td>\n<td>"; |
$result .= "<td valign=\"top\"><input type=\"radio\" name=\"$var.forminput\""; |
$result .= "<td valign=\"top\"><input type=\"radio\" name=\"$var.forminput\""; |
if (!$checked) { |
if (!$checked) { |
$result .= " selected"; |
$result .= " checked"; |
$checked = 1; |
$checked = 1; |
} |
} |
$result .= " value=\"$value\"></td>\n<td>$text</td>\n</tr>\n\n"; |
$result .= " value=\"$value\"></td>\n<td>$text</td>\n</tr>\n\n"; |
Line 899 sub render {
|
Line 943 sub render {
|
my $date; |
my $date; |
|
|
# Default date: Now |
# Default date: Now |
$date = localtime($wizvars->{$var}); |
$date = localtime(); |
|
$date->min = 0; |
|
|
if (defined $self->{ERROR_MSG}) { |
if (defined $self->{ERROR_MSG}) { |
$result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />'; |
$result .= '<font color="#FF0000">' . $self->{ERROR_MSG} . '</font><br /><br />'; |
Line 1098 sub render {
|
Line 1143 sub render {
|
$level = 9; # general course, see lonparmset.pm perldoc |
$level = 9; # general course, see lonparmset.pm perldoc |
$affectedResourceId = "0.0"; |
$affectedResourceId = "0.0"; |
} elsif ($wizvars->{GRANULARITY} eq 'map') { |
} elsif ($wizvars->{GRANULARITY} eq 'map') { |
my $navmap = Apache::lonnavmaps::navmap->new( |
my $navmap = Apache::lonnavmaps::navmap->new(Apache->request, |
$ENV{"request.course.fn"}.".db", |
$ENV{"request.course.fn"}.".db", |
$ENV{"request.course.fn"}."_parms.db", 0, 0); |
$ENV{"request.course.fn"}."_parms.db", 0, 0); |
my $res = $navmap->getById($wizvars->{RESOURCE_ID}); |
my $res = $navmap->getById($wizvars->{RESOURCE_ID}); |
Line 1108 sub render {
|
Line 1153 sub render {
|
$level = 8; |
$level = 8; |
$affectedResourceId = $wizvars->{RESOURCE_ID}; |
$affectedResourceId = $wizvars->{RESOURCE_ID}; |
} else { |
} else { |
my $navmap = Apache::lonnavmaps::navmap->new( |
my $navmap = Apache::lonnavmaps::navmap->new(Apache->request, |
$ENV{"request.course.fn"}.".db", |
$ENV{"request.course.fn"}.".db", |
$ENV{"request.course.fn"}."_parms.db", 0, 0); |
$ENV{"request.course.fn"}."_parms.db", 0, 0); |
my $res = $navmap->getById($wizvars->{RESOURCE_ID}); |
my $res = $navmap->getById($wizvars->{RESOURCE_ID}); |
Line 1266 sub render {
|
Line 1311 sub render {
|
# Create the composite function that renders the column on the nav map |
# Create the composite function that renders the column on the nav map |
# have to admit any language that lets me do this can't be all bad |
# have to admit any language that lets me do this can't be all bad |
# - Jeremy (Pythonista) ;-) |
# - Jeremy (Pythonista) ;-) |
|
my $checked = 0; |
my $renderColFunc = sub { |
my $renderColFunc = sub { |
my ($resource, $part, $params) = @_; |
my ($resource, $part, $params) = @_; |
|
|
Line 1273 sub render {
|
Line 1319 sub render {
|
return '<td> </td>'; |
return '<td> </td>'; |
} else { |
} else { |
my $col = "<td><input type='radio' name='${var}.forminput' "; |
my $col = "<td><input type='radio' name='${var}.forminput' "; |
if ($vals->{$resource->{ID}}) { |
if (!$checked) { |
$col .= "checked "; |
$col .= "checked "; |
|
$checked = 1; |
} |
} |
$col .= "value='" . $resource->{ID} . "' /></td>"; |
$col .= "value='" . $resource->symb() . "' /></td>"; |
return $col; |
return $col; |
} |
} |
}; |
}; |