Apache-Wyrd
view release on metacpan or search on metacpan
Wyrd/Interfaces/Setter.pm view on Meta::CPAN
=item (scalar) C<_quote_set> ([hashref], [scalar])
More SQL-ish, but not CGI-ish. A blank hashref is used in place of the
CGI environment when passed no parameters. Placemarkers are replaced
with the quote function of DBI via the Wyrd->dbl->quote function so as
to be used in SQL queries.
=cut
sub _quote_set {
my ($self, $hash, $temp) = @_;
#if a target ($temp) is provided, use it instead of the data
$temp = $self->{'_data'} unless ($temp);
$hash = {} unless (ref($hash) eq 'HASH');
#first do conditionals
$temp = $self->_regexp_conditionals($hash, $temp);
#then do quotations, altering a copy, not the original
my %hash = %$hash;
foreach my $i (keys(%hash)) {
$hash{$i}=$self->dbl->dbh->quote($hash{$i});
$hash{$i}='NULL' if ($hash{$i} eq q(''));
}
#then do replacements
foreach my $i (sort {length($b) <=> length($a)} keys(%hash)) {
next unless ($i);#this is to prevent strange tied hashes from creating iloops
$self->_verbose("temp is $temp, i is $i and hash is $$hash{$i}");
$temp =~ s/\$:$i/$hash{$i}/gi;
}
return $temp;
}
=item (scalar) C<_cgi_quote_set> ([scalar])
same as C<_quote_set>, but with the CGI environment option forced and no
interpreted hash option.
=cut
sub _cgi_quote_set {
my ($self, $temp) = @_;
#if a target ($temp) is provided, use it instead of the data
$temp = $self->{'_data'} unless ($temp);
#first get a clean hash -- no point in doing conditionals if undef is changed to NULL
my $hash = $self->_cgi_hash($temp);
#then do conditionals
$temp = $self->_regexp_conditionals($hash, $temp);
#then do quotations
$hash = $self->_cgi_hash($temp, 'quoted');
#then do replacements
foreach my $i (sort {length($b) <=> length($a)} keys(%$hash)) {
next unless ($i);#this is to prevent strange tied hashes from creating iloops
$self->_verbose("temp is $temp, i is $i and hash is $$hash{$i}");
$temp =~ s/\$:$i/$$hash{$i}/gi;
}
return $temp;
}
=pod
=item (scalar) C<_escape_set> ([hashref], [scalar])
More HTML-form-ish but not CGI-ish. A blank hashref is used in place of
the CGI environment when passed no parameters. Values are HTML escaped
so they can be used within <input type="text"> tags in HTML.
=cut
sub _escape_set {
my ($self, $hash, $temp) = @_;
#if a target ($temp) is provided, use it instead of the data
$temp = $self->{'_data'} unless ($temp);
$hash = {} unless (ref($hash) eq 'HASH');
#first do conditionals
$temp = $self->_regexp_conditionals($hash, $temp);
#then do quotations, altering a copy, not the original
my %hash = %$hash;
foreach my $i (keys(%hash)) {
$hash{$i}=Apache::Util::escape_html($hash{$i});
}
#then do replacements
foreach my $i (sort {length($b) <=> length($a)} keys(%hash)) {
next unless ($i);#this is to prevent strange tied hashes from creating iloops
$self->_verbose("temp is $temp, i is $i and hash is $$hash{$i}");
$temp =~ s/\$:$i/$hash{$i}/gi;
}
return $temp;
}
=pod
=item (scalar) C<_cgi_escape_set> ([scalar])
same as C<_escape_set>, but with the CGI environment option forced and
no interpreted hash option.
=cut
sub _cgi_escape_set {
my ($self, $temp) = @_;
#if a target ($temp) is provided, use it instead of the data
$temp = $self->{'_data'} unless ($temp);
#first get a clean hash -- no point in doing conditionals if undef is changed to NULL
my $hash = $self->_cgi_hash($temp);
#then do conditionals
$temp = $self->_regexp_conditionals($hash, $temp);
#then do quotations
$hash = $self->_cgi_hash($temp, 'escaped');
#then do replacements
$temp = $self->_setter_replacements($hash, $temp);
return $temp;
}
=pod
=item (scalar) C<_regexp_conditionals> (hashref, scalar)
internal method for performing conditional interpretation.
=cut
sub _regexp_conditionals {
my ($self, $hash, $string) = @_;
my $changed = 0; #toggle: if there is nothing left to change, it's time to return
my $mode = 's'; #(s)eek a conditional (c)onfirm that it is a conditional, com(p)lete the expression
my $state = '?'; #keep the argument or discard it
my $buf = ''; #buffer for temp storage of the conditional
my $out = ''; #buffer for the completed expression
my $depth = 0; #how many layers of conditionals are we at?
do {
$changed = 0;
foreach my $char (unpack('U*', $string)) {
$char = chr($char);#returns unicode
if ($mode eq 's') {#always begin by seeking
if ($char eq '?' or $char eq '!') {
$buf = '';
$buf .= $char;
$mode = 'c';
$state = $char;
} else {
$out .= $char;
}
}
elsif ($mode eq 'c') {
if ((length($buf) > 3) and ($buf !~ /^[?!]:[_a-zA-Z][_a-zA-Z0-9]+$/)) {
#not a valid identifier, move on...
$out .= $buf . $char;
$mode = 's';
}
if ($char eq '{') {
my $identifier = substr($buf, 2);
if (exists($$hash{$identifier})) {
if (not(defined($$hash{$identifier}))) {
$state =~ tr/?!/!?/;
}
$buf = '';
$mode = 'p';
$depth = 1;
$changed = 1;
} else {
$out .= $buf . $char;
$mode = 's';
}
} else {
$buf .= $char;
}
}
elsif ($mode eq 'p') {
Wyrd/Interfaces/Setter.pm view on Meta::CPAN
}
=pod
=item (scalar) C<_setter_replacements> (hashref, scalar)
internal method for performing value replacements.
=cut
sub _setter_replacements {
my ($self, $hash, $temp) = @_;
foreach my $i (sort {length($b) <=> length($a)} keys(%$hash)) {
#sorted so that the longest go first, avoiding problems where one variable (key) name is a
#substring of another
next unless ($i);#this is to prevent strange tied hashes from creating iloops
$self->_verbose("temp is '$temp', i is '$i' and value is '$$hash{$i}'");
$temp =~ s/\$:\Q$i\E/$$hash{$i}/gi;
}
return $temp;
}
=pod
=item (scalar) C<_setter_defaults> (hashref, scalar)
internal method for setting default template to BASECLASS::_data and default
parameters to null hash.
=cut
sub _setter_defaults {
my ($self, $hash, $temp) = @_;
#if a target ($temp) is provided, use it instead of the data
$temp ||= $self->{'_data'};
$hash = $self->_cgi_hash($temp) unless (ref($hash) eq 'HASH');
return $hash, $temp;
}
=pod
=item (scalar) C<_cgi_hash> (hashref, scalar)
internal method for interpreting the CGI environment into the template
data hashref.
=cut
sub _cgi_hash {
my ($self, $temp, $modifier) = @_;
my $hash = {};
my @params = ();
unless ($temp) {
#give up and use CGIs params
@params = $self->dbl->param;
} else {
#guess at the params from the template
@params = ($temp =~ m/[\$\?\!]\:([a-zA-Z_][a-zA-Z0-9_]+)/g);
}
foreach my $param (@params) {
if ($modifier eq 'escaped') {
$hash->{$param} = Apache::Util::escape_html(scalar($self->dbl->param($param)));
} elsif ($modifier eq 'quoted') {
#scalar is used because of some funny business in dbh -- worth investigating?
$hash->{$param} = $self->dbl->dbh->quote(scalar($self->dbl->param($param)));
} else {
$hash->{$param} = $self->dbl->param($param);
}
$self->_verbose("$param = $$hash{$param}");
}
$self->_debug("Found params ->" . join ', ', @params);
return $hash
}
=pod
=item (scalar) C<_attribute_template> (array)
Shortcut method for quickly creating templates of all attributes in a
wyrd, given an array of attribute names.
=cut
sub _attribute_template {
my ($self, @attributes) = @_;
my $string = join ('', map {qq(\?\:$_\{ $_="\$\:$_\"})} @attributes);
return $string;
}
=pod
=item (scalar) C<_template_hash> (string, [hashref])
Shortcut method for quickly creating a hash from a template. If the
template is not provided, the object's _data attribute is used. If a
hashref is supplied as the second value, values for the returned hashref are
based on that. Otherwise, the calling object itself provides the values. By
default, template items that are not defined by the attributes of the object
or provided hashref are ignored.
=cut
sub _template_hash {
my ($self, $template, $hash) = @_;
$template ||= $self->{'_data'};
$hash ||= $self;
my @keys = $template =~ /[\$\!\?]:([_a-zA-Z][_a-zA-Z0-9]+)/g;
my %out_hash = ();
foreach my $key (@keys) {
if (eval{exists($hash->{$key})}) {
$out_hash{$key} = $hash->{$key};
}
}
return \%out_hash;
}
=pod
=back
=head1 BUGS/CAVEATS/RESERVED METHODS
=head2 Interpolation Bug
"$:" is a variable in perl, so be sure to escape or single-quote your
in-code templates. If you start seeing B<-variablename> in your pages,
you'll know why.
=head2 Defined Null Conditional Bug
There's some un-perlish behavior in the setting of conditionals. Conditional
statements are set (?) or unset (!) depending on whether the item is defined,
not whether it is true. An eq operator, for example, returns '' (the null
string) when the arguments are not equivalent strings, so a template with a
conditional that should be false, and therefore unset, is actually considered
true, since the result is defined and exists. For example
$result = $self->_set({'a' => 'a' eq 'b'}, '?:a{wrong}');
returns "wrong", not ''. To prevent this, it should be written:
$result = $self->_set({'a' => ('a' eq 'b') || undef}, '?:a{wrong}');
=head1 AUTHOR
Barry King E<lt>wyrd@nospam.wyrdwright.comE<gt>
=head1 SEE ALSO
=over
=item Apache::Wyrd
General-purpose HTML-embeddable perl object
=back
=head1 LICENSE
Copyright 2002-2007 Wyrdwright, Inc. and licensed under the GNU GPL.
See LICENSE under the documentation for C<Apache::Wyrd>.
=cut
1;
( run in 0.491 second using v1.01-cache-2.11-cpan-39bf76dae61 )