File Coverage

blib/lib/Text/Template/Simple/Caller.pm
Criterion Covered Total %
statement 107 108 99.0
branch 16 26 61.5
condition 7 11 63.6
subroutine 22 22 100.0
pod 1 1 100.0
total 153 168 91.0


line stmt bran cond sub pod time code
1             ## no critic (ProhibitUnusedPrivateSubroutines)
2             package Text::Template::Simple::Caller;
3 62     62   431 use strict;
  62         125  
  62         6561  
4 62     62   439 use warnings;
  62         604  
  62         2420  
5              
6 62     62   3057 use constant PACKAGE => 0;
  62         547  
  62         5160  
7 62     62   2505 use constant FILENAME => 1;
  62         15859  
  62         75548  
8 62     62   969 use constant LINE => 2;
  62         126  
  62         8120  
9 62     62   329 use constant SUBROUTINE => 3;
  62         1429  
  62         6040  
10 62     62   591 use constant HASARGS => 4;
  62         117  
  62         8325  
11 62     62   361 use constant WANTARRAY => 5;
  62         144  
  62         3082  
12 62     62   860 use constant EVALTEXT => 6;
  62         120  
  62         4439  
13 62     62   329 use constant IS_REQUIRE => 7;
  62         191  
  62         4647  
14 62     62   3135 use constant HINTS => 8;
  62         122  
  62         3979  
15 62     62   2049 use constant BITMASK => 9;
  62         127  
  62         7036  
16              
17 62     62   53492 use Text::Template::Simple::Util qw( ishref fatal );
  62         186  
  62         6778  
18 62     62   592 use Text::Template::Simple::Constants qw( EMPTY_STRING );
  62         125  
  62         102920  
