File Coverage

blib/lib/Dotiac/DTL/Filter.pm
Criterion Covered Total %
statement 706 803 87.9
branch 416 634 65.6
condition 100 240 41.6
subroutine 56 59 94.9
pod 55 55 100.0
total 1333 1791 74.4


line stmt bran cond sub pod time code
1             ###############################################################################
2             #Filter.pm
3             #Last Change: 2009-01-19
4             #Copyright (c) 2009 Marc-Seabstian "Maluku" Lucksch
5             #Version 0.8
6             ####################
7             #This file is part of the Dotiac::DTL project.
8             #http://search.cpan.org/perldoc?Dotiac::DTL
9             #
10             #Filter.pm is published under the terms of the MIT license, which basically
11             #means "Do with it whatever you want". For more information, see the
12             #license.txt file that should be enclosed with libsofu distributions. A copy of
13             #the license is (at the time of writing) also available at
14             #http://www.opensource.org/licenses/mit-license.php .
15             ###############################################################################
16            
17             package Dotiac::DTL::Filter;
18 12     12   57 use strict;
  12         21  
  12         349  
19 12     12   56 use warnings;
  12         21  
  12         208331  
20             require Scalar::Util;
21             our $VERSION = 0.8;
22            
23             sub add {
24 24     24 1 27 my $value=shift;
25 24         25 my $add=shift;
26 24 100 66     56 $value->set($value->repr+$add->repr) if $value->number and $add->number;
27 24 100 66     62 $value->set($value->repr.$add->repr) unless $value->number and $add->number;
28 24         62 return $value;
29            
30             }
31            
32             sub addslashes {
33 8     8 1 9 my $value =shift;
34 8         21 my $val=$value->repr();
35 8         73 $val=~s/([\\'"])/\\$1/g;
36 8         20 $value->set($val);
37 8         19 return $value;
38             }
39            
40             sub capfirst {
41 8     8 1 8 my $value=shift;
42 8         17 return $value->set(ucfirst $value->repr);
43             }
44            
45             sub center {
46 16     16 1 17 my $value=shift;
47 16         17 my $length=shift;
48 16 50       38 return $value unless $length->number;
49 16         15 my $padding = shift;
50 16         18 my $pad=" ";
51 16 100       34 $pad=substr($padding->repr,0,1) if $padding;
52 16         39 my $val=$value->repr;
53 16         40 my $len=$length->repr;
54 16         28 $len-=CORE::length $val;
55 16 100       59 $val=($pad x int($len/2)).$val.($pad x int($len/2)).($len%2?$pad:"");
56 16         38 $value->set($val);
57 16         35 return $value;
58             }
59            
60             sub cut {
61 24     24 1 33 my $value=shift;
62 24         65 my $val=$value->repr();
63 24         39 my $t=shift;
64 24         58 $t=$t->repr();
65 24         281 $val=~s/\Q$t//g;
66 24         76 $value->set($val);
67 24         60 return $value;
68             }
69            
70             #locale stuff
71             our @datemonths=qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
72             our @datemonthl=qw( January February March April May Juni Juli August September October November December );
73             our @datemontha=qw( Jan. Feb. March April May Juni Juli Aug. Sep. Oct. Nov. Dec. );
74             our @weekdays=qw/Sun Mon Tue Wed Thu Fri Sat/;
75             our @weekdayl=qw/Sunday Monday Tuesday Wednesday Thursday Friday Saturday/;
76             our @timeampm=qw/a.m. p.m. AM PM/;
77             our @timespotnames=qw/midnight noon/;
78             our @datesuffixes=qw/th st nd rd/; #qw/Default day1 day2 day3 day4 day5...
79            
80             sub date {
81 16     16 1 82 my $value=shift;
82 16 50 66     51 return $value unless $value->number() or $value->array();
83 16         54 my $time=$value->repr();
84 16         36 my $safe=0;
85 16         22 my $string=shift;
86 16 50 33     76 if (not defined $string or not $string->scalar()) {
87 0         0 $string=$Dotiac::DTL::DATE_FORMAT;
88 0         0 $safe=1;
89             }
90             else {
91 16         49 $safe=$string->safe();
92 16         39 $string=$string->repr;
93             }
94 16         31 my @t;
95 16 100       39 if ($value->number()) {
96 12         45 @t=localtime($time);
97             }
98             else {
99 4         5 @t=@{$value->content};
  4         13  
100             }
101 16         215 my @s=split //,$string;
102 16         31 my $res;
103 16         44 while (my $s=shift(@s)) {
104 336 100       3427 if ($s eq '\\') {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    50          
    100          
    100          
    100          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
105 8         21 $res.=shift(@s);
106             }
107             elsif ($s eq "a") {
108 8 100 33     50 if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) {
      66        
109 4         13 $res.=$timeampm[0];
110             }
111             else {
112 4         19 $res.=$timeampm[1];
113             }
114             }
115             elsif ($s eq "A") {
116 8 100 33     214 if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) {
      66        
117 4         16 $res.=$timeampm[2];
118             }
119             else {
120 4         14 $res.=$timeampm[3];
121             }
122             }
123             elsif ($s eq "b") {
124 8         29 $res.=lc($datemonths[$t[4]]);
125             }
126             elsif ($s eq "d") {
127 8         39 $res.=sprintf("%02d",$t[3]);
128             }
129             elsif ($s eq "D") {
130 8         31 $res.=$weekdays[$t[6]];
131             }
132             elsif ($s eq "f") {
133 8         12 my $h=$t[2];
134 8         14 $h=$h%12;
135 8 50       21 $h=12 unless $h;
136 8         13 $res.=$h;
137 8 50       56 $res.=sprintf(":%02d",$t[1]) if ($t[1]);
138             }
139             elsif ($s eq "F") {
140 16         53 $res.=$datemonthl[$t[4]];
141             }
142             elsif ($s eq "g") {
143 8         12 my $h=$t[2];
144 8         10 $h=$h%12;
145 8 50       28 $h=12 unless $h;
146 8         25 $res.=$h;
147             }
148             elsif ($s eq "G") {
149 8         25 $res.=$t[2];
150             }
151             elsif ($s eq "h") {
152 8         14 my $h=$t[2];
153 8         10 $h=$h%12;
154 8 50       19 $h=12 unless $h;
155 8         34 $res.=sprintf("%02d",$h);
156             }
157             elsif ($s eq "H") {
158 16         57 $res.=sprintf("%02d",$t[2]);
159             }
160             elsif ($s eq "i") {
161 16         58 $res.=sprintf("%02d",$t[1]);
162             }
163             elsif ($s eq "j") {
164 16         54 $res.=$t[3];
165             }
166             elsif ($s eq "l") {
167 8         32 $res.=$weekdayl[$t[6]];
168             }
169             elsif ($s eq "L") {
170 8         17 my $d=$t[5]+1900;
171 8 50 33     70 $res.=(((not $d%4 and $d%100) or not $d%400)?"1":"0");
172             }
173             elsif ($s eq "m") {
174 8         34 $res.=sprintf("%02d",$t[4]+1);
175             }
176             elsif ($s eq "M") {
177 8         25 $res.=$datemonths[$t[4]];
178             }
179             elsif ($s eq "n") {
180 8         28 $res.=$t[4]+1;
181             }
182             elsif ($s eq "N") {
183 8         32 $res.=$datemontha[$t[4]];
184             }
185             elsif ($s eq "O") {
186 8         25 my @tt=localtime(0);
187 8 50       57 $tt[2]+=1 if $t[8];
188 8         43 $res.=sprintf("%+05d",$tt[2]*100+$tt[1]);
189             }
190             elsif ($s eq "P") {
191 8 50 33     52 if ($t[2] == 12 and $t[1] == 0) {
    50 33        
192 0         0 $res.=$timespotnames[1];
193             }
194             elsif ($t[2] == 0 and $t[1] == 0) {
195 0         0 $res.=$timespotnames[0];
196             }
197             else {
198 8         13 my $h=$t[2];
199 8         11 $h=$h%12;
200 8 50       19 $h=12 unless $h;
201 8         12 $res.=$h;
202 8 50       30 $res.=sprintf(":%02d",$t[1]) if ($t[1]);
203 8 100 33     37 if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) {
      66        
204 4         16 $res.=" ".$timeampm[0];
205             }
206             else {
207 4         18 $res.=" ".$timeampm[1];
208             }
209             }
210            
211             }
212             elsif ($s eq "r") {
213 8         16 $res.=$weekdays[$t[6]];
214 8         12 $res.=", ";
215 8         13 $res.=$t[4]+1;
216 8         22 $res.=" ".$datemonths[$t[4]]." ".($t[5]+1900);
217 8         25 $res.=sprintf(" %02d:%02d:%02d",$t[2],$t[1],$t[0]);
218 8         22 my @tt=localtime(0);
219 8 50       50 $tt[2]+=1 if $t[8];
220 8         37 $res.=sprintf(" %+05d",$tt[2]*100+$tt[1]);
221             }
222             elsif ($s eq "s") {
223 8         31 $res.=sprintf("%02d",$t[0]);
224             }
225             elsif ($s eq "S") {
226 16 100       36 if ($datesuffixes[$t[3]]) {
227 8         22 $res.=$datesuffixes[$t[3]];
228             }
229             else {
230 8         27 $res.=$datesuffixes[0]
231             }
232             }
233             elsif ($s eq "t") {
234 8 50 33     175 if ($t[4] == 1 or $t[4]==3 or $t[4] == 5 or $t[4] == 7 or $t[4] == 8 or $t[4] == 10 or $t[4] == 12) {
    50 33        
      33        
      33        
      33        
      33        
235 0         0 $res.="31";
236             }
237             elsif ($t[4] == 2) {
238 0         0 my $d=$t[5]+1900;
239 0 0 0     0 if ((not $d%4 and $d%100) or not $d%400) {
      0        
240 0         0 $res.="29";
241             }
242             else {
243 0         0 $res.="28";
244             }
245             }
246             else {
247 8         23 $res.="30";
248             }
249             }
250             elsif ($s eq "T") {
251 0         0 require POSIX;
252 0         0 $res.=POSIX::strftime("%Z", @t);
253             }
254             elsif ($s eq "t") {
255 0         0 $res.=$t[6];
256             }
257             elsif ($s eq "W") {
258 4         1103 require POSIX;
259 4         8859 $res.=POSIX::strftime("%W", @t);
260             }
261             elsif ($s eq "y") {
262 8         39 $res.=sprintf("%02d",($t[5]%100));
263             }
264             elsif ($s eq "Y") {
265 16         74 $res.=sprintf("%04d",$t[5]+1900);
266             }
267             elsif ($s eq "z") {
268 8         30 $res.=$t[7];
269             }
270             elsif ($s eq "Z") {
271 0         0 my @tt=localtime(0);
272 0 0       0 $tt[2]+=1 if $t[8];
273 0         0 $res.=$tt[2]*3600+$t[1]*60+$t[0];
274             }
275             elsif ($s eq "\n") {
276 0         0 $res.="n";
277             }
278             elsif ($s eq "\t") {
279 0         0 $res.="t";
280             }
281             elsif ($s eq "\f") {
282 8         24 $res.="f";
283             }
284             elsif ($s eq "\b") {
285 0         0 $res.="b";
286             }
287             elsif ($s eq "\r") {
288 0         0 $res.="r";
289             }
290             else {
291 44         111 $res.=$s;
292             }
293             }
294 16         65 return Dotiac::DTL::Value->new($res,$safe);
295             }
296            
297             sub default {
298 32     32 1 34 my $val=shift;
299 32         32 my $def=shift;
300 32 50       67 return $def unless $val->true;
301 0         0 return $val;
302             }
303            
304             sub default_if_none {
305 12     12 1 14 my $val=shift;
306 12         11 my $def=shift;
307 12 50       24 return $def unless $val->defined;
308 0         0 return $val;
309             }
310            
311             sub dictsort {
312 20     20 1 31 my $value=shift;
313 20 50       51 return $value unless $value->array();
314 20         28 my $by=shift;
315 20 100       35 unless ($by) {
316 64 100 66     193 $value->set([sort { if (Scalar::Util::looks_like_number($a) and Scalar::Util::looks_like_number($b)) {
  8         21  
317 40         49 $a <=> $b
318             }
319             else {
320 24         48 $a cmp $b
321             }
322 8         9 } @{$value->content}]);
323 8         21 return $value;
324             }
325 12         40 $by=$by->repr();
326 56         61 $value->set([sort {
327 12         27 my $aa = $a;
328 56 50       113 if (ref $a) {
329 56 100 66     255 $aa = $a->{$by} if Scalar::Util::reftype($a) eq "HASH" and exists $a->{$by};
330 56 50 66     267 $aa = $a->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $a->[$by];
      66        
331 56 50 33     133 $aa = $a->$by() if Scalar::Util::blessed($a) and $a->can($by);
332             }
333 56         61 my $bb = $b;
334 56 50       109 if (ref $b) {
335 56 100 66     215 $bb = $b->{$by} if Scalar::Util::reftype($b) eq "HASH" and $b->{$by};
336 56 50 66     234 $bb = $b->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $b->[$by];
      66        
337 56 50 33     140 $bb = $b->$by() if Scalar::Util::blessed($b) and $b->can($by);
338             }
339 56 100 66     235 if (Scalar::Util::looks_like_number($aa) and Scalar::Util::looks_like_number($bb)) {
340 16         53 $aa <=> $bb
341             }
342             else {
343 40         77 $aa cmp $bb
344             }
345 12         24 } @{$value->content}]);
346 12         31 return $value;
347            
348             }
349            
350             sub dictsortreversed {
351 20     20 1 29 my $value=shift;
352 20 50       51 return $value unless $value->array();
353 20         35 my $by=shift;
354 20 100       36 unless ($by) {
355 64 100 66     230 $value->set([reverse sort { if (Scalar::Util::looks_like_number($a) and Scalar::Util::looks_like_number($b)) {
  8         24  
356 40         55 $a <=> $b
357             }
358             else {
359 24         49 $a cmp $b
360             }
361 8         12 } @{$value->content}]);
362 8         23 return $value;
363             }
364 12         57 $by=$by->repr();
365 56         56 $value->set([reverse sort {
366 12         31 my $aa = $a;
367 56 50       108 if (ref $a) {
368 56 100 66     240 $aa = $a->{$by} if Scalar::Util::reftype($a) eq "HASH" and exists $a->{$by};
369 56 50 66     254 $aa = $a->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $a->[$by];
      66        
370 56 50 33     141 $aa = $a->$by() if Scalar::Util::blessed($a) and $a->can($by);
371             }
372 56         62 my $bb = $b;
373 56 50       94 if (ref $b) {
374 56 100 66     216 $bb = $b->{$by} if Scalar::Util::reftype($b) eq "HASH" and $b->{$by};
375 56 50 66     254 $bb = $b->[$by] if Scalar::Util::reftype($a) eq "ARRAY" and Scalar::Util::looks_like_number($by) and exists $b->[$by];
      66        
376 56 50 33     158 $bb = $b->$by() if Scalar::Util::blessed($b) and $b->can($by);
377             }
378 56 100 66     180 if (Scalar::Util::looks_like_number($aa) and Scalar::Util::looks_like_number($bb)) {
379 16         53 $aa <=> $bb
380             }
381             else {
382 40         93 $aa cmp $bb
383             }
384 12         18 } @{$value->content}]);
385 12         33 return $value;
386            
387             }
388            
389             sub divisibleby {
390 12     12 1 15 my $value=shift;
391 12 100       31 return Dotiac::DTL::Value->safe(0) unless $value->number;
392 8         10 my $by=shift;
393 8 50       14 return Dotiac::DTL::Value->safe(0) unless $by;
394 8 50       16 return Dotiac::DTL::Value->safe(0) unless $by->number;
395 8         18 my $res=!($value->content % $by->content);
396 8         23 return Dotiac::DTL::Value->safe($res);
397             }
398            
399             sub escape {
400 72     72 1 104 my $value=shift;
401 72         280 $value->escape(1);
402 72         180 return $value;
403             }
404            
405             #Not for JSON output of objects, I need to write an JSON-Addon for that.
406            
407             my %jsescape = (
408             "\n" => "\\n",
409             "\r" => "\\r",
410             "\t" => "\\t",
411             "\f" => "\\f",
412             "\b" => "\\b",
413             '"' => "\\\"",
414             "\\" => "\\\\",
415             "'" => "\\'",
416             );
417            
418             sub escapejs {
419 12     12 1 15 my $value=shift;
420 12         32 my $val=$value->repr();
421 12         44 $val =~ s/([\n\r\t\f\b"'\\])/$jsescape{$1}/eg;
  20         65  
422             #$val =~ s/([\x00-\x08\x0b\x0e-\x1f\x7f-\x{FFFF}])/'\\u' .sprintf("%04x",ord($1))/eg; #Won't work in Perl 5.6.0
423 12         36 $val =~ s/([^\x09\x0a\x0c\x0d\x20-\x7e])/'\\u' .sprintf("%04x",ord($1))/eg;
  8         34  
424 12         32 $value->set($val);
425 12         37 return $value;
426             }
427            
428             #Locale crap
429             our @filesizeformat=qw/bytes Kb Mb Gb Tb Eb Pb manybytes manybytes manybytes manybytes/;
430            
431             our $floatformatlocale="";
432             #sub {
433             # my $v=shift;
434             # $v=s/\./,/g;
435             # return $v;
436             #}
437            
438             sub filesizeformat {
439 12     12 1 14 my $val=shift;
440 12 50       28 return $val unless $val->number();
441 12         30 my $value=$val->content();
442 12         14 my $i=0;
443 12         24 while ($value >= 1024.0) {
444 24         23 $value=$value/1024.0;
445 24         39 $i++;
446             }
447 12 100       21 if ($value < 10) {
448 8         46 $value=sprintf("%1.2f",$value);
449             }
450             else {
451 4         20 $value=sprintf("%4.1f",$value);
452             }
453 12         27 $value=~s/0+$//g;
454 12         21 $value=~s/\.$//g;
455 12 50       19 $value=$floatformatlocale->($value) if $floatformatlocale;
456 12         53 $val->set($value." ".$filesizeformat[$i]);
457 12         31 return $val;
458             }
459            
460             sub first {
461 12     12 1 14 my $value=shift;
462 12 50       29 if ($value->object) {
463 0 0       0 if ($value->content->can("__getitem__")) {
464 0         0 my $x = $value->content->__getitem__(0);
465 0 0       0 if (defined $x) {
466 0         0 $value->set($x);
467 0         0 return $value;
468             }
469             }
470             }
471 12 100       30 if ($value->array) {
    50          
472 8         22 $value->set($value->content->[0]);
473             }
474             elsif ($value->hash) {
475 4         6 my @a=sort keys %{$value->content};
  4         10  
476 4         12 $value->set($value->content->{$a[0]});
477             }
478 12         38 return $value;
479             }
480            
481             sub fix_ampersands {
482 12     12 1 12 my $value=shift;
483 12         26 my $val=$value->repr();
484 12         32 $val=~s/&/&/g;
485 12         29 $value->set($val);
486 12         24 return $value;
487             }
488            
489             sub floatformat {
490 16     16 1 19 my $val=shift;
491 16 50       40 return $val if not $val->number;
492 16         42 my $value=$val->content;
493 16         20 my $arg=shift;
494 16 100 100     55 if ($arg and not $arg->number) {
495 4         18 $val->set(int($value+0.5));
496 4         12 return $val
497             }
498 12 100       22 if ($arg) {
499 8         15 $arg=$arg->content;
500             }
501             else {
502 4         5 $arg=-1;
503             }
504 12         34 my $skip=$arg=~s/^-//;
505 12         79 $value=sprintf("%.".$arg."f",$value);
506 12 100       25 unless ($skip) {
507 8 50       15 $value=$floatformatlocale->($value) if $floatformatlocale;
508 8         21 $val->set($value);
509 8         21 return $val;
510             }
511 4         16 $value=~s/0+$//g;
512 4         9 $value=~s/\.$//g;
513 4 50       11 $value=$floatformatlocale->($value) if $floatformatlocale;
514 4         12 $val->set($value);
515 4         10 return $val;
516             }
517            
518             my $escape=sub {
519             my $val=shift;
520             $val=~s/&/&/g;
521             $val=~s/
522             $val=~s/>/>/g;
523             $val=~s/\"/"/g;
524             $val=~s/\'/'/g;
525             return $val;
526             };
527            
528             sub force_escape {
529 12     12 1 16 my $value=shift;
530 12         37 $value->escape(1);
531 12         30 return Dotiac::DTL::Value->safe($value->string());
532             }
533            
534             sub get_digit {
535 12     12 1 15 my $value=shift;
536 12 100       32 return $value unless $value->number;
537 8         21 my $val=$value->content;;
538 8         11 my $pos = shift;
539 8 50 33     28 return $val unless defined $pos and $pos->number;
540 8         17 $pos=int $pos->content;
541 8 50       17 return $value if $pos < 1;
542 8 100       24 return Dotiac::DTL::Value->safe(0) if $pos > CORE::length($val);
543 4         18 $value->set(substr $val,-$pos,1);
544 4         12 return $value;
545             }
546            
547             #Should only be used together with urlencode
548             sub iriencode {
549 12     12 1 14 my $val=shift;
550 12         31 my $value=$val->repr;
551             #require Encode;
552             #$value=Encode::encode_utf8($value) if Encode::is_utf8($value);
553 12   33     17 $value = eval { pack("C*", unpack("U0C*", $value))} || pack("C*", unpack("C*", $value));
554 12         37 $value=~s/([^a-zA-Z0-9\[\]\(\)\$\%\&\/:;#=,!\?\*_.~-])/uc sprintf("%%%02x",ord($1))/eg;
  16         65  
555 12         31 $val->set($value);
556 12         27 return $val;
557             }
558            
559             sub join {
560 20     20 1 30 my $value=shift;
561 20         23 my $j=shift;
562 20 100       42 if ($j) {
563 16         47 $j=$j->repr;
564             }
565             else {
566 4         6 $j="";
567             }
568 20 50       69 if ($value->object) {
569 0 0 0     0 if ($value->content->can("__len__") and $value->content->can("__getitem__")) { #No support for __iter__ right now.
570 0         0 my @a;
571 0         0 foreach my $i (0 .. $value->content->__len__()-1) {
572 0         0 push @a,$value->content->__getitem__($i);
573             }
574 0         0 $value->set(CORE::join($j,@a));
575 0         0 return $value
576             }
577 0 0 0     0 if ($value->content->can("count") and $value->content->can("__getitem__")) { #No support for __iter__ right now.
578 0         0 my @a;
579 0         0 foreach my $i (0 .. $value->content->count()-1) {
580 0         0 push @a,$value->content->__getitem__($i);
581             }
582 0         0 $value->set(CORE::join($j,@a));
583 0         0 return $value;
584             }
585             }
586 20 50       55 $value->set(CORE::join($j,@{$value->content})) if $value->array;
  20         58  
587 20 50       65 $value->set(CORE::join($j,values %{$value->content})) if $value->hash;
  0         0  
588 20         55 return $value;
589             }
590            
591             sub last {
592 12     12 1 16 my $value=shift;
593 12 50       31 if ($value->object) {
594 0 0 0     0 if ($value->content->can("__len__") and $value->content->can("__getitem__")) {
595 0         0 my $x = $value->content->__getitem__($value->content->__len__()-1);
596 0 0       0 if (defined $x) {
597 0         0 $value->set($x);
598 0         0 return $value;
599             }
600             }
601 0 0 0     0 if ($value->content->can("count") and $value->content->can("__getitem__")) {
602 0         0 my $x = $value->content->__getitem__($value->content->count()-1);
603 0 0       0 if (defined $x) {
604 0         0 $value->set($x);
605 0         0 return $value;
606             }
607             }
608             }
609 12 100       35 if ($value->array) {
    50          
610 8 100       9 if (@{$value->content}) {
  8         27  
611 4         11 $value->set($value->content->[-1]);
612             }
613             else {
614 4         11 $value->set(undef);
615             }
616             }
617             elsif ($value->hash) {
618 4         4 my @a=sort keys %{$value->content};
  4         11  
619 4 50       10 if (@a) {
620 4         10 $value->set($value->content->{$a[-1]});
621             }
622             else {
623 0         0 $value->set(undef);
624             }
625             }
626 12         38 return $value;
627             }
628            
629             sub length {
630 12     12 1 13 my $value=shift;
631 12 50       29 return Dotiac::DTL::Value->safe(0) if $value->undef;
632 12 100       31 return Dotiac::DTL::Value->safe(CORE::length($value->content)) if $value->scalar;
633 8 50 33     18 return Dotiac::DTL::Value->safe($value->content->count()) if $value->object and $value->content->can("count");
634 8 50 33     16 return Dotiac::DTL::Value->safe($value->content->__len__()) if $value->object and $value->content->can("__len__");
635 8 100       18 return Dotiac::DTL::Value->safe(scalar @{$value->content}) if $value->array;
  4         11  
636 4 50       11 return Dotiac::DTL::Value->safe(scalar keys %{$value->content}) if $value->hash;
  4         10  
637 0         0 return Dotiac::DTL::Value->safe(0);
638             }
639            
640             #output will be 1 or 0, not True or False
641             sub length_is {
642 12     12 1 13 my $value=shift;
643 12         11 my $is=shift;
644 12 50       28 if ($is->number) {
645 12         26 $is=int($is->content());
646             }
647             else {
648 0         0 $is=0;
649             }
650 12 50 33     54 $is = 0 unless defined $is and Scalar::Util::looks_like_number($is);
651 12 50       26 return Dotiac::DTL::Value->safe(!$is) if $value->undef;
652 12 100       29 return Dotiac::DTL::Value->safe(CORE::length($value->content) == $is) if $value->scalar();
653 8 50 33     20 return Dotiac::DTL::Value->safe($value->content->count() == $is) if $value->object and $value->content->can("count");
654 8 50 33     21 return Dotiac::DTL::Value->safe($value->content->__len__() == $is) if $value->object and $value->content->can("__len__");
655 8 100       18 return Dotiac::DTL::Value->safe(@{$value->content} == $is) if $value->array;
  4         11  
656 4 50       10 return Dotiac::DTL::Value->safe(keys %{$value->content} == $is) if $value->hash;
  4         10  
657 0         0 return Dotiac::DTL::Value->safe(0)
658             }
659            
660             sub linebreaks {
661 12     12 1 20 my $value=shift;
662 12         27 $value=$value->string();
663 12         56 $value=~s/\n\s*\n/<\/p>

/g;

664 12         30 $value=~s/\n/
/g;
665 12         44 return Dotiac::DTL::Value->safe("

".$value."

");
666             }
667            
668             sub linebreaksbr {
669 12     12 1 14 my $value=shift;
670 12         27 $value=$value->string();
671 12         39 $value=~s/\n/
/g;
672 12         32 return Dotiac::DTL::Value->safe($value);
673             }
674            
675             sub linenumbers {
676 12     12 1 15 my $val=shift;
677 12         29 my $value=$val->repr();
678 12 50       27 return $val->set("1: $value") unless $value;
679 12         22 my $count = ($value =~ tr/\n/\n/);
680 12         16 $count=CORE::length $count;
681 12         10 my $i=1;
682 12         32 $value=~s/\n/sprintf("\n%0$count"."d: ",++$i)/eg;
  44         112  
683 12         46 return $val->set(sprintf("%0$count"."d: ",1).$value);
684             }
685            
686             sub ljust {
687 16     16 1 22 my $value=shift;
688 16         16 my $length=shift;
689 16 50       41 return $value unless $length->number;
690 16         19 my $padding = shift;
691 16         19 my $pad=" ";
692 16 100       32 $pad=substr($padding->repr,0,1) if $padding;
693 16         35 my $val=$value->repr;
694 16         40 my $len=$length->repr;
695 16         30 $len-=CORE::length $val;
696 16         23 $val=$val.($pad x int($len));
697 16         37 $value->set($val);
698 16         36 return $value;
699             }
700            
701             sub lower {
702 44     44 1 64 my $value=shift;
703 44         137 return $value->set(lc $value->repr);
704             }
705            
706             sub make_list {
707 20     20 1 28 my $value=shift;
708 20         56 my $val=$value->repr;
709 20         33 my $by=shift;
710 20 100       46 if ($by) {
711 4         14 $by=quotemeta $by->repr;
712 4         42 $value->set([split /$by/,$val]);
713             }
714 20         111 return $value->set([split //,$val]);
715             }
716            
717             #No locale for now
718            
719             sub phone2numeric {
720 12     12 1 17 my $val=shift;
721 12         37 my $value=$val->repr;
722 12         28 $value=~y/AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpRrSsTtUuVvWwXxYy/222222333333444444555555666666777777888888999999/;
723 12         37 return $val->set($value);
724             }
725            
726             our $pluralizedefault = "s";
727            
728             sub pluralize {
729 32     32 1 49 my $value=shift;
730 32         246 my $val=0;
731 32 50       89 $val=CORE::length $value->content if $value->scalar;
732 32 50       189 $val=$value->content if $value->number;
733 32 50       133 $val=scalar keys %{$value->content} if $value->hash;
  0         0  
734 32 50       239 $val=scalar @{$value->content} if $value->array;
  0         0  
735 32         52 my $s = $pluralizedefault;
736 32 100       76 if (@_) {
737 24 50       60 $s=shift() if @_;
738 24         71 $s=$s->repr();
739             }
740 32         261 my $p;
741             my $o;
742 32 100       64 if (@_) {
743 8         15 $o=$s;
744 8         13 $p=shift;
745 8         220 $p=$p->repr();
746             }
747             else {
748 24         65 ($o,$p) = split /,/,$s,2;
749             }
750 32 100       75 unless ($p) {
751 16         22 $p=$o;
752 16         21 $o="";
753             }
754 32 100       123 return $value->set($val==1?$o:$p);
755             }
756            
757            
758             sub pprint {
759 0     0 1 0 require Data::Dumper;
760 0         0 return Dotiac::DTL::Value->new(Data::Dumper->Dump([@_]));
761             }
762            
763             sub random {
764 12     12 1 14 my $value=shift;
765 12 50       36 if ($value->object) {
766 0 0 0     0 if ($value->content->can("__len__") and $value->content->can("__getitem__")) {
767 0         0 my $x = $value->content->__getitem__(int(rand($value->content->__len__())));
768 0 0       0 if (defined $x) {
769 0         0 return $value->set($x);
770             }
771             }
772 0 0 0     0 if ($value->content->can("count") and $value->content->can("__getitem__")) {
773 0         0 my $x = $value->content->__getitem__(int(rand($value->content->count())));
774 0 0       0 if (defined $x) {
775 0         0 return $value->set($x);
776             }
777             }
778             }
779 12 100       35 if ($value->array) {
    50          
780 8 100       8 if (@{$value->content}) {
  8         21  
781 4         11 return $value->set($value->content->[int(rand(scalar @{$value->content}))]);
  4         12  
782             }
783             else {
784 4         11 return $value->set(undef);
785             }
786             }
787             elsif ($value->hash) {
788 4         6 my @a=sort keys %{$value->content};
  4         12  
789 4 50       11 if (@a) {
790 4         10 return $value->set($value->content->{$a[int(rand(scalar @a))]});
791             }
792             else {
793 0         0 return $value->set(undef);
794             }
795             }
796 0         0 return $value;
797             }
798            
799             sub removetags {
800 12     12 1 17 my $val=shift;
801 12         31 my $value=$val->repr();
802 12         20 my $tags=shift;
803 12         26 $tags=$tags->repr;
804 12 50       27 if ($tags) {
805 12         34 my @t=split /\s+/,$tags;
806 12         20 my $t=CORE::join("|",map {quotemeta $_} @t);
  20         48  
807 12         443 $value=~s/<\/?(?:$t)(?:\/?>|\s[^>]+>)//g;
808             }
809 12         43 return $val->set($value);
810             }
811            
812             sub rjust {
813 16     16 1 20 my $value=shift;
814 16         17 my $length=shift;
815 16 50       46 return $value unless $length->number;
816 16         20 my $padding = shift;
817 16         21 my $pad=" ";
818 16 100       37 $pad=substr($padding->repr,0,1) if $padding;
819 16         41 my $val=$value->repr;
820 16         43 my $len=$length->repr;
821 16         31 $len-=CORE::length $val;
822 16         34 $val=($pad x int($len)).$val;
823 16         43 $value->set($val);
824 16         42 return $value;
825             }
826            
827             sub safe {
828 36     36 1 52 my $value=shift;
829 36         103 $value->safe(1);
830 36         84 return $value;
831             }
832            
833             sub slice {
834 40     40 1 50 my $value=shift;
835 40 50 66     97 return $value unless $value->hash or $value->array;
836 40         67 my $slice=shift;
837 40 50       70 return $value unless $slice;
838 40         130 $slice=$slice->repr;
839 40         118 my @slice=split /:/,$slice,2;
840            
841 40         179 my @value;
842 40 100       100 @value=@{$value->content} if $value->array;
  20         54  
843 40 100       103 @value=sort keys %{$value->content} if $value->hash;
  20         51  
844            
845 40   100     167 $slice[0] = int($slice[0] || 0) || 0;
846 40 100       86 unless ($#slice) {
847 8 50       26 return $value unless Scalar::Util::looks_like_number($slice[0]);
848 8 100       22 return $value->set($value[int($slice[0])]) if $value->array;
849 4 50       16 return $value->set($value->content->{$value[int($slice[0])]}) if $value->hash;
850             }
851            
852 32   100     119 $slice[1] = int($slice[1] || 0) || 0;
853 32 100       66 $slice[1]-=$slice[0] if ($slice[1] > 0);
854 32 100       69 $slice[1]=scalar(@value)-$slice[0] unless $slice[1];
855 32 100       73 return $value->set([splice(@value,$slice[0],$slice[1])]) if $value->array;
856 16 50       43 return $value->set([map {$value->content->{$_}} splice(@value,$slice[0],$slice[1])]) if $value->hash;
  28         64  
857             }
858            
859             sub slugify {
860 12     12 1 15 my $value=shift;
861 12         33 my $val=$value->repr();
862 12         24 $val=lc($val);
863 12         40 $val=~s/[^\w\s]//g;
864 12         30 $val=~s/^\s+//g;
865 12         31 $val=~s/\s+$//g;
866 12         23 $val=~s/\s/-/g;
867 12         36 $value->safe(1);
868 12         32 return $value->set($val);
869             }
870            
871            
872            
873             #This follows perls sprintf rules for now, which are about the same, but there is no "r"
874            
875             sub stringformat {
876 12     12 1 18 my $value=shift;
877 12         14 my $format=shift;
878 12 50       26 return $value unless $format;
879 12         33 $format=$format->repr;
880 12         19 my $val="";
881 12 100       29 if ($format=~tr/r/s/) {
882 4         14 $val=$value->pyrepr;
883             }
884             else {
885 8         21 $val=$value->repr;
886             }
887 12         26 my $v;
888 12         12 eval {
889 12     0   66 local $SIG{__WARN__} = sub {};
  0         0  
890 12         66 $v=sprintf("%$format",$val);
891             };
892 12 50       46 return $value->set($v) unless $@;
893 0         0 undef $@;
894 0         0 return $value;
895             }
896            
897             sub striptags {
898 12     12 1 15 my $value=shift;
899 12         31 my $val=$value->repr;
900 12         20 my $tags=shift;
901 12         92 $val=~s/<[^>]+>//g;
902 12         35 return $value->set($val);
903             }
904            
905             sub time {
906 12     12 1 18 my $value=shift;
907 12 50 66     33 return $value unless $value->number() or $value->array();
908 12         33 my $time=$value->repr();
909 12         25 my $safe=0;
910 12         14 my $string=shift;
911 12 50 33     47 if (not defined $string or not $string->scalar()) {
912 0         0 $string=$Dotiac::DTL::DATE_FORMAT;
913 0         0 $safe=1;
914             }
915             else {
916 12         34 $safe=$string->safe();
917 12         32 $string=$string->repr;
918             }
919 12         20 my @t;
920 12 100       28 if ($value->number()) {
921 8         22 @t=localtime($time);
922             }
923             else {
924 4         6 @t=@{$value->content};
  4         13  
925             }
926 12         102 my @s=split //,$string;
927 12         17 my $res;
928 12         28 while (my $s=shift(@s)) {
929 80 50       488 if ($s eq '\\') {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    50          
    100          
    100          
    100          
930 0         0 $res.=shift(@s);
931             }
932             elsif ($s eq "a") {
933 4 50 0     14 if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) {
      33        
934 4         13 $res.=$timeampm[0];
935             }
936             else {
937 0         0 $res.=$timeampm[1];
938             }
939             }
940             elsif ($s eq "A") {
941 4 50 0     16 if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) {
      33        
942 4         13 $res.=$timeampm[2];
943             }
944             else {
945 0         0 $res.=$timeampm[3];
946             }
947             }
948             elsif ($s eq "f") {
949 4         8 my $h=$t[2];
950 4         6 $h=$h%12;
951 4 50       7 $h=12 unless $h;
952 4         13 $res.=$h;
953 4 50       23 $res.=sprintf(":%02d",$t[1]) if ($t[1]);
954             }
955             elsif ($s eq "g") {
956 4         7 my $h=$t[2];
957 4         6 $h=$h%12;
958 4 50       9 $h=12 unless $h;
959 4         11 $res.=$h;
960             }
961             elsif ($s eq "G") {
962 4         14 $res.=$t[2];
963             }
964             elsif ($s eq "h") {
965 4         8 my $h=$t[2];
966 4         5 $h=$h%12;
967 4 50       15 $h=12 unless $h;
968 4         16 $res.=sprintf("%02d",$h);
969             }
970             elsif ($s eq "H") {
971 8         33 $res.=sprintf("%02d",$t[2]);
972             }
973             elsif ($s eq "i") {
974 8         27 $res.=sprintf("%02d",$t[1]);
975             }
976             elsif ($s eq "O") {
977 4         12 my @tt=localtime(0);
978 4 50       23 $tt[2]+=1 if $t[8];
979 4         22 $res.=sprintf("%+05d",$tt[2]*100+$tt[1]);
980             }
981             elsif ($s eq "P") {
982 8 50 33     37 if ($t[2] == 12 and $t[1] == 0) {
    50 33        
983 0         0 $res.=$timespotnames[1];
984             }
985             elsif ($t[2] == 0 and $t[1] == 0) {
986 0         0 $res.=$timespotnames[0];
987             }
988             else {
989 8         9 my $h=$t[2];
990 8         12 $h=$h%12;
991 8 50       21 $h=12 unless $h;
992 8         11 $res.=$h;
993 8 50       28 $res.=sprintf(":%02d",$t[1]) if ($t[1]);
994 8 50 0     21 if ($t[2] > 12 or ($t[2] == 12 and $t[1] > 0)) {
      33        
995 8         31 $res.=" ".$timeampm[0];
996             }
997             else {
998 0         0 $res.=" ".$timeampm[1];
999             }
1000             }
1001            
1002             }
1003             elsif ($s eq "s") {
1004 4         14 $res.=sprintf("%02d",$t[0]);
1005             }
1006             elsif ($s eq "Z") {
1007 4         13 my @tt=localtime(0);
1008 4 50       23 $tt[2]+=1 if $t[8];
1009 4         17 $res.=$tt[2]*3600+$t[1]*60+$t[0];
1010             }
1011             elsif ($s eq "\n") {
1012 4         10 $res.="n";
1013             }
1014             elsif ($s eq "\t") {
1015 0         0 $res.="t";
1016             }
1017             elsif ($s eq "\f") {
1018 4         13 $res.="f";
1019             }
1020             elsif ($s eq "\b") {
1021 4         11 $res.="b";
1022             }
1023             elsif ($s eq "\r") {
1024 4         12 $res.="r";
1025             }
1026             else {
1027 4         14 $res.=$s;
1028             }
1029             }
1030 12         40 return Dotiac::DTL::Value->new($res,$safe);
1031             }
1032            
1033             our @timenames=qw/year years month month week weeks day days hour hours minute minutes/;
1034            
1035             sub timesince {
1036 20     20 1 27 my $val=shift;
1037 20 50       53 return $val unless $val->number;
1038 20         54 $val=$val->content;
1039 20         32 my $comp=shift;
1040 20 50 33     71 if ($comp and $comp->number) {
1041 20         43 $comp=$comp->content;
1042             }
1043             else {
1044 0         0 $comp=CORE::time();
1045             }
1046 20         40 my $dist=$comp-$val;
1047 20 50       41 return Dotiac::DTL::Value->safe("0 $timenames[11]") if $dist < 60;
1048 20         30 my $mi=int($dist/60);
1049 20         29 my $h=int($mi/60);
1050 20         23 $mi=$mi%60;
1051 20         25 my $d=int($h/24);
1052 20         19 $h=$h%24;
1053 20         27 my $w=int($d/7);
1054 20         23 my $m=int($d/30);
1055 20 50       29 if ($m) {
1056 0         0 $d=$d%30;
1057             }
1058             else {
1059 20         22 $d=$d%7;
1060             }
1061 20         24 my $y=int($m/12);
1062 20         31 $m=$m%12;
1063 20 100       36 if (@_) {
1064 8 0       89 my $r=($y?"$y ".($y==1?"$timenames[0] ":"$timenames[1] "):"").($m?"$m ".($m==1?"$timenames[2] ":"$timenames[3] "):($w?"$w ".($w==1?"$timenames[4] ":"$timenames[5] "):"")).($d?"$d ".($d==1?"$timenames[6] ":"$timenames[7] "):"").($h?"$h ".($h==1?"$timenames[8] ":"$timenames[9] "):"").($mi?"$mi ".($mi==1?"$timenames[10] ":"$timenames[11] "):"");
    50          
    0          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
1065 8         25 $r=~s/\s$//;
1066 8         29 return Dotiac::DTL::Value->safe($r);
1067             }
1068 12 0       22 return Dotiac::DTL::Value->safe("$y ".($y==1?$timenames[0]:$timenames[1])) if ($y);
    50          
1069 12 0       26 return Dotiac::DTL::Value->safe("$m ".($m==1?$timenames[2]:$timenames[3])) if ($m);
    50          
1070 12 50       40 return Dotiac::DTL::Value->safe("$w ".($w==1?$timenames[4]:$timenames[5])) if ($w);
    100          
1071 8 0       16 return Dotiac::DTL::Value->safe("$d ".($d==1?$timenames[6]:$timenames[7])) if ($d);
    50          
1072 8 50       49 return Dotiac::DTL::Value->safe("$h ".($h==1?$timenames[8]:$timenames[9]).($mi?" $mi ".($mi==1?$timenames[10]:$timenames[11]):"")) if $h;
    50          
    50          
    100          
1073 4 50       30 return Dotiac::DTL::Value->safe("$mi ".($mi==1?$timenames[10]:$timenames[11])) if ($mi);
    50          
1074            
1075             }
1076            
1077             sub timeuntil {
1078 20     20 1 23 my $val=shift;
1079 20 50       51 return $val unless $val->number;
1080 20         49 $val=$val->content;
1081 20         27 my $comp=shift;
1082 20 50 33     67 if ($comp and $comp->number) {
1083 20         42 $comp=$comp->content;
1084             }
1085             else {
1086 0         0 $comp=CORE::time();
1087             }
1088 20         33 my $dist=$val-$comp;
1089 20 50       35 return Dotiac::DTL::Value->safe("0 $timenames[11]") if $dist < 60;
1090 20         28 my $mi=int($dist/60);
1091 20         22 my $h=int($mi/60);
1092 20         22 $mi=$mi%60;
1093 20         22 my $d=int($h/24);
1094 20         21 $h=$h%24;
1095 20         21 my $w=int($d/7);
1096 20         24 my $m=int($d/30);
1097 20 50       29 if ($m) {
1098 0         0 $d=$d%30;
1099             }
1100             else {
1101 20         21 $d=$d%7;
1102             }
1103 20         25 my $y=int($m/12);
1104 20         17 $m=$m%12;
1105 20 100       33 if (@_) {
1106 8 0       110 my $r=($y?"$y ".($y==1?"$timenames[0] ":"$timenames[1] "):"").($m?"$m ".($m==1?"$timenames[2] ":"$timenames[3] "):($w?"$w ".($w==1?"$timenames[4] ":"$timenames[5] "):"")).($d?"$d ".($d==1?"$timenames[6] ":"$timenames[7] "):"").($h?"$h ".($h==1?"$timenames[8] ":"$timenames[9] "):"").($mi?"$mi ".($mi==1?"$timenames[10] ":"$timenames[11] "):"");
    50          
    0          
    50          
    100          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
1107 8         24 $r=~s/\s$//;
1108 8         26 return Dotiac::DTL::Value->safe($r);
1109             }
1110 12 0       20 return Dotiac::DTL::Value->safe("$y ".($y==1?$timenames[0]:$timenames[1])) if ($y);
    50          
1111 12 0       20 return Dotiac::DTL::Value->safe("$m ".($m==1?$timenames[2]:$timenames[3])) if ($m);
    50          
1112 12 50       41 return Dotiac::DTL::Value->safe("$w ".($w==1?$timenames[4]:$timenames[5])) if ($w);
    100          
1113 8 0       14 return Dotiac::DTL::Value->safe("$d ".($d==1?$timenames[6]:$timenames[7])) if ($d);
    50          
1114 8 50       44 return Dotiac::DTL::Value->safe("$h ".($h==1?$timenames[8]:$timenames[9]).($mi?" $mi ".($mi==1?$timenames[10]:$timenames[11]):"")) if $h;
    50          
    50          
    100          
1115 4 50       30 return Dotiac::DTL::Value->safe("$mi ".($mi==1?$timenames[10]:$timenames[11])) if ($mi);
    50          
1116            
1117             }
1118            
1119             sub title {
1120 8     8 1 11 my $val=shift;
1121 8         21 my $value=$val->repr();
1122 8         42 $value=~s/(\w+)/ucfirst($1)/eg;
  12         35  
1123 8         28 return $val->set($value);
1124             }
1125            
1126             sub truncatewords {
1127 8     8 1 11 my $value=shift;
1128 8         11 my $words=shift;
1129 8 50 33     45 return $value unless $words and $words->number;
1130 8         23 my @val = split /(\s+)/,$value->repr;
1131 8         29 $words=($words->content-1)*2;
1132 8 100       31 return $value if $words >= $#val;
1133             #$words=$#val if $words > $#val;
1134 4 50       29 return $value->set(CORE::join("",@val[0 .. $words],($val[$words]=~/\.\.\./?"":"...")));
1135             }
1136            
1137             my %singletags=qw/br 1 col 1 link 1 base 1 img 1 param 1 area 1 hr 1 input 1/;
1138            
1139             sub truncatewords_html {
1140 8     8 1 13 my $val=shift;
1141 8         23 my $value=$val->string();
1142 8         13 my $words=shift;
1143 8 50 33     36 return $val unless $words and $words->number;
1144 8         13 my $len=CORE::length($value);
1145 8         104 $words=$words->content;
1146 8         15 my $ret="";
1147 8         11 my @tags;
1148 8   100     67 while ($words and (pos($value)||0) < $len) {
      100        
1149 60         71 my $pos=pos($value);
1150 60 100       1228 if ($a=$value=~m/\G(\s*[^<\s]+\s*)/g) {
1151 36         57 $ret.=$1;
1152             #warn "$1 $words";
1153 36         40 $words--;
1154 36         159 next;
1155             }
1156             else {
1157 24         59 pos($value)=$pos;
1158             }
1159 24 50       99 if ($a=$value=~m/\G\s*
1160 24 50       77 if ($a=$value=~m/([^>]+)>/g) {
1161 24         53 $ret.="<$1>";
1162 24         39 my $tag=lc($1);
1163 24 50       90 if ($tag eq "/") { #SGML: Close last tag , never seen it used in HTML, but whatever.
    100          
    50          
1164 0         0 shift @tags;
1165             }
1166             elsif ($tag=~s/^\///) {
1167 8         20 my @t=@tags;
1168 8         311 $tag=~m/^(\w+)/;
1169 8         16 $tag=$1;
1170 8         13 my $t=shift @t;
1171 8   66     69 $t=shift @t while (@t and $t ne $tag);
1172 8 50       17 if ($t eq $tag) {
1173 8         20 @tags=@t; #SGML:

bbb

, the

also closes
.
1174             }
1175 8         47 next;
1176             }
1177             elsif ($tag=~s/\/$//) { #XML: Singletag
1178 0         0 next;
1179             }
1180             else {
1181 16         38 $tag=~m/^(\w+)/;
1182 16         25 $tag=$1;
1183 16 50       52 unshift @tags,$tag unless $singletags{$tag}; #Some HTML-Tags shouldn't be closed, (why not, I wonder)
1184 16         83 next;
1185             }
1186             }
1187             else {
1188 0         0 return $val->set($ret); #Parsingerror.
1189             }
1190             }
1191             else {
1192 0         0 pos($value)=$pos;
1193             }
1194            
1195             }
1196 8 100       27 return $val if $words > 0; #Should be allright then.
1197 4         20 $ret=~s/\s+$//g;
1198 4 50       16 $ret.="..." unless $ret=~m/\.\.\.$/;
1199 4         6 foreach my $t (@tags) {
1200 8         17 $ret.="";
1201             }
1202 4         14 return $val->set($ret);
1203             }
1204            
1205            
1206             #TODO TODO TODO
1207             # Split in subfuntion ziehe safe aus $value->safe();
1208             #TODO TODO TODO
1209             #
1210             my $unordered_list;
1211             $unordered_list = sub {
1212             my $e=shift;
1213             my $save=shift;
1214             my $level=shift;
1215             my $res="";
1216             return "" unless ref $e and ref $e eq "ARRAY";
1217             my @loop=@$e;
1218             while (@loop) {
1219             my $title=shift @loop;
1220             $title=$escape->($title) unless $save;
1221             $res.="\t"x($level)."
  • $title";
  • 1222             if (ref $loop[0] and ref $loop[0] eq "ARRAY") {
    1223             $res.="\n"."\t"x($level)."
      \n";
    1224             $res.=$unordered_list->(shift(@loop),$save,$level+1);
    1225             $res.="\t"x($level)."\n";
    1226             $res.="\t"x($level);
    1227             }
    1228            
    1229             $res.="\n"
    1230             }
    1231             return $res;
    1232            
    1233             };
    1234            
    1235             sub unordered_list {
    1236 4     4 1 9 my $value=shift;
    1237 4 50       14 return "
  • ".$value->string()."
  • \n" if $value->scalar;
    1238 4 50       17 return $value unless $value->array;
    1239 4         15 my @loop=@$value;
    1240 4 0 33     16 if (@loop==2 and ref $loop[1] and Scalar::Util::reftype($loop[1]) eq "ARRAY" and (ref $loop[1]->[0] or not @{$loop[1]})) {
          33        
          0        
          0        
    1241             #$ret.=unordered_list($loop[0],$save,$level);
    1242             my $r=sub {
    1243 0     0   0 my $d=shift;
    1244 0         0 my $r=shift;
    1245 0         0 return ($d->[0],[map {$r->($_,$r)} @{$d->[1]}]);
      0         0  
      0         0  
    1246 0         0 };
    1247 0         0 @loop=$r->($value,$r);
    1248             #@loop=($loop[0],[map {@$_} @{$loop[1]}]);
    1249             }
    1250 4         13 my $ret=$unordered_list->($value->content(),$value->safe,0);
    1251 4         20 return Dotiac::DTL::Value->safe($ret);
    1252             }
    1253            
    1254            
    1255             sub upper {
    1256 36     36 1 74 my $value=shift;
    1257 36         122 $value->set(uc $value->repr);
    1258 36         122 return $value;
    1259             }
    1260            
    1261             #This awesome Regex ripped of http://geekswithblogs.net/casualjim/archive/2005/12/01/61722.aspx
    1262            
    1263             #Addition: parameters: Safechars. urlencode:"" encodes also slashes, needed if you are gonna built an url and urlencode:":/?=&" can be run over an http://foo/bar?foo=bar string
    1264             sub urlencode {
    1265 104     104 1 152 my $val=shift;
    1266 104         287 my $value=$val->repr;
    1267 104         212 my $safe="/";
    1268 104 100       262 if (@_) {
    1269 100         129 $safe=shift;
    1270 100 100       259 $safe=$safe->repr() if ref $safe; # For internal use
    1271             }
    1272 104 100       218 $safe="" unless $safe;
    1273 104         156 $safe=quotemeta($safe);
    1274 104         2039 my $find=qr/([^\w$safe\.~-])/;
    1275 104         440 $value=~s/$find/uc sprintf("%%%02x",ord($1))/eg;
      20         98  
    1276 104         339 return $val->set($value);
    1277             }
    1278            
    1279             sub urlize {
    1280 8     8 1 12 my $value=shift;
    1281 8         26 $value=$value->string();
    1282             #$value=~s"(^|(?'.$a.''"eg;
    1283 8 50       101 $value=~s"((?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!\$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)(?:(?:&|&|;)(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)?)"my $a=$1;''.$a.''"eg;
      8         17  
      8         50  
    1284 8         28 return Dotiac::DTL::Value->safe($value);
    1285             }
    1286            
    1287             sub urlizetrunc {
    1288 8     8 1 17 my $value=shift;
    1289 8         29 $value=$value->string();
    1290 8         17 my $len=shift;
    1291 8 50 33     37 if ($len and $len->number) {
    1292 8         28 $len=int($len->content);
    1293             }
    1294             else {
    1295 0         0 $len=0;
    1296             }
    1297 8 50       23 $len=15 unless $len;
    1298             #$value=~s"(^|(?'.($len >= CORE::length($a)?$a:substr($a,0,$len).'...').''"eg;
    1299 8 50       110 $value=~s"((?#Protocol)(?:(?:ht|f)tp(?:s?)\:\/\/|~/|/)?(?#Username:Password)(?:\w+:\w+@)?(?#Subdomains)(?:(?:[-\w]+\.)+(?#TopLevel Domains)(?:com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|travel|[a-z]{2}))(?#Port)(?::[\d]{1,5})?(?#Directories)(?:(?:(?:/(?:[-\w~!\$+|.,=]|%[a-f\d]{2})+)+|/)+|\?|#)?(?#Query)(?:(?:\?(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)(?:(?:&|&|;)(?:[-\w~!\$+|.,*:]|%[a-f\d{2}])+=(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)*)*(?#Anchor)(?:#(?:[-\w~!\$+|.,*:=]|%[a-f\d]{2})*)?)"my $a=$1;''.($len >= CORE::length($a)?$a:substr($a,0,$len).'...').''"eg;
      8 50       18  
      8         73  
    1300 8         33 return Dotiac::DTL::Value->safe($value);
    1301             }
    1302            
    1303            
    1304            
    1305             sub wordcount {
    1306 12     12 1 17 my $value=shift;
    1307 12         32 $value=$value->repr;
    1308 12         106 return Dotiac::DTL::Value->safe(scalar( ()=$value=~m/\S+/g));
    1309             }
    1310            
    1311             sub wordwrap {
    1312 4     4 1 6 my $val=shift;
    1313 4         15 my @value = split /(\s+)/,$val->repr;
    1314 4         12 my $len=shift;
    1315 4 50 33     17 if ($len and $len->number) {
    1316 4         13 $len=int($len->content);
    1317             }
    1318             else {
    1319 0         0 $len=0;
    1320             }
    1321 4 50       12 $len=80 unless $len;
    1322 4         7 my $line=shift @value;
    1323 4         5 my $ret="";
    1324 4         10 while (my $space=shift(@value)) {
    1325 20         23 my $word=shift(@value);
    1326 20 50       42 $word="" unless $word;
    1327 20 100       41 if (CORE::length($line.$space.$word) > $len) {
    1328 16         20 $ret.=$line."\n";
    1329 16         41 $line=$word;
    1330             }
    1331             else {
    1332 4         13 $line.=$space.$word;
    1333             }
    1334             }
    1335 4         6 $ret.=$line;
    1336 4         11 return $val->set($ret);
    1337             }
    1338            
    1339            
    1340            
    1341             sub yesno {
    1342 48     48 1 56 my $value=shift;
    1343 48         54 my $yes=shift;
    1344 48 100       87 if (@_) {
    1345 24         28 my $no=shift;
    1346 24         24 my $undef=shift;
    1347 24 50       45 $yes=Dotiac::DTL::Value->safe("") unless $yes;
    1348 24 50       41 $no=Dotiac::DTL::Value->safe("") unless $no;
    1349 24 100       41 $undef=$no unless $undef;
    1350 24 100       54 return $yes if $value->true;
    1351 16 100       41 return $undef if $value->undef;
    1352 8         22 return $no;
    1353             }
    1354 24 50       42 if ($yes) {
    1355 24         61 $yes=$yes->string();
    1356             }
    1357             else {
    1358 0         0 $yes="";
    1359             }
    1360 24         66 my ($y,$no,$undef) = split /,/,$yes,3;
    1361 24 50       51 $no="" unless $no;
    1362 24 100       36 $undef=$no unless $undef;
    1363 24 100       66 return Dotiac::DTL::Value->safe($y) if $value->true;
    1364 16 100       38 return Dotiac::DTL::Value->safe($undef) if $value->undef;
    1365 8         25 return Dotiac::DTL::Value->safe($no);
    1366             }
    1367            
    1368            
    1369             =head1 SEE ALSO
    1370            
    1371             L, L
    1372            
    1373             =cut
    1374             1;
    1375            
    1376             __END__