###############################################################################
#case-insensitive.pm
#Last Change: 2009-02-09
#Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch
#Version 0.4
####################
#This file is an addon to the Dotiac::DTL project.
#http://search.cpan.org/perldoc?Dotiac::DTL
#
#case-insensitive.pm is published under the terms of the MIT license, which
#basically means "Do with it whatever you want". For more information, see the
#license.txt file that should be enclosed with this distribution. A copy of
#the license is (at the time of writing) also available at
#http://www.opensource.org/licenses/mit-license.php .
###############################################################################
package Dotiac::DTL::Addon::case_insensitive;
use strict;
use warnings;
#If it is not already loaded.
require Dotiac::DTL::Core;
our $VERSION=0.4;
my $old;
our %keymap=();
sub import {
no warnings qw/redefine/;
$old = \&Dotiac::DTL::devar_var;
*Dotiac::DTL::devar_var=\&devar_var;
}
sub unimport {
no warnings qw/redefine/;
*Dotiac::DTL::devar_var = $old;
}
sub devar_var {
my $name=shift;
my $n=$name;
return Dotiac::DTL::Value->safe(undef) unless defined $name;
my $lcn = lc($name);
my $param=shift;
my $f=substr $name,0,1;
my $l=substr $name,-1,1;
my $escape=shift;
return Dotiac::DTL::Value->safe(substr $name,1,-1) if $f eq "'" and $l eq "'" or $f eq '"' and $l eq '"';
return Dotiac::DTL::Value->safe(Dotiac::DTL::descap(substr $name,1,-1)) if $f eq "`" and $l eq "`";
if ($lcn eq "block.super" and $param->{"block.super"}) {
return Dotiac::DTL::Value->safe($param->{"block.super"}->string($param,@_)) if Scalar::Util::blessed($param->{"block.super"});
return Dotiac::DTL::Value->safe($param->{"block.super"}->($param,@_)) if ref $param->{"block.super"} eq "CODE";
}
return Dotiac::DTL::Value->new($param->{$name},!$escape) if exists $param->{$name};
return Dotiac::DTL::Value->new($param->{$Dotiac::DTL::Addon::case_insensitive::keymap{$lcn}},!$escape) if defined $Dotiac::DTL::Addon::case_insensitive::keymap{$lcn} and exists($param->{$Dotiac::DTL::Addon::case_insensitive::keymap{$lcn}});
foreach my $k (keys %{$param}) {
if (lc($k) eq $lcn) {
$Dotiac::DTL::Addon::case_insensitive::keymap{$lcn}=$k;
return Dotiac::DTL::Value->new($param->{$k},!$escape);
}
}
my @tree=split/\./,$name;
$name=shift @tree;
$lcn = lc($name);
if (exists $param->{$name}) {
$param=$param->{$name};
}
elsif (defined $Dotiac::DTL::Addon::case_insensitive::keymap{$lcn} and exists $param->{$Dotiac::DTL::Addon::case_insensitive::keymap{$lcn}}) {
$param=$param->{$Dotiac::DTL::Addon::case_insensitive::keymap{$lcn}};
}
else {
my $found=0;
foreach my $k (keys %$param) {
if (lc($k) eq $lcn) {
$Dotiac::DTL::Addon::case_insensitive::keymap{$lcn}=$k;
$found=1;
$param=$param->{$k};
last;
}
}
unless ($found) {
return Dotiac::DTL::Value->safe($n) if $n!~/[^\d\-\.\,\e]/;
foreach my $k (keys %Dotiac::DTL::cycle) {
if (lc($k) eq $lcn and $Dotiac::DTL::cycle{$k}->[1]) {
return Dotiac::DTL::Value->safe("") if $Dotiac::DTL::included{"cycle_$k"}++;
my $r=devar_raw($Dotiac::DTL::cycle{$k}->[2]->[$Dotiac::DTL::cycle{$k}->[0]-1 % $Dotiac::DTL::cycle{$k}->[1]],$param,$escape,@_);
$Dotiac::DTL::included{"cycle_$k"}=0;
return $r;
}
}
return Dotiac::DTL::Value->safe(undef) ;
}
}
while (defined(my $name = shift @tree)) {
$lcn = lc($name);
my $r = Scalar::Util::reftype($param);
if ($r) {
if ($r eq "HASH") {
if (not exists $param->{$name}) {
my $found=0;
foreach my $k (keys %{$param}) {
if (lc($k) eq $lcn) {
$found=1;
$param=$param->{$k};
last;
}
}
next if $found;
return Dotiac::DTL::Value->safe(undef) unless Scalar::Util::blessed($param);
}
else {
$param=$param->{$name};
next;
}
}
elsif ($r eq "ARRAY") {
if ($name=~m/\D/) {
return Dotiac::DTL::Value->safe(undef) unless Scalar::Util::blessed($param);
}
else {
if (not exists $param->[$name]) {
return Dotiac::DTL::Value->safe(undef) unless Scalar::Util::blessed($param);
}
else {
$param=$param->[$name];
next;
}
}
}
}
if (Scalar::Util::blessed($param)) {
return Dotiac::DTL::Value->safe(undef) unless $Dotiac::DTL::ALLOW_METHOD_CALLS;
my $found=0;
foreach my $k ($param->dotiac_get_all_methods()) {
if (lc($k) eq $lcn) {
$found=1;
$param=$param->$k();
last;
}
}
if (not $found and $param->can("__getitem__")) {
my $x;
eval {
$x=$param->__getitem__($name);
1;
} or return Dotiac::DTL::Value->safe(undef);
if (defined $x) {
$param=$x;
next;
}
}
return Dotiac::DTL::Value->safe(undef) unless $found;
next;
}
return Dotiac::DTL::Value->safe($n) if $n!~/[^\d\-\.\,\e]/;
return Dotiac::DTL::Value->safe(undef);
}
return Dotiac::DTL::Value->new($param,!$escape);
}
package UNIVERSAL;
use strict;
sub dotiac_get_all_methods {
my ($class, undef) = @_;
$class = ref $class || $class;
my %classes_seen;
my %methods;
my @class = ($class);
no strict 'refs';
while ($class = shift @class) {
next if $classes_seen{$class}++;
unshift @class, @{"${class}::ISA"};
# Based on methods_via() in perl5db.pl
for my $method (grep { # not /^[(_]/ and # Has to be removed, sadly
defined &{${"${class}::"}{$_}}}
keys %{"${class}::"}) {
$methods{$method} = wantarray ? undef : $class->can($method);
}
}
wantarray ? keys %methods : \%methods;
}
1;
__END__
=head1 NAME
Dotiac::DTL::Addon::case_insensitive: Ignore case of Dotiac variables
=head1 SYNOPSIS
Load from a Dotiac::DTL-template:
{% load case-insensitive %}
Load in Perl file for all templates:
use Dotiac::DTL::Addon::case_insensitive; #Note the underline instead of the minus
=head1 INSTALLATION
via CPAN:
perl -MCPAN -e "install Dotiac::DTL::Addon::case_insensitive"
or get it from L<https://sourceforge.net/project/showfiles.php?group_id=249411&package_id=306751>, extract it and then run in the extracted folder:
perl Makefile.PL
make test
make install
=head1 DESCRIPTION
This will make variable lookups become case-insensitive.
{{ Data }} == {{ DAtA }} == {{ DaTa }} == ...
{{ var.Foo }} == {{ var.foo }} == {{ var.FOO }} == ...
L<Filter and tag names stay case sensitive>.
=head1 INTERNALS
=head2 devar_var
This function of L<Dotiac::DTL::Core> will be overwritten.
=head2 dotiac_get_all_methods
Addon to UNIVERSAL, which gets all methods, stolen from the perl 6 RFC 335 (L<http://dev.perl.org/perl6/rfc/335.html>);
=head1 BUGS
This will make Dotiac slower.
Please report any bugs or feature requests to L<https://sourceforge.net/tracker2/?group_id=249411&atid=1126445>
=head1 SEE ALSO
L<Dotiac::DTL>, L<Dotiac::DTL::Addon>, L<http://www.dotiac.com>, L<http://www.djangoproject.com>
=head1 AUTHOR
Marc-Sebastian Lucksch
perl@marc-s.de
=cut