File Coverage

blib/lib/Text/Template/Simple/Caller.pm
Criterion Covered Total %
statement 108 109 99.0
branch 16 26 61.5
condition 7 11 63.6
subroutine 22 22 100.0
pod 1 1 100.0
total 154 169 91.1


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