package HTML::Transmorgify::FormDefault; use strict; use warnings; use Digest::MD5 qw(md5_hex); use HTML::Transmorgify qw(dangling %variables $query_param $debug queue_intercept queue_capture run $debug rbuf postbuf capture_compile); use URI::Escape; use HTML::Entities; use Scalar::Util qw(refaddr blessed); use YAML; require Exporter; our @ISA = qw(HTML::Transmorgify Exporter); our @EXPORT = qw(validate_form_submission); my %tags; my $tag_package = { tag_package => __PACKAGE__ }; our @rtmp; our $default_enable = 1; sub add_tags { my ($self, $tobj) = @_; $self->intercept_shared($tobj, __PACKAGE__, 65, %tags); } our @btmp; sub return_true { 1 } $tags{input} = undef; $tags{button} = undef; $tags{textarea} = undef; $tags{"/textarea"} = undef; $tags{select} = undef; $tags{"/select"} = undef; $tags{option} = undef; $tags{"/option"} = undef; $tags{"/form"} = \&dangling; $tags{form} = \&form_tag; sub qpval { my ($name, $value) = @_; return '' unless $query_param->{$name}; if (ref $query_param->{$name}) { if (defined $value) { return grep { $_ eq $value } @{$query_param->{$name}}; } else { return ''; } } else { if (defined $value) { return $query_param->{$name} eq $value; } else { return $query_param->{$name}; } } } sub compile_time_gate { my ($attr) = @_; unless ($attr->boolean('auto_default', undef, 1, raw => 1)) { print STDERR "GATE: Bailing early from $attr\n" if $debug; return 0; } if ($attr->boolean('readonly', undef, 0, raw => 1)) { print STDERR "GATE: Bailing early from $attr is read-only\n" if $debug; return 0; } $attr->hide('no_auto_defaults'); $attr->hide('readonly'); print STDERR "GATE: compile time okay for $attr\n" if $debug; return 1; } sub run_time_gate { my ($attr) = @_; unless ($query_param && %$query_param) { print STDERR "GATE: No query parameters\n" if $debug; return 0; } unless ($attr->boolean('auto_default', undef, 1)) { print STDERR "GATE: Bailing late from $attr\n" if $debug; return 0; } if ($attr->boolean('readonly', undef, 0)) { print STDERR "GATE: Bailing late from $attr is read-only\n" if $debug; return 0; } my $name = $attr->get('name') || $attr->get('id'); unless ($name) { print STDERR "GATE: No name or id for $attr\n" if $debug; return 0; } unless (exists $query_param->{$name}) { print STDERR "GATE: No user input for $attr\n" if $debug; return 0; } print STDERR "GATE: run time time okay for $attr\n" if $debug; return $name; }; sub form_tag { my ($fattr, $closed) = @_; die if $closed; my $default; return unless compile_time_gate($fattr); my $text_cb = sub { my ($attr, $closed) = @_; rbuf(sub { return 1 unless run_time_gate($attr); $attr->set(value => qpval($attr->get('name'))); }); }; my $vals = {}; my $radio_cb = sub { my ($attr, $closed) = @_; rbuf(sub { my $name = run_time_gate($attr); return 1 unless $name; my $value = $attr->get('value'); if (qpval($name, $value)) { $attr->set(checked => undef); } else { $attr->set(checked => 0); $attr->hide('checked'); } return 1; }); }; my $nothing = sub { 1 }; my $input_cb = sub { my ($attr, $closed) = @_; return 1 unless compile_time_gate($attr); my %handlers = ( text => $text_cb, password => $text_cb, radio => $radio_cb, checkbox => $radio_cb, submit => $nothing, hidden => $nothing, reset => $nothing, file => $nothing, # if we have some sort of caching, cache it! image => $nothing, button => $nothing, ); my $type = lc($attr->get('type')); die unless $handlers{$type}; $handlers{$type}->($attr, $closed); $attr->eval_at_runtime(1); return 1; }; my $textarea_cb = sub { my ($attr, $closed) = @_; return 1 unless compile_time_gate($attr); $attr->eval_at_runtime(1); my ($b, $deferred) = capture_compile('textarea', $attr, undef, %HTML::Transmorgify::queued_intercepts); my $b2 = []; { local($HTML::Transmorgify::rbuf) = $b2; for my $ccb (@HTML::Transmorgify::queued_captures) { $ccb->($b); } } postbuf(sub { my $name = run_time_gate($attr); if ($name) { $HTML::Transmorgify::result->[0] .= encode_entities(qpval($name)) . ""; } else { run($b); run($b2); $deferred->doit(); $HTML::Transmorgify::result->[0] .= ""; } }); return 1; }; my $select_cb = sub { my ($attr, $closed) = @_; return 1 unless compile_time_gate($attr); $attr->eval_at_runtime(1); my $option_cb = sub { my ($oattr, $closed) = @_; return 1 unless compile_time_gate($attr); $oattr->eval_at_runtime(1); my $get_value; if (defined $oattr->raw('value')) { $get_value = sub { $oattr->get('value'); }; } else { my $b; queue_capture(sub { $b = shift; }); $get_value = sub { local(@btmp) = (''); run($b, \@btmp); return $btmp[0]; }; } rbuf(sub { my $name = run_time_gate($attr); return 1 unless $name; my $value = $get_value->(); if (qpval($name, $value)) { $oattr->set(selected => undef); } else { $oattr->set(selected => 0); $oattr->hide('selected'); } }); }; queue_intercept(__PACKAGE__, option => $option_cb, "/select", => sub { 1 }, ); }; queue_intercept(__PACKAGE__, input => $input_cb, textarea => $textarea_cb, select => $select_cb, '/form' => \&return_true, ); return 1; }; __END__