/[webpac2]/Webpacus/lib/Webpacus/Controller/Output.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /Webpacus/lib/Webpacus/Controller/Output.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/lib/WebPAC/Output/html.pm revision 1 by dpavlin, Sat Jun 25 20:23:23 2005 UTC Webpacus/lib/Webpacus/Controller/Output.pm revision 342 by dpavlin, Mon Jan 2 18:39:55 2006 UTC
# Line 1  Line 1 
1  package WebPAC::Output::html;  package WebPAC::Output::TT;
2    
3  use warnings;  use warnings;
4  use strict;  use strict;
5    
6    use base qw/WebPAC::Common/;
7    
8    use Template;
9    use List::Util qw/first/;
10    use Data::Dumper;
11    use Encode;
12    
13  =head1 NAME  =head1 NAME
14    
15  WebPAC::Output::html - The great new WebPAC::Output::html!  WebPAC::Output::TT - use Template Toolkit to produce output
16    
17  =head1 VERSION  =head1 VERSION
18    
19  Version 0.01  Version 0.06
20    
21  =cut  =cut
22    
23  our $VERSION = '0.01';  our $VERSION = '0.06';
24    
25  =head1 SYNOPSIS  =head1 SYNOPSIS
26    
27  Quick summary of what the module does.  Produce output using Template Toolkit.
28    
29    =head1 FUNCTIONS
30    
31  Perhaps a little code snippet.  =head2 new
32    
33      use WebPAC::Output::html;  Create new instance.
34    
35      my $foo = WebPAC::Output::html->new();   my $tt = new WebPAC::Output::TT(
36      ...          include_path => '/path/to/conf/output/tt',
37            filters => {
38                    filter_1 => sub { uc(shift) },
39            },
40     );
41    
42  =head1 EXPORT  By default, Template Toolkit will C<EVAL_PERL> if included in templates.
43    
44  A list of functions that can be exported.  You can delete this section  =cut
 if you don't export anything, such as for a purely object-oriented module.  
