Apache-Wyrd
view release on metacpan or search on metacpan
Wyrd/Form.pm view on Meta::CPAN
=item _variables
hashref of all input/form values, loaded first from the storage
variable, then from the CGI environment.
=item _globals
hashref of private variables for the given form. By default, the form
will have any matching C<Apache::Wyrd::Interfaces::Setter>-style
placemarkers set to these values.
=item _input_index & _input
Inputs are stored in arrayref to support multiple inputs of the same
variable. Hence, unique names need to be used in an index to indicate a
given member of the arrayref _input.
=item _errortag_index & _errortag
Errortags are conditionally-varying elements of the form usually
indicating errors.
=item _view_index & _view
Views are set-style templates used for showing the current state of the
form on the page.
=item _errors
flags for particular error conditions, stored in an arrayref. This array
is checked against registered triggers for errortags. Errors are
defined as arbitrary strings signifying an error event such as "preview"
or "no full name". Note that as soon as an error is inserted, the form
will not advance to the next template until the error is corrected
(unless, of course, the ignore_errors flag is set).
=item _error_messages
arrayref of strings to be displayed to the user explaining what error
conditions have occurred and how to fix them.
=item _current_identifier
which of the multiple forms is the current focus. Will normally change
during any given run of the Form object as one form is approved and the
next is loaded.
=item _form & _form_index
Forms are individual "states" that the form is in, usually signifying
the process of filling out each step of a multiple-page form.
=item _action_index
Hashref holding the action to put into the form tag when using that form
as the current form.
=item _next_form, _current_form, & _last_form
self explanatory place markers used in deciding where in the sequence of
forms the user is.
=back
=head2 PERL METHODS
I<(format: (returns) name (arguments after self))>
=over
=item (void) C<drop_var> (scalar)
Remove a parameter from the tracked state.
=cut
#Public methods
sub drop_var {
#accessor for special cases
my ($self, $var) = @_;
delete($self->{'_variables'}->{$var->name});
}
=item (void) C<insert_error> (scalar)
Add a "trigger" to the error register. In the most usual case where the
error indicates illegal input, this is the parameter name, but may
represent a more complex error condition, such as a scheduling conflict
or unbalanced set of figures.
=cut
sub insert_error {
my ($self, $error) = @_;
$self->{'_errors'} = [@{$self->{'_errors'}}, $error];
}
=item (void) C<insert_error_messages> (array[ref])
Insert an error message into the error message queue. The queue is
processed by the C<_dump_errors> method.
=cut
sub insert_error_messages {
my ($self, @error_messages) = @_;
@error_messages = @{$error_messages[0]} if (ref($error_messages[0]) eq 'ARRAY');
$self->{'_error_messages'} = [@{$self->{'_error_messages'}}, @error_messages];
}
=item (void) C<register_form> (Apache::Wyrd::Form::Template)
Add a form Template to this form object. Called by
C<Apache::Wyrd::Form::Template> to build the form sequence. Also notes
the action attribute of the template, which can override the default or
given action of the Form.
=cut
Wyrd/Form.pm view on Meta::CPAN
$header .= $self->{'_stored_data'} if ($self->{'_stored_data'});
return "<form name=\"$name\" action=\"$action\" method=\"$method\"$extra_attributes>\n" . $header . $form . "\n</form>";
}
sub _current_marker {
my $self = shift;
my $form = $self->{'_current_form'};
return undef unless ($form);
return '<input type="hidden" name="_current_form" value="' . $form . '">' . "\n";
}
sub register_child {
my ($self) = @_;
$self->_raise_exception($self->_class_name . ' has separate child registers. Do not call register_child.');
}
sub _set_children {
my ($self) = @_;
$self->_raise_exception($self->_class_name . ' has separate child registers. Do not call set_children.');
}
=pod
=back
=head1 BUGS/CAVEATS/RESERVED METHODS
Reserves the _setup, the _format_output, AND the _generate_output method. Subclassing is done via the other hooks, above.
=cut
#standard Wyrd methods
sub _setup {
my ($self) = @_;
$self->{'_globals'} = {error_block => undef};
$self->{'_variables'} = {};
$self->{'_input_index'} = {};
$self->{'_input'} = [];
$self->{'_errortag_index'} = {};
$self->{'_errortag'} = [];
$self->{'_view_index'} = {};
$self->{'_view'} = [];
$self->{'_errors'} = [];
$self->{'_triggers'} = {};
$self->{'_error_messages'} = [];
$self->{'_current_identifier'} = 0;
$self->{'_form'} = {};
$self->{'_form_index'} = [];
$self->{'_action_index'} = {};
#use CGI to attempt to set current and next forms. Forms will set themselves in
#the first pass of _process_self. NB- subforms can't outclass this.
$self->{'_next_form'} = $self->dbl->param('_next_form');
$self->{'_current_form'} = $self->dbl->param('_current_form');
$self->{'_last_form'} = undef;
$self->_interpret_action;
return;
}
sub _format_output {
my ($self) = @_;
#Decide on current and next forms or die trying.
$self->_raise_exception("One or more FormTemplate objects are required for each form.")
unless ($self->{'_current_form'});#forms changed this value registering
if (not(grep {$self->{'_current_form'} eq $_} @{$self->{'_form_index'}})) {#if we've come here from another form
$self->{'_next_form'} = $self->{'_form_index'}->[0];
$self->{'_current_form'} = $self->{'_form_index'}->[0];
}
unless ($self->{'_next_form'}) {#give cgi a chance to override
my $last_form = undef;
foreach my $form (@{$self->{'_form_index'}}) {#otherwise find next in sequence
$last_form = $self->{'_next_form'};
$self->{'_next_form'} = $form;
last if ($last_form eq $self->{'_current_form'});
}
}
$self->_raise_exception("Could not determine what the next form should be. Use the 'nextform' attribute to name it.")
unless ($self->{'_next_form'});#catch malformed forms
$self->_debug('Forms found: ' . $self->{'_current_form'} . " -> " . $self->{'_next_form'});
#Use the current form as self and process self again.
$self->_reload_form;
#Do any preprocessing on widgets
$self->_activate_widgets;
#Form::Preload object preloads _variables
$self->_preload_inputs if (($self->_flags->preload) and not($self->_submitted));
#everything up to this point is all that's needed for a new form.
return undef unless ($self->_submitted);
#cover reset events
return undef if ($self->_check_reset);
#Start processing the data from CGI.
$self->_unpack_data;#get storage
#inputs should now be registered (_reload above), go through them for errors.
$self->_check_inputs;
#Check form-wide conditions
$self->_check_form;
#Check global conditions
$self->_check_globals;
#error -> same form, set errorconditions
my $error = $self->_check_errors;
#no error -> next form. ignore_errors flag overrides error checking and forces next form.
if ((not($error) or $self->_flags->ignore_errors)) {
$self->{'_current_form'} = $self->{'_next_form'};
#last form was decided by the last form to be parsed in the first pass of
#_process_self.
if ($self->{'_current_form'} eq $self->{'_last_form'}){
$self->_submit_data;
$self->_pack_data if ($self->_flags->continue);
} else {
$self->_pack_data;
}
$self->_reload_form;
} else {
$self->_dispatch_errors;
$self->_pack_data;
$self->_fire_triggers;
}
return;
}
sub _generate_output {
my ($self) = @_;
my (%item) = %{$self->{'_globals'}};
#fill in placemarkers
foreach my $child (keys(%{$self->{'_input_index'}})) {
$self->_verbose("processing input $child :" . $self->{'_input_index'}->{$child} . ' : ' . $self->{'_input'}->[$self->{'_input_index'}->{$child}]->name);
my $input = $self->{'_input'}->[$self->{'_input_index'}->{$child}];
my $output = $input->final_output;
$item{$child} = $output;
}
foreach my $child (keys(%{$self->{'_errortag_index'}})) {
$self->_verbose("processing errortag $child :" . $self->{'_errortag_index'}->{$child} . ' : ' . $self->{'_errortag'}->[$self->{'_errortag_index'}->{$child}]->trigger);
my $errtag = $self->{'_errortag'}->[$self->{'_errortag_index'}->{$child}];
my $output = $errtag->final_output;
$self->_debug($output . ' for ' . $child);
$item{$child} = $output;
}
foreach my $child (keys(%{$self->{'_view_index'}})) {
$self->_verbose("processing view $child");
my $view = $self->{'_view'}->[$self->{'_view_index'}->{$child}];
my $output = $view->final_output($self->{_variables});
$item{$child} = $output;
}
my $out = $self->{_data};
$out = $self->_text_set(\%item, $out);
$out = $self->_wrap_form($out);
#finally, filter out any Input character sequences
$out =~ s/\x00//g;
return $out;
}
=pod
=head1 AUTHOR
Barry King E<lt>wyrd@nospam.wyrdwright.comE<gt>
=head1 SEE ALSO
=over
( run in 1.373 second using v1.01-cache-2.11-cpan-98e64b0badf )