19              
20             our $VERSION = '0.86';
21              
22             sub stack {
23 8     8 1 16 my $self = shift;
24 8   50     25 my $opt = shift || {};
25 8 50       28 fatal('tts.caller.stack.hash') if ! ishref($opt);
26 8   50     32 my $frame = $opt->{frame} || 0;
27 8   50     27 my $type = $opt->{type} || EMPTY_STRING;
28 8         14 my(@callers, $context);
29              
30 8         113 TRACE: while ( my @c = caller ++$frame ) {
31              
32 32         76 INITIALIZE: foreach my $id ( 0 .. $#c ) {
33 352 100       569 next INITIALIZE if $id == WANTARRAY; # can be undef
34 320   100     821 $c[$id] ||= EMPTY_STRING;
35             }
36              
37 32 50       103 $context = defined $c[WANTARRAY] ? ( $c[WANTARRAY] ? 'LIST' : 'SCALAR' )
    50          
38             : 'VOID'
39             ;
40              
41 32 50       541 push @callers,
42             {
43             class => $c[PACKAGE ],
44             file => $c[FILENAME ],
45             line => $c[LINE ],
46             sub => $c[SUBROUTINE],
47             context => $context,
48             isreq => $c[IS_REQUIRE],
49             hasargs => $c[HASARGS ] ? 'YES' : 'NO',
50             evaltext => $c[EVALTEXT ],
51             hints => $c[HINTS ],
52             bitmask => $c[BITMASK ],
53             };
54              
55             }
56              
57 8 50       25 return if ! @callers; # no one called us?
58 8 50       31 return reverse @callers if ! $type;
59              
60 8 50       90 if ( $self->can( my $method = '_' . $type ) ) {
61 8         37 return $self->$method( $opt, \@callers );
62             }
63              
64 0         0 return fatal('tts.caller.stack.type', $type);
65             }
66              
67             sub _string {
68 4     4   7 my $self = shift;
69 4         7 my $opt = shift;
70 4         8 my $callers = shift;
71 4         5 my $is_html = shift;
72              
73 4 50       25 my $name = $opt->{name} ? "FOR $opt->{name} " : EMPTY_STRING;
74 4         12 my $rv = qq{[ DUMPING CALLER STACK $name]\n\n};
75              
76 4         8 foreach my $c ( reverse @{$callers} ) {
  4         10  
77 16         90 $rv .= sprintf qq{%s %s() at %s line %s\n},
78             $c->{context},
79             $c->{sub},
80             $c->{file},
81             $c->{line};
82             }
83              
84 4 100       23 $rv = "<!-- $rv -->" if $is_html;
85 4         71 return $rv;
86             }
87              
88             sub _html_comment {
89 2     2   7 my($self, @args) = @_;
90 2         12 return $self->_string( @args, 'add html comment' );
91             }
92              
93             sub _html_table {
94 2     2   5 my $self = shift;
95 2         6 my $opt = shift;
96 2         4397 my $callers = shift;
97 2         38 my $rv = EMPTY_STRING;
98              
99 2         8 foreach my $c ( reverse @{ $callers } ) {
  2         14  
100 8         35 $self->_html_table_blank_check( $c ); # modifies in place
101 8         26 $rv .= $self->_html_table_row( $c )
102             }
103              
104 2         14 return $self->_html_table_wrap( $rv );
105             }
106              
107             sub _html_table_wrap {
108 2     2   5 my($self, $content) = @_;
109 2         78 return <<"HTML";
110             <div id="ttsc-wrapper">
111             <table border = "1"
112             cellpadding = "1"
113             cellspacing = "2"
114             id = "ttsc-dump"
115             >
116             <tr>
117             <td class="ttsc-title">CONTEXT</td>
118             <td class="ttsc-title">SUB</td>
119             <td class="ttsc-title">LINE</td>
120             <td class="ttsc-title">FILE</td>
121             <td class="ttsc-title">HASARGS</td>
122             <td class="ttsc-title">IS_REQUIRE</td>
123             <td class="ttsc-title">EVALTEXT</td>
124             <td class="ttsc-title">HINTS</td>
125             <td class="ttsc-title">BITMASK</td>
126             </tr>
127             $content
128             </table>
129             </div>
130             HTML
131             }
132              
133             sub _html_table_row {
134 8     8   18 my($self,$c) = @_;
135 8         91 return <<"HTML";
136             <tr>
137             <td class="ttsc-value">$c->{context}</td>
138             <td class="ttsc-value">$c->{sub}</td>
139             <td class="ttsc-value">$c->{line}</td>
140             <td class="ttsc-value">$c->{file}</td>
141             <td class="ttsc-value">$c->{hasargs}</td>
142             <td class="ttsc-value">$c->{isreq}</td>
143             <td class="ttsc-value">$c->{evaltext}</td>
144             <td class="ttsc-value">$c->{hints}</td>
145             <td class="ttsc-value">$c->{bitmask}</td>
146             </tr>
147             HTML
148             }
149              
150             sub _html_table_blank_check {
151 8     8   14 my $self = shift;
152 8         15 my $struct = shift;
153 8         13 foreach my $id ( keys %{ $struct }) {
  8         46  
154 80 100 66     445 if ( not defined $struct->{ $id } or $struct->{ $id } eq EMPTY_STRING ) {
155 16         76 $struct->{ $id } = '&#160;';
156             }
157             }
158 8         38 return;
159             }
160              
161             sub _text_table {
162 2     2   6 my $self = shift;
163 2         4 my $opt = shift;
164 2         4 my $callers = shift;
165 2         6 my $ok = eval { require Text::Table; 1; };
  2         11  
  2         5  
166 2 50       12 fatal('tts.caller._text_table.module', $@) if ! $ok;
167              
168 2         20 my $table = Text::Table->new( qw(
169             | CONTEXT | SUB | LINE | FILE | HASARGS
170             | IS_REQUIRE | EVALTEXT | HINTS | BITMASK |
171             ));
172              
173 2         8749 my $pipe = q{|};
174 2         5 foreach my $c ( reverse @{$callers} ) {
  2         6  
175 8         976 $table->load(
176             [
177             $pipe, $c->{context},
178             $pipe, $c->{sub},
179             $pipe, $c->{line},
180             $pipe, $c->{file},
181             $pipe, $c->{hasargs},
182             $pipe, $c->{isreq},
183             $pipe, $c->{evaltext},
184             $pipe, $c->{hints},
185             $pipe, $c->{bitmask},
186             $pipe
187             ],
188             );
189             }
190              
191 2 50       309 my $name = $opt->{name} ? "FOR $opt->{name} " : EMPTY_STRING;
192 2         7 my $top = qq{| DUMPING CALLER STACK $name |\n};
193              
194 2         22 my $rv = qq{\n} . ( q{-} x (length($top) - 1) ) . qq{\n} . $top
195             . $table->rule( qw( - + ) )
196             . $table->title
197             . $table->rule( qw( - + ) )
198             . $table->body
199             . $table->rule( qw( - + ) )
200             ;
201              
202 2         91369 return $rv;
203             }
204              
205             1;
206              
207             __END__
208              
209             =head1 NAME
210              
211             Text::Template::Simple::Caller - Caller stack tracer
212              
213             =head1 SYNOPSIS
214              
215             use strict;
216             use Text::Template::Simple::Caller;
217             x();
218             sub x { y() }
219             sub y { z() }
220             sub z { print Text::Template::Simple::Caller->stack }
221              
222             =head1 DESCRIPTION
223              
224             This document describes version C<0.86> of C<Text::Template::Simple::Caller>
225             released on C<5 March 2012>.
226              
227             Caller stack tracer for Text::Template::Simple. This module is not used
228             directly inside templates. You must use the global template function
229             instead. See L<Text::Template::Simple::Dummy> for usage from the templates.
230              
231             =head1 METHODS
232              
233             =head2 stack
234              
235             Class method. Accepts parameters as a single hashref:
236              
237             my $dump = Text::Template::Simple::Caller->stack(\%opts);
238              
239             =head3 frame
240              
241             Integer. Defines how many call frames to go back. Default is zero (full list).
242              
243             =head3 type
244              
245             Defines the dump type. Available options are:
246              
247             =over 4
248              
249             =item string
250              
251             A simple text dump.
252              
253             =item html_comment
254              
255             Same as string, but the output wrapped with HTML comment codes:
256              
257             <!-- [DUMP] -->
258              
259             =item html_table
260              
261             Returns the dump as a HTML table.
262              
263             =item text_table
264              
265             Uses the optional module C<Text::Table> to format the dump.
266              
267             =back
268              
269             =head1 AUTHOR
270              
271             Burak Gursoy <burak@cpan.org>.
272              
273             =head1 COPYRIGHT
274              
275             Copyright 2004 - 2012 Burak Gursoy. All rights reserved.
276              
277             =head1 LICENSE
278              
279             This library is free software; you can redistribute it and/or modify
280             it under the same terms as Perl itself, either Perl version 5.12.3 or,
281             at your option, any later version of Perl 5 you may have available.
282              
283             =cut