45    
46  =head1 FUNCTIONS  sub new {
47            my $class = shift;
48            my $self = {@_};
49            bless($self, $class);
50    
51            my $log = $self->_get_logger;
52    
53            # create Template toolkit instance
54            $self->{'tt'} = Template->new(
55                    INCLUDE_PATH => $self->{'include_path'},
56                    FILTERS => $self->{'filter'},
57                    EVAL_PERL => 1,
58            );
59            
60            $log->logdie("can't create TT object: $Template::ERROR") unless ($self->{'tt'});
61    
62            $log->debug("filters defined: ",Dumper($self->{'filter'}));
63    
64            $self ? return $self : return undef;
65    }
66    
67    
68    =head2 apply
69    
70    Create output from in-memory data structure using Template Toolkit template.
71    
72  =head2 function1   my $text = $tt->apply(
73            template => 'text.tt',
74            data => $ds,
75            record_uri => 'database/prefix/mfn',
76     );
77    
78    It also has follwing template toolikit filter routies defined:
79    
80  =cut  =cut
81    
82  sub function1 {  sub apply {
83            my $self = shift;
84    
85            my $args = {@_};
86    
87            my $log = $self->_get_logger();
88    
89            foreach my $a (qw/template data/) {
90                    $log->logconfess("need $a") unless ($args->{$a});
91            }
92    
93    =head3 tt_filter_type
94    
95    filter to return values of specified from $ds, usage from TT template is in form
96    C<d('FieldName','delimiter')>, where C<delimiter> is optional, like this:
97    
98      [% d('Title') %]
99      [% d('Author',', ' %]
100    
101    =cut
102    
103            sub tt_filter_type {
104                    my ($data,$type) = @_;
105                    
106                    die "no data?" unless ($data);
107                    $type ||= 'display';
108    
109                    my $default_delimiter = {
110                            'display' => '&#182;<br/>',
111                            'index' => '\n',
112                    };
113    
114                    return sub {
115    
116                            my ($name,$join) = @_;
117    
118                            die "no data hash" unless ($data->{'data'} && ref($data->{'data'}) eq 'HASH');
119                            # Hm? Should we die here?
120                            return unless ($name);
121    
122                            my $item = $data->{'data'}->{$name} || return;
123    
124                            my $v = $item->{$type} || return;
125    
126                            if (ref($v) eq 'ARRAY') {
127                                    if ($#{$v} == 0) {
128                                            $v = $v->[0];
129                                    } else {
130                                            $join = $default_delimiter->{$type} unless defined($join);
131                                            $v = join($join, @{$v});
132                                    }
133                            } else {
134                                    warn("TT filter $type(): field $name values aren't ARRAY, ignoring");
135                            }
136    
137                            return $v;
138                    }
139            }
140    
141            $args->{'d'} = tt_filter_type($args, 'display');
142            $args->{'display'} = tt_filter_type($args, 'display');
143    
144    =head3 tt_filter_search
145    
146    filter to return links to search, usage in TT:
147    
148      [% search('FieldToDisplay','FieldToSearch','optional delimiter', 'optional_template.tt') %]
149    
150    =cut
151    
152            sub tt_filter_search {
153    
154                    my ($data) = @_;
155    
156                    die "no data?" unless ($data);
157                    
158                    return sub {
159    
160                            my ($display,$search,$delimiter,$template) = @_;
161                            
162                            # default delimiter
163                            $delimiter ||= '&#182;<br/>',
164    
165                            die "no data hash" unless ($data->{'data'} && ref($data->{'data'}) eq 'HASH');
166                            # Hm? Should we die here?
167                            return unless ($display);
168    
169                            my $item = $data->{'data'}->{$display} || return;
170    
171                            return unless($item->{'display'});
172                            if (! $item->{'search'}) {
173                                    warn "error in TT template: field $display didn't insert anything into search, use d('$display') and not search('$display'...)";
174                                    return;
175                            }
176    
177                            my @warn;
178                            foreach my $type (qw/display search/) {
179                                    push @warn, "field $display type $type values aren't ARRAY" unless (ref($item->{$type}) eq 'ARRAY');
180                            }
181    
182                            if (@warn) {
183                                    warn("TT filter search(): " . join(",", @warn) . ", skipping");
184                                    return;
185                            }
186                            my @html;
187    
188                            my $d_el = $#{ $item->{'display'} };
189                            my $s_el = $#{ $item->{'search'} };
190    
191                            # easy, both fields have same number of elements or there is just
192                            # one search and multiple display
193                            if ( $d_el == $s_el || $s_el == 0 ) {
194    
195                                    foreach my $i ( 0 .. $d_el ) {
196    
197                                            my $s;
198                                            if ($s_el > 0) {
199                                                    $s = $item->{'search'}->[$i] || die "can't find value $i for type search in field $search";
200                                            } else {
201                                                    $s = $item->{'search'}->[0];
202                                            }
203                                            #$s =~ s/([^\w.-])/sprintf("%%%02X",ord($1))/eg;
204                                            $s = __quotemeta( $s );
205    
206                                            my $d = $item->{'display'}->[$i] || die "can't find value $i for type display in field $display";
207    
208                                            my $template_arg = '';
209                                            $template_arg = qq{,'$template'} if ($template);
210    
211                                            push @html, qq{<a href="#" onclick="return search_via_link('$search','$s'${template_arg})">$d</a>};
212                                    }
213    
214                                    return join($delimiter, @html);
215                            } else {
216                                    my $html = qq{<div class="notice">WARNING: we should really support if there is $d_el display elements and $s_el search elements, but currently there is no nice way to do so, so we will just display values</div>};
217                                    my $v = $item->{'display'};
218    
219                                    if ($#{$v} == 0) {
220                                            $html .= $v->[0];
221                                    } else {
222                                            $html .= join($delimiter, @{$v});
223                                    }
224                                    return $html;
225                            }
226                    }
227            }
228    
229            $args->{'search'} = tt_filter_search($args);
230    
231    =head3 load_rec
232    
233    Used mostly for onClick events like this:
234    
235      <a href="#" onClick="[% load_rec( record_uri, 'template_name.tt') %]>foo</a>
236    
237    It will automatically do sanity checking and create correct JavaScript code.
238    
239    =cut
240    
241            $args->{'load_rec'} = sub {
242                    my @errors;
243    
244                    my $record_uri = shift or push @errors, "record_uri missing";
245                    my $template = shift or push @errors, "template missing";
246    
247                    if ($record_uri !~ m#^[^/]+/[^/]+/[^/]+$#) {
248                            push @errors, "invalid format of record_uri: $record_uri";
249                    }
250    
251                    if (@errors) {
252                            return "Logger.error('errors in load_rec: " . join(", ", @errors) . "'); return false;";
253                    } else {
254                            return "load_rec('$record_uri','$template'); return false;";
255                    }
256            };
257    
258    =head3 load_template
259    
260    Used to re-submit search request and load results in different template
261    
262      <a href="#" onClick="[% load_template( 'template_name.tt' ) %]">bar</a>
263    
264    =cut
265    
266            $args->{'load_template'} = sub {
267                    my $template = shift or return "Logger.error('load_template missing template name!'); return false;";
268                    return "load_template($template); return false;";
269            };
270    
271            my $out;
272    
273            $self->{'tt'}->process(
274                    $args->{'template'},
275                    $args,
276                    \$out
277            ) || $log->logconfess( "apply can't process template: ", $self->{'tt'}->error() );
278    
279            return $out;
280  }  }
281    
282  =head2 function2  =head2 to_file
283    
284    Create output from in-memory data structure using Template Toolkit template
285    to a file.
286    
287     $tt->to_file(
288            file => 'out.txt',
289            template => 'text.tt',
290            data => $ds
291     );
292    
293  =cut  =cut
294    
295  sub function2 {  sub to_file {
296            my $self = shift;
297    
298            my $args = {@_};
299    
300            my $log = $self->_get_logger();
301    
302            my $file = $args->{'file'} || $log->logconfess("need file name");
303    
304            $log->debug("creating file ",$file);
305    
306            open(my $fh, ">", $file) || $log->logdie("can't open output file '$file': $!");
307            print $fh $self->output(
308                    template => $args->{'template'},
309                    data => $args->{'data'},
310            ) || $log->logdie("print: $!");
311            close($fh) || $log->logdie("close: $!");
312    
313            return 1;
314  }  }
315    
 =head1 AUTHOR  
316    
317  Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>  =head2 __quotemeta
318    
319    Helper to quote JavaScript-friendly characters
320    
321  =head1 BUGS  =cut
322    
323  Please report any bugs or feature requests to  sub __quotemeta {
324  C<bug-webpac-output-html@rt.cpan.org>, or through the web interface at          local $_ = shift;
325  L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=WebPAC>.          $_ = decode('iso-8859-2', $_);
326  I will be notified, and then you'll automatically be notified of progress on  
327  your bug as I make changes.          s<([\x{0080}-\x{fffd}]+)>{sprintf '\u%0*v4X', '\u', $1}ge if ( Encode::is_utf8($_) );
328            {
329                    use bytes;  
330                    s<((?:[^ \x21-\x7E]|(?:\\(?!u)))+)>{sprintf '\x%0*v2X', '\x', $1}ge;
331            }
332    
333            s/\\x09/\\t/g;
334            s/\\x0A/\\n/g;
335            s/\\x0D/\\r/g;
336            s/"/\\"/g;
337            s/\\x5C/\\\\/g;
338    
339  =head1 ACKNOWLEDGEMENTS          return $_;
340    }
341    
342    =head1 AUTHOR
343    
344    Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
345    
346  =head1 COPYRIGHT & LICENSE  =head1 COPYRIGHT & LICENSE
347    
# Line 70  under the same terms as Perl itself. Line 352  under the same terms as Perl itself.
352    
353  =cut  =cut
354    
355  1; # End of WebPAC::Output::html  1; # End of WebPAC::Output::TT

Legend:
Removed from v.1  
changed lines
  Added in v.342

  ViewVC Help
Powered by ViewVC 1.1.26