source: trunk/lib/OpenGuides/Template.pm @ 555

Last change on this file since 555 was 555, checked in by kake, 17 years ago

Fixed bug relating to lat/long representation in dms.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.3 KB
Line 
1package OpenGuides::Template;
2
3use strict;
4use vars qw( $VERSION );
5$VERSION = '0.12';
6
7use Carp qw( croak );
8use CGI; # want to get rid of this and put the burden on the templates
9use Geography::NationalGrid;
10use Geography::NationalGrid::GB;
11use OpenGuides; # for $VERSION for template variable
12use OpenGuides::CGI;
13use Template;
14use URI::Escape;
15
16=head1 NAME
17
18OpenGuides::Template - Do Template Toolkit related stuff for OpenGuides applications.
19
20=head1 DESCRIPTION
21
22Does all the Template Toolkit stuff for OpenGuides.  Distributed and
23installed as part of the OpenGuides project, not intended for
24independent installation.  This documentation is probably only useful
25to OpenGuides developers.
26
27=head1 SYNOPSIS
28
29  use Config::Tiny;
30  use OpenGuides::Utils;
31  use OpenGuides::Template;
32
33  my $config = Config::Tiny->read('wiki.conf');
34  my $wiki = OpenGuides::Utils->make_wiki_object( config => $config );
35
36  print OpenGuides::Template->output( wiki     => $wiki,
37                                      config   => $config,
38                                      template => "node.tt",
39                                      vars     => { foo => "bar" }
40  );
41
42=head1 METHODS
43
44=over 4
45
46=item B<output>
47
48  print OpenGuides::Template->output( wiki         => $wiki,
49                                      config       => $config,
50                                      template     => "node.tt",
51                                      content_type => "text/html",
52                                      cookies      => $cookie,
53                                      vars         => {foo => "bar"}
54  );
55
56Returns everything you need to send to STDOUT, including the
57Content-Type: header. Croaks unless C<template> is supplied.
58
59The variables supplied in C<vars> are passed through to the template
60specified.  Additional Template Toolkit variables are automatically
61set and passed through as well, as described below.  B<Note:>
62variables set in C<vars> will over-ride any variables of the same name
63in the config object or the user cookies.
64
65=over
66
67=item * C<openguides_version>
68
69=item * C<site_name>
70
71=item * C<cgi_url>
72
73=item * C<full_cgi_url>
74
75=item * C<enable_page_deletion> (gets set to true or false - defaults to false)
76
77=item * C<contact_email>
78
79=item * C<stylesheet>
80
81=item * C<home_link>
82
83=item * C<formatting_rules_link> (unless C<omit_formatting_link> is set in user cookie)
84
85=item * C<navbar_on_home_page>
86
87=item * C<home_name>
88
89=back
90
91=over
92
93If C<node> is supplied:
94
95=item * C<node_name>
96
97=item * C<node_param> (the node name escaped for use in URLs)
98
99=back
100
101Content-Type: defaults to C<text/html> and is omitted if the
102C<content_type> arg is explicitly set to the blank string.
103
104=cut
105
106sub output {
107    my ($class, %args) = @_;
108    croak "No template supplied" unless $args{template};
109    my $config = $args{config} or croak "No config supplied";
110    my $template_path = $config->{_}->{template_path};
111    my $custom_template_path = $config->{_}->{custom_template_path} || "";
112    my $tt = Template->new( { INCLUDE_PATH => "$custom_template_path:$template_path" } );
113
114    my $script_name = $config->{_}->{script_name};
115    my $script_url  = $config->{_}->{script_url};
116
117    # Ensure that script_url ends in a '/' - this is done in Build.PL but
118    # we need to allow for people editing the config file by hand later.
119    $script_url .= "/" unless $script_url =~ /\/$/;
120
121    # Check cookie to see if we need to set the formatting_rules_link.
122    my ($formatting_rules_link, $omit_help_links);
123    my $formatting_rules_node = $config->{_}->{formatting_rules_node} ||"";
124    my %cookie_data = OpenGuides::CGI->get_prefs_from_cookie(config=>$config);
125    if ( $cookie_data{omit_help_links} ) {
126        $omit_help_links = 1;
127    } else {
128        if ( $formatting_rules_node ) {
129            $formatting_rules_link = $script_url . $script_name . "?"
130                                   . uri_escape($args{wiki}->formatter->node_name_to_node_param($formatting_rules_node));
131        }
132    }
133
134    my $enable_page_deletion = 0;
135    if ( $config->{_}->{enable_page_deletion}
136         and ( lc($config->{_}->{enable_page_deletion}) eq "y"
137               or $config->{_}->{enable_page_deletion} eq "1" )
138       ) {
139        $enable_page_deletion = 1;
140    }
141
142    my $tt_vars = { site_name             => $config->{_}->{site_name},
143                    cgi_url               => $script_name,
144                    full_cgi_url          => $script_url . $script_name,
145                    contact_email         => $config->{_}->{contact_email},
146                    stylesheet            => $config->{_}->{stylesheet_url},
147                    home_link             => $script_url . $script_name,
148                    home_name             => $config->{_}->{home_name},
149                    navbar_on_home_page   => $config->{_}->{navbar_on_home_page},
150                    omit_help_links       => $omit_help_links,
151                    formatting_rules_link => $formatting_rules_link,
152                    formatting_rules_node => $formatting_rules_node,
153                    openguides_version    => $OpenGuides::VERSION,
154                    enable_page_deletion  => $enable_page_deletion,
155                    language              => $config->{_}->{default_language},
156    };
157
158    if ($args{node}) {
159        $tt_vars->{node_name} = CGI->escapeHTML($args{node});
160        $tt_vars->{node_param} = CGI->escape($args{wiki}->formatter->node_name_to_node_param($args{node}));
161    }
162
163    # Now set further TT variables if explicitly supplied - do this last
164    # as these override auto-set ones.
165    $tt_vars = { %$tt_vars, %{ $args{vars} || {} } };
166
167    my $header = "";
168    unless ( defined $args{content_type} and $args{content_type} eq "" ) {
169        $header = CGI::header( -cookie => $args{cookies} );
170    }
171    my $output;
172    $tt->process( $args{template}, $tt_vars, \$output );
173
174    $output ||= qq(<html><head><title>ERROR</title></head><body><p>
175                   Failed to process template: )
176              . $tt->error
177              . qq(</p></body></html>);
178
179    return $header . $output;
180}
181
182=item B<extract_metadata_vars>
183
184  my %node_data = $wiki->retrieve_node( "Home Page" );
185
186  my %metadata_vars = OpenGuides::Template->extract_metadata_vars(
187                                        wiki     => $wiki,
188                                        config   => $config,
189                                        metadata => $node_data{metadata} );
190
191  # -- or --
192
193  my %metadata_vars = OpenGuides::Template->extract_metadata_vars(
194                                        wiki     => $wiki,
195                                        config   => $config,
196                                        cgi_obj  => $q );
197
198  # -- then --
199
200  print OpenGuides::Template->output( wiki     => $wiki,
201                                      config   => $config,
202                                      template => "node.tt",
203                                      vars     => { foo => "bar",
204                                                    %metadata_vars }
205                                     );
206
207Picks out things like categories, locales, phone number etc from
208EITHER the metadata hash returned by L<CGI::Wiki> OR the query
209parameters in a L<CGI> object, and packages them nicely for passing to
210templates or storing in L<CGI::Wiki> datastore.  If you supply both
211C<metadata> and C<cgi_obj> then C<metadata> will take precedence, but
212don't do that.
213
214=cut
215
216sub extract_metadata_vars {
217    my ($class, %args) = @_;
218    my %metadata = %{$args{metadata} || {} };
219    my $q = $args{cgi_obj};
220    my $formatter = $args{wiki}->formatter;
221    my $config = $args{config};
222    my $script_name = $config->{_}->{script_name};
223
224    # Categories and locales are displayed as links in the page footer.
225    # We return these twice, as eg 'category' being a simple array of
226    # category names, but 'categories' being an array of hashrefs including
227    # a URL too.  This is ick.
228    my (@catlist, @loclist);
229    if ( $args{metadata} ) {
230        @catlist = @{ $metadata{category} || [] };
231        @loclist = @{ $metadata{locale}   || [] };
232    } else {
233        my $categories_text = $q->param('categories');
234        my $locales_text    = $q->param('locales');
235        @catlist = sort split("\r\n", $categories_text);
236        @loclist = sort split("\r\n", $locales_text);
237    }
238
239    my @categories = map { { name => $_,
240                             url  => "$script_name?Category_"
241            . uri_escape($formatter->node_name_to_node_param($_)) } } @catlist;
242
243    my @locales    = map { { name => $_,
244                             url  => "$script_name?Locale_"
245            . uri_escape($formatter->node_name_to_node_param($_)) } } @loclist;
246
247    # The 'website' attribute might contain a URL so we wiki-format it here
248    # rather than just CGI::escapeHTMLing it all in the template.
249    my $website = $args{metadata} ? $metadata{website}[0]
250                                  : $q->param("website");
251    my $formatted_website_text = "";
252    if ( $website ) {
253        $formatted_website_text = $class->format_website_text(
254            formatter => $formatter,
255            text      => $website );
256    }
257
258    my $hours_text = $args{metadata} ? $metadata{opening_hours_text}[0]
259                                     : $q->param("hours_text");
260    my %vars = (
261        categories             => \@categories,
262        locales                => \@locales,
263        category               => \@catlist,
264        locale                 => \@loclist,
265        formatted_website_text => $formatted_website_text,
266        hours_text             => $hours_text
267    );
268
269    if ( $args{metadata} ) {
270        foreach my $var ( qw( phone fax address postcode os_x os_y
271                              latitude longitude map_link website) ) {
272            $vars{$var} = $metadata{$var}[0];
273        }
274    } else {
275        foreach my $var ( qw( phone fax address postcode map_link website) ) {
276            $vars{$var} = $q->param($var);
277        }
278
279        my $os_x = $q->param("os_x");
280        my $os_y = $q->param("os_y");
281        # Trim whitespace - trailing whitespace buggers up the integerification
282        # by postgres and it's an easy mistake to make when typing into a form.
283        $os_x =~ s/\s+//;
284        $os_y =~ s/\s+//;
285        # Work out latitude and longitude for the preview display.
286        if ($os_x and $os_y) {
287            my $point = Geography::NationalGrid::GB->new( Easting  => $os_x,
288                                                          Northing => $os_y );
289            %vars = ( %vars,
290                      latitude  => sprintf("%.6f", $point->latitude),
291                      longitude => sprintf("%.6f", $point->longitude),
292                      os_x      => $os_x,
293                      os_y      => $os_y
294            );
295        }
296    }
297
298    # Check whether we need to munge lat and long.
299    # Store them unmunged as well so commit_node can get hold of them.
300    my %prefs = OpenGuides::CGI->get_prefs_from_cookie( config => $config );
301    if ( $prefs{latlong_traditional} ) {
302        foreach my $var ( qw( latitude longitude ) ) {
303            next unless defined $vars{$var};
304            $vars{$var."_unmunged"} = $vars{$var};
305            $vars{$var} = Geography::NationalGrid->deg2string($vars{$var});
306        }
307    }
308
309    return %vars;
310}
311
312sub format_website_text {
313    my ($class, %args) = @_;
314    my ($formatter, $text) = @args{ qw( formatter text ) };
315    my $formatted = $formatter->format($text);
316
317    # Strip out paragraph markers put in by formatter since we want this
318    # to be a single string to put in a <ul>.
319    $formatted =~ s/<p>//g;
320    $formatted =~ s/<\/p>//g;
321
322    return $formatted;
323}
324
325
326=back
327
328=head1 AUTHOR
329
330The OpenGuides Project (openguides-dev@openguides.org)
331
332=head1 COPYRIGHT
333
334  Copyright (C) 2003 The OpenGuides Project.  All Rights Reserved.
335
336This module is free software; you can redistribute it and/or modify it
337under the same terms as Perl itself.
338
339=cut
340
3411;
Note: See TracBrowser for help on using the repository browser.