File Coverage

blib/lib/NTS/Template.pm
Criterion Covered Total %
statement 124 145 85.5
branch 73 98 74.4
condition 9 26 34.6
subroutine 8 9 88.8
pod 0 7 0.0
total 214 285 75.0


line stmt bran cond sub pod time code
1             # O NTS::Template foi baseado na estrutura de programacao
2             # do Template Toolkit
3             # By: Udlei Nattis
4              
5             package NTS::Template;
6              
7 6     6   6285 use strict;
  6         13  
  6         412  
8 6     6   31 no warnings;
  6         11  
  6         18517  
9             our $VERSION = '2.1';
10              
11             my (%my,@string);
12             my $func = {
13             # Funcao printf
14             PRINTF => "my \$PRINTF = sub { my (\$x,\$y) = \@_; printf(\$x,\$y); };",
15              
16             # Funcao copiada do CGI::Util
17             ESCAPE => "my \$ESCAPE = sub {
18             my (\$toenc) = shift;
19             return undef unless defined (\$toenc);
20             \$toenc = pack(\"C*\", unpack(\"C*\", \$toenc));
21             \$toenc=~s/([^a-zA-Z0-9_.-])/uc sprintf(\"%%%02x\",ord(\$1))/eg;
22             print(\$toenc); };",
23              
24             # Funcao copiada do CGI::Util
25             UNESCAPE => "my \$UNESCAPE = sub {
26             my \$todec = shift;
27             return undef unless defined(\$todec);
28             \$todec =~ tr/+/ /;
29             \$todec =~ s/%(?:([0-9a-fA-F]{2})|u([0-9a-fA-F]{4}))/
30             defined(\$1)? chr hex(\$1) : utf8_chr(hex($\2))/ge;
31             print(\$todec); };",
32             };
33              
34             # Atalho
35             sub view_templ {
36 0     0 0 0 my($templ_dir,$templ_file,$templ_vars,$templ_extra) = @_;
37            
38 0         0 my $templ = NTS::Template->new();
39 0         0 my $r = $templ->process({ templ_dir => $templ_dir, templ_file => $templ_file, templ_vars => $templ_vars,
40             templ_extra => $templ_extra });
41              
42 0         0 return $r;
43             }
44              
45             # Cria modulo do template
46             sub new {
47 6     6 0 216 my ($class,$vars) = @_;
48 6         16 my $self = {};
49              
50 6   50     60 bless $self, ref $class || $class || "NTS::Template";
51              
52 6         43 return $self;
53             }
54              
55             # Processa arquivo
56             sub process {
57 6     6 0 16 my ($self,$vars) = @_;
58 6         13 my ($data,$file,$_r);
59            
60             # Arquivo
61 6         28 $file = $vars->{templ_dir}."/".$vars->{templ_file};
62            
63             # Executa parse
64 6         31 $data .= $self->parse($self->load($file),$vars->{templ_vars},$vars->{templ_dir});
65              
66             # Retira quebra de linha
67 6 50       43 $data =~ s/\s+|\t+/ /g if ($vars->{templ_extra}->{nospaces});
68              
69 6         22 my $my;
70 6         32 foreach (keys %my) {
71             # Variavel com conteudo
72 20 100       70 if (defined $vars->{templ_vars}->{$_}) { $my .= "my \$$_ = \$vars->{templ_vars}->{$_};\n"; }
  4 100       19  
73            
74             # Verifica se existe funcao
75 1         3 elsif ($func->{$_}) { $my .= $func->{$_}."\n"; }
76            
77             # Variavel sem conteudo
78 15         39 else { $my .= "my \$$_;\n"; };
79             }
80              
81 6         35 $data = $my.$data;
82              
83             # Saida para variavel
84 6 50       71 if (defined $vars->{templ_extra}->{oreturn}) {
    50          
    50          
85 0         0 $data =~ s/[^s]print\(|[^s]printf\(/\$_r .= sprintf(/g;
86             }
87            
88             # Verifica se deve alterar saida dos dados
89             elsif ($ENV{'MOD_PERL'}) {
90 0         0 $data =~ s/[^s]print\(/Apache->request->print(/g;
91 0         0 $data =~ s/[^s]printf\(/Apache->request->printf(/g;
92 0 0       0 Apache->request->print($data."\n") if $vars->{templ_extra}->{source};
93             }
94              
95             # Printa sources
96             elsif ($vars->{templ_extra}->{source}) {
97 6         27 print($data."\n");
98             }
99              
100             # print $data;
101             # Apache->request->print($data);
102 6         1251 $_r = eval $data;
103 6 100       36 if ($@) {
104 1 50       6 if ($ENV{'MOD_PERL'}) {
105 0         0 Apache->request->print($@);
106             } else {
107 1         3 print $@."\n";
108             }
109             }
110              
111             # Altera saida do source
112 6 50 33     69 $_r = $data."\n".$_r
113             if ($vars->{templ_extra}->{source} && $vars->{templ_extra}->{oreturn});
114              
115 6 50       23 return $_r if $vars->{templ_extra}->{oreturn};
116 6         28 return 1;
117             }
118              
119             # Abre arquivo
120             sub load {
121 6     6 0 13 my ($self,$file) = @_;
122 6         29 my ($data);
123            
124             # Printa todo o conteudo de uma vez
125 6         35 local $/;
126              
127 6 50       378 if (open(FH,"<".$file)) {
128 6         173 $data = ;
129 6         58 close(FH);
130 6         51 return $data;
131             }
132              
133             # Termina com erro
134 0         0 else { die "Can't open file $file: $!\n"; }
135             }
136              
137             sub parse {
138 6     6 0 25 my ($self,$data,$templ_vars,$templ_dir) = @_;
139            
140             # Adiciona \ em caracteres nao permitidos
141 6         13 my $p = 0;
142 6         10 my ($ndata,$i,$j);
143            
144             # Recupera condicoes
145 6         104 while ($data =~ s/(.*?)?(?:\[\%\s?(.*?)\s?\%\])//sx) {
146            
147             # String padrao
148 56         127 $ndata .= "print(\"".AddSlashes($1)."\"); ";
149              
150 56         83 my ($n,$c,$nc,$l,$tp,$fc);
151 56 100       181 $l = ($2 =~ /^#/) ? "" : $2;
152            
153             # Verifica qual o tipo de condicao
154 56 100 66     542 if ($l eq "ELSE") { $n = " } else { "; }
  5 100 66     7  
    50          
    100          
    100          
    100          
    100          
    100          
    100          
155 16         31 elsif ($l eq "END" || $l eq "/IF" || $l eq "/FOREACH") { $n = " } "; }
156            
157             # include
158             elsif ($l =~ /^INCLUDE\s+(\-[a-z]+)?\s?(.*)/) { #(\-[a-z]+)?\s+?([\w\.\/]+)/) {
159 0         0 $i = $1; $j = $2;
  0         0  
160            
161             # Include em variavel
162 0 0       0 if ($templ_vars->{$j} =~ /^(.*)\/([\w\-\.]+)$/) {
163 0 0 0     0 $ndata .= $self->parse($self->load($1."/".$2),$templ_vars,$templ_dir)
      0        
164             if (!$i || ($i eq "-f" && -f $1."/".$2)); }
165              
166             # Include padrao
167             else {
168 0 0 0     0 $ndata .= $self->parse($self->load($templ_dir."/".$j),$templ_vars,$templ_dir)
      0        
169             if (!$i || ($i eq "-f" && -f $templ_dir."/".$j)); }
170             }
171            
172 14         28 elsif ($l =~ /^IF\s?(.*)/) { $c = $1; $n = "if "; }
  14         22  
173            
174 1         3 elsif ($l =~ /^UNLESS\s?(.*)/) { $c = $1; $n = "unless "; }
  1         2  
175            
176             elsif ($l =~ /^FOREACH\s+(\w+)\s?=\s?(.*)/) {
177             # $tp (type) verifica tipo de $c e adiciona ele em keys %{}, @{} ou outra forma
178             # quando necessario
179 1         2 $tp = $2;
180 1         3 $c = $2; $n = "foreach \$$1 "; $my{$1} = 1; }
  1         4  
  1         3  
181            
182 1         2 elsif ($l =~ /^FOR\s?(.*)/) { $c = $1; $n = "for "; }
  1         2  
183            
184 1         2 elsif ($l =~ /^(ELSIF|^ELSEIF)\s?(.*)/) { $c = $2; $n = " } elsif "; }
  1         2  
185            
186             # Funcoes
187             elsif ($l =~ /^\&(\w+)\((.*)\)/) {
188 2         5 $c = $2;
189 2         3 $nc = 1;
190              
191             # $fc = function
192 2         4 $fc = $1;
193 2         4 $my{$1} = 1;
194             }
195            
196             else {
197             # $nc = no condition
198 15         22 $nc = 1;
199 15         21 $c = $l; }
200              
201             # Monta condicao
202 56 100       110 if ($c) {
203              
204             # Recupera strings
205 30         34 my (@string,$s);
206            
207 30         32 $s = 0;
208 30         392 while ($c =~ s/([\-a-z]{1,2}?\s)?(\".*?[^\\]\")|([\-a-z]{1,2}?\s)?(\/.*?\/)/ .$s/) {
209            
210 8 50       26 if ($4) { $string[$s] = $4; }
  0 50       0  
211 0         0 elsif ($1) { $string[$s] = $1."\"".$templ_dir."/\".".$2; }
212 8         18 else { $string[$s] = $2; }
213            
214 8         98 $s++;
215             }
216              
217             # Trata condicoes e variaveis
218 30         37 my @n;
219            
220             #while ($c =~ s/\s?([^\(\)=!&<>\s]+)(\s+)?([\(\)=!&<>]{1,2})?//) {
221 30         176 while ($c =~ s/\s?(^[\!])?([^\;\(\)=!&<>\s\%\,\~]+)(\s+)?([\~\,\;\(\)=!&<>\+\%\-\.\*\/]{1,2})?//) {
222 59         113 my $i = $2;
223 59         83 my $j = $4;
224 59         78 my $k = $1;
225              
226             # Altera tudo para eq e ne
227 59 100       158 if ($j eq "==") { $j = "eq"; }
  8 100       13  
228 2         4 elsif ($j eq "!=") { $j = "ne"; }
229              
230            
231             # Volta para == caso seja igual a 0
232 59 100       120 if ($i eq "0") {
233 1 50       5 if ($n[$#n] =~ /\s+?eq\s+?/) { $n[$#n] = " == "; }
  0 50       0  
234 0         0 elsif ($n[$#n] =~ /\s+?ne\s+?/) { $n[$#n] = " != "; }
235             }
236            
237             # Recupera strings
238 59 100       172 if ($i =~ /^\.(\d+)/) {
239 8         14 $i = $1;
240 8         18 push(@n,$string[$i]); }
241              
242             else {
243 51         117 push(@n,$k.&parse_cond($i,$j)); }
244              
245             # Adiciona condicao
246 59 100       212 if ($j) {
247 23         181 push(@n," $j "); }
248             }
249            
250             # Recupera variavel
251 30         81 $i = join("",@n);
252            
253             # Var simples
254 30 100       91 if (defined $nc) {
255             # Verifica quando 'e para printar variavel
256 13 100 100     95 if (!$#n && $i =~ /\w$|}$/) {
    100          
257 2         6 $n .= "print($i); "; }
258            
259             # Verifica se esta dentro de uma funcao
260             elsif (defined $fc) {
261 2         7 $n .= "&\$".$fc."(".$i."); ";
262             }
263            
264 9         25 else { $n .= $i."; "; }
265            
266             }
267              
268             # Condicao
269             else {
270              
271             # Verifica se precisa tratar tipo
272 17 100       60 if (defined $tp) {
273 1         2 $tp =~ s/\./}->{/g;
274            
275             # Verifica se 'e array
276 1         2 $j = ref $templ_vars->{$tp};
277 1 50       4 if ($j eq "ARRAY") { $i = "\@{$i}"; }
  0 50       0  
278            
279             # Verifica se 'e hash
280 0         0 elsif ($j eq "HASH") { $i = "keys \%{$i}"; }
281              
282             # Else
283 1         2 else { $i = "\@{$i}"; }
284            
285 1         2 undef $tp;
286             }
287            
288 17         57 $n .= "($i) { "; }
289             }
290              
291 56         487 $ndata .= $n;
292             }
293              
294 6 50       35 $ndata .= "print(\"".AddSlashes($data)."\"); " if $data;
295              
296 6         20 return $ndata;
297             }
298              
299             # Parseia condicoes
300             sub parse_cond {
301 51     51 0 83 my ($i,$j) = @_;
302            
303             # Verifica AND e OR
304 51 100       367 if ($i eq "AND") { return " && "; }
  2 100       7  
    100          
    100          
    100          
305 1         5 elsif ($i eq "OR") { return " || "; }
306              
307             # Valor numerico
308 5         25 elsif ($i =~ /^(\d+)$/) { return "\'".$1."\'"; }
309              
310             # Trata variavel simples
311 32         88 elsif ($i =~ /^(\w+)([\+\-]{2})?$/) { $my{$1} = 1; return "\$$1$2"; }
  32         143  
312              
313             # Variavel estilo hash
314             elsif ($i =~ /^\w+[\.]{1}\w+/) {
315            
316             # Separa pela virgula para tratar
317 10         13 my @r;
318 10         56 while ($i =~ s/(\w+)([\+\-]{2})?//sx) {
319 20 100       44 if (@r) { push(@r,"{$1}$2"); }
  10         59  
320 10         27 else { push(@r,"\$$1"); $my{$1} = 1; }
  10         60  
321             }
322            
323 10         38 return join("->",@r);
324             }
325              
326             else {
327 1         2 return $i; }
328             }
329              
330             # Adiciona barras invertidas
331             sub AddSlashes {
332 62     62 0 123 my($str,$oreturn) = @_;
333              
334 62 50       115 $str =~ s/\%/%%/g if ($oreturn);
335             #$str =~ s/\\/\\\\/g;
336              
337 62         116 $str =~ s/([\"\#\@\$\\])/\\$1/g;
338              
339 62         164 return $str;
340             }
341              
342             1;
343              
344             __END__