source: trunk/lib/OpenGuides.pm @ 551

Last change on this file since 551 was 551, checked in by Dominic Hargreaves, 17 years ago

Release 0.44.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.8 KB
Line 
1package OpenGuides;
2use strict;
3
4use Carp "croak";
5use CGI;
6use CGI::Wiki::Plugin::Diff;
7use CGI::Wiki::Plugin::Locator::UK;
8use OpenGuides::CGI;
9use OpenGuides::Template;
10use OpenGuides::Utils;
11use Time::Piece;
12use URI::Escape;
13
14use vars qw( $VERSION );
15
16$VERSION = '0.44';
17
18=head1 NAME
19
20OpenGuides - A complete web application for managing a collaboratively-written guide to a city or town.
21
22=head1 DESCRIPTION
23
24The OpenGuides software provides the framework for a collaboratively-written
25city guide.  It is similar to a wiki but provides somewhat more structured
26data storage allowing you to annotate wiki pages with information such as
27category, location, and much more.  It provides searching facilities
28including "find me everything within a certain distance of this place".
29Every page includes a link to a machine-readable (RDF) version of the page.
30
31=head1 METHODS
32
33=over
34
35=item B<new>
36
37  my $guide = OpenGuides->new( config => $config );
38
39=cut
40
41sub new {
42    my ($class, %args) = @_;
43    my $self = {};
44    bless $self, $class;
45    my $wiki = OpenGuides::Utils->make_wiki_object( config => $args{config} );
46    $self->{wiki} = $wiki;
47    $self->{config} = $args{config};
48    my $locator = CGI::Wiki::Plugin::Locator::UK->new;
49    $wiki->register_plugin( plugin => $locator );
50    $self->{locator} = $locator;
51    my $differ = CGI::Wiki::Plugin::Diff->new;
52    $wiki->register_plugin( plugin => $differ );
53    $self->{differ} = $differ;
54    return $self;
55}
56
57=item B<wiki>
58
59An accessor, returns the underlying L<CGI::Wiki> object.
60
61=cut
62
63sub wiki {
64    my $self = shift;
65    return $self->{wiki};
66}
67
68=item B<config>
69
70An accessor, returns the underlying L<Config::Tiny> object.
71
72=cut
73
74sub config {
75    my $self = shift;
76    return $self->{config};
77}
78
79=item B<locator>
80
81An accessor, returns the underlying L<CGI::Wiki::Plugin::Locator::UK> object.
82
83=cut
84
85sub locator {
86    my $self = shift;
87    return $self->{locator};
88}
89
90=item B<differ>
91
92An accessor, returns the underlying L<CGI::Wiki::Plugin::Diff> object.
93
94=cut
95
96sub differ {
97    my $self = shift;
98    return $self->{differ};
99}
100
101=item B<display_node>
102
103  # Print node to STDOUT.
104  $guide->display_node(
105                        id      => "Calthorpe Arms",
106                        version => 2,
107                      );
108
109  # Or return output as a string (useful for writing tests).
110  $guide->display_node(
111                        id            => "Calthorpe Arms",
112                        return_output => 1,
113                      );
114
115  # Or return the hash of variables that will be passed to the template
116  # (not including those set additionally by OpenGuides::Template).
117  $guide->display_node(
118                        id             => "Calthorpe Arms",
119                        return_tt_vars => 1,
120                      );
121
122If C<version> is omitted then the latest version will be displayed.
123
124=cut
125
126sub display_node {
127    my ($self, %args) = @_;
128    my $return_output = $args{return_output} || 0;
129    my $version = $args{version};
130    my $id = $args{id} || $self->config->{_}->{home_name};
131    my $wiki = $self->wiki;
132    my $config = $self->config;
133
134    my %tt_vars;
135
136    if ( $id =~ /^(Category|Locale) (.*)$/ ) {
137        my $type = $1;
138        $tt_vars{is_indexable_node} = 1;
139        $tt_vars{index_type} = lc($type);
140        $tt_vars{index_value} = $2;
141        $tt_vars{"rss_".lc($type)."_url"} =
142                           $config->{_}{script_name} . "?action=rss;"
143                           . lc($type) . "=" . lc(CGI->escape($2));
144    }
145
146    my %current_data = $wiki->retrieve_node( $id );
147    my $current_version = $current_data{version};
148    undef $version if ($version && $version == $current_version);
149    my %criteria = ( name => $id );
150    $criteria{version} = $version if $version;#retrieve_node default is current
151
152    my %node_data = $wiki->retrieve_node( %criteria );
153    my $raw = $node_data{content};
154    if ( $raw =~ /^#REDIRECT\s+(.+?)\s*$/ ) {
155        my $redirect = $1;
156        # Strip off enclosing [[ ]] in case this is an extended link.
157        $redirect =~ s/^\[\[//;
158        $redirect =~ s/\]\]\s*$//;
159        # See if this is a valid node, if not then just show the page as-is.
160        if ( $wiki->node_exists($redirect) ) {
161            my $output = $self->redirect_to_node($redirect);
162            return $output if $return_output;
163            print $output;
164            exit 0;
165        }
166    }
167    my $content    = $wiki->format($raw);
168    my $modified   = $node_data{last_modified};
169    my %metadata   = %{$node_data{metadata}};
170
171    my %metadata_vars = OpenGuides::Template->extract_metadata_vars(
172                            wiki     => $wiki,
173                            config   => $config,
174                            metadata => $node_data{metadata} );
175
176    %tt_vars = (
177                 %tt_vars,
178                 %metadata_vars,
179                 content       => $content,
180                 last_modified => $modified,
181                 version       => $node_data{version},
182                 node          => $id,
183                 language      => $config->{_}->{default_language},
184               );
185
186
187    # We've undef'ed $version above if this is the current version.
188    $tt_vars{current} = 1 unless $version;
189
190    if ($id eq "RecentChanges") {
191        my $minor_edits = $self->get_cookie( "show_minor_edits_in_rc" );
192        my %recent_changes;
193        my $q = CGI->new;
194        my $since = $q->param("since");
195        if ( $since ) {
196            $tt_vars{since} = $since;
197            my $t = localtime($since); # overloaded by Time::Piece
198            $tt_vars{since_string} = $t->strftime;
199            my %criteria = ( since => $since );
200            $criteria{metadata_was} = { edit_type => "Normal edit" }
201              unless $minor_edits;
202            my @rc = $self->{wiki}->list_recent_changes( %criteria );
203
204            @rc = map {
205                {
206                  name        => CGI->escapeHTML($_->{name}),
207                  last_modified => CGI->escapeHTML($_->{last_modified}),
208                  version     => CGI->escapeHTML($_->{version}),
209                  comment     => CGI->escapeHTML($_->{metadata}{comment}[0]),
210                  username    => CGI->escapeHTML($_->{metadata}{username}[0]),
211                  host        => CGI->escapeHTML($_->{metadata}{host}[0]),
212                  username_param => CGI->escape($_->{metadata}{username}[0]),
213                  edit_type   => CGI->escapeHTML($_->{metadata}{edit_type}[0]),
214                  url         => "$config->{_}->{script_name}?"
215          . CGI->escape($wiki->formatter->node_name_to_node_param($_->{name})),
216                }
217                       } @rc;
218            if ( scalar @rc ) {
219                $recent_changes{since} = \@rc;
220            }
221        } else {
222            for my $days ( [0, 1], [1, 7], [7, 14], [14, 30] ) {
223                my %criteria = ( between_days => $days );
224                $criteria{metadata_was} = { edit_type => "Normal edit" }
225                  unless $minor_edits;
226                my @rc = $self->{wiki}->list_recent_changes( %criteria );
227
228                @rc = map {
229                {
230                  name        => CGI->escapeHTML($_->{name}),
231                  last_modified => CGI->escapeHTML($_->{last_modified}),
232                  version     => CGI->escapeHTML($_->{version}),
233                  comment     => CGI->escapeHTML($_->{metadata}{comment}[0]),
234                  username    => CGI->escapeHTML($_->{metadata}{username}[0]),
235                  host        => CGI->escapeHTML($_->{metadata}{host}[0]),
236                  username_param => CGI->escape($_->{metadata}{username}[0]),
237                  edit_type   => CGI->escapeHTML($_->{metadata}{edit_type}[0]),
238                  url         => "$config->{_}->{script_name}?"
239          . CGI->escape($wiki->formatter->node_name_to_node_param($_->{name})),
240                }
241                           } @rc;
242                if ( scalar @rc ) {
243                    $recent_changes{$days->[1]} = \@rc;
244                }
245            }
246        }
247        $tt_vars{recent_changes} = \%recent_changes;
248        my %processing_args = (
249                                id            => $id,
250                                template      => "recent_changes.tt",
251                                tt_vars       => \%tt_vars,
252                               );
253        if ( !$since && $self->get_cookie("track_recent_changes_views") ) {
254            my $cookie =
255               OpenGuides::CGI->make_recent_changes_cookie(config => $config );
256            $processing_args{cookies} = $cookie;
257            $tt_vars{last_viewed} = OpenGuides::CGI->get_last_recent_changes_visit_from_cookie( config => $config );
258        }
259        return %tt_vars if $args{return_tt_vars};
260        my $output = $self->process_template( %processing_args );
261        return $output if $return_output;
262        print $output;
263    } elsif ( $id eq $self->config->{_}->{home_name} ) {
264        my @recent = $wiki->list_recent_changes(
265            last_n_changes => 10,
266            metadata_was   => { edit_type => "Normal edit" },
267        );
268        @recent = map { {name          => CGI->escapeHTML($_->{name}),
269                         last_modified => CGI->escapeHTML($_->{last_modified}),
270                         comment       => CGI->escapeHTML($_->{metadata}{comment}[0]),
271                         username      => CGI->escapeHTML($_->{metadata}{username}[0]),
272                         url           => "$config->{_}->{script_name}?"
273          . CGI->escape($wiki->formatter->node_name_to_node_param($_->{name})) }
274                       } @recent;
275        $tt_vars{recent_changes} = \@recent;
276        return %tt_vars if $args{return_tt_vars};
277        my $output = $self->process_template(
278                                              id            => $id,
279                                              template      => "home_node.tt",
280                                              tt_vars       => \%tt_vars,
281                                            );
282        return $output if $return_output;
283        print $output;
284    } else {
285        return %tt_vars if $args{return_tt_vars};
286        my $output = $self->process_template(
287                                              id            => $id,
288                                              template      => "node.tt",
289                                              tt_vars       => \%tt_vars,
290                                            );
291        return $output if $return_output;
292        print $output;
293    }
294}
295
296=item B<display_diffs>
297
298  $guide->display_diffs(
299                         id            => "Home Page",
300                         version       => 6,
301                         other_version => 5,
302                       );
303
304  # Or return output as a string (useful for writing tests).
305  my $output = $guide->display_diffs(
306                                      id            => "Home Page",
307                                      version       => 6,
308                                      other_version => 5,
309                                      return_output => 1,
310                                    );
311
312  # Or return the hash of variables that will be passed to the template
313  # (not including those set additionally by OpenGuides::Template).
314  my %vars = $guide->display_diffs(
315                                    id             => "Home Page",
316                                    version        => 6,
317                                    other_version  => 5,
318                                    return_tt_vars => 1,
319                                  );
320
321=cut
322
323sub display_diffs {
324    my ($self, %args) = @_;
325    my %diff_vars = $self->differ->differences(
326                                        node          => $args{id},
327                                        left_version  => $args{version},
328                                        right_version => $args{other_version},
329                                              );
330    $diff_vars{not_deletable} = 1;
331    $diff_vars{not_editable} = 1;
332    $diff_vars{deter_robots} = 1;
333    return %diff_vars if $args{return_tt_vars};
334    my $output = $self->process_template(
335                                          id       => $args{id},
336                                          template => "differences.tt",
337                                          tt_vars  => \%diff_vars
338                                        );
339    return $output if $args{return_output};
340    print $output;
341}
342
343=item B<find_within_distance>
344
345  $guide->find_within_distance(
346                                id => $node,
347                                metres => $q->param("distance_in_metres")
348                              );
349
350=cut
351
352sub find_within_distance {
353    my ($self, %args) = @_;
354    my $node = $args{id};
355    my $metres = $args{metres};
356    my %data = $self->wiki->retrieve_node( $node );
357    my $lat = $data{metadata}{latitude}[0];
358    my $long = $data{metadata}{longitude}[0];
359    my $script_url = $self->config->{_}{script_url};
360    print CGI->redirect( $script_url . "supersearch.cgi?lat=$lat;long=$long;distance_in_metres=$metres" );
361}
362
363=item B<show_index>
364
365  $guide->show_index(
366                      type   => "category",
367                      value  => "pubs",
368                    );
369
370  # RDF version.
371  $guide->show_index(
372                      type   => "locale",
373                      value  => "Holborn",
374                      format => "rdf",
375                    );
376
377  # Or return output as a string (useful for writing tests).
378  $guide->show_index(
379                      type          => "category",
380                      value         => "pubs",
381                      return_output => 1,
382                    );
383
384=cut
385
386sub show_index {
387    my ($self, %args) = @_;
388    my $wiki = $self->wiki;
389    my $formatter = $wiki->formatter;
390    my %tt_vars;
391    my @selnodes;
392
393    if ( $args{type} and $args{value} ) {
394        if ( $args{type} eq "fuzzy_title_match" ) {
395            my %finds = $wiki->fuzzy_title_match( $args{value} );
396            @selnodes = sort { $finds{$a} <=> $finds{$b} } keys %finds;
397            $tt_vars{criterion} = {
398                type  => $args{type},  # for RDF version
399                value => $args{value}, # for RDF version
400                name  => CGI->escapeHTML("Fuzzy Title Match on '$args{value}'"),
401                not_editable => 1
402            };
403        } else {
404            @selnodes = $wiki->list_nodes_by_metadata(
405                metadata_type  => $args{type},
406                metadata_value => $args{value},
407                ignore_case    => 1,
408            );
409            my $name = ucfirst($args{type}) . " $args{value}" ;
410            my $url = $self->config->{_}->{script_name}
411                      . "?"
412                      . ucfirst( $args{type} )
413                      . "_"
414                      . uri_escape(
415                              $formatter->node_name_to_node_param($args{value})
416                                  );
417            $tt_vars{criterion} = {
418                type  => $args{type},
419                value => $args{value}, # for RDF version
420                name  => CGI->escapeHTML( $name ),
421                url   => $url,
422                not_editable => 1
423            };
424        }
425    } else {
426        @selnodes = $wiki->list_all_nodes();
427    }
428
429    my @nodes = map { { name      => $_,
430                        node_data => { $wiki->retrieve_node( name => $_ ) },
431                        param     => $formatter->node_name_to_node_param($_) }
432                    } sort @selnodes;
433
434    $tt_vars{nodes} = \@nodes;
435
436    my ($template, %conf);
437
438    if ( $args{format} and $args{format} eq "rdf" ) {
439        $template = "rdf_index.tt";
440        $conf{content_type} = "text/plain";
441    } else {
442        $template = "site_index.tt";
443    }
444
445    %conf = (
446              %conf,
447              node        => "$args{type} index", # KLUDGE
448              template    => $template,
449              tt_vars     => \%tt_vars,
450    );
451
452    my $output = $self->process_template( %conf );
453    return $output if $args{return_output};
454    print $output;
455}
456
457=item B<list_all_versions>
458
459  $guide->list_all_versions ( id => "Home Page" );
460
461  # Or return output as a string (useful for writing tests).
462  $guide->list_all_versions (
463                              id            => "Home Page",
464                              return_output => 1,
465                            );
466
467  # Or return the hash of variables that will be passed to the template
468  # (not including those set additionally by OpenGuides::Template).
469  $guide->list_all_versions (
470                              id             => "Home Page",
471                              return_tt_vars => 1,
472                            );
473
474=cut
475
476sub list_all_versions {
477    my ($self, %args) = @_;
478    my $return_output = $args{return_output} || 0;
479    my $node = $args{id};
480    my %curr_data = $self->wiki->retrieve_node($node);
481    my $curr_version = $curr_data{version};
482    croak "This is the first version" unless $curr_version > 1;
483    my @history;
484    for my $version ( 1 .. $curr_version ) {
485        my %node_data = $self->wiki->retrieve_node( name    => $node,
486                                                    version => $version );
487        # $node_data{version} will be zero if this version was deleted.
488        push @history, {
489            version  => CGI->escapeHTML( $version ),
490            modified => CGI->escapeHTML( $node_data{last_modified} ),
491            username => CGI->escapeHTML( $node_data{metadata}{username}[0] ),
492            comment  => CGI->escapeHTML( $node_data{metadata}{comment}[0] ),
493                       } if $node_data{version};
494    }
495    @history = reverse @history;
496    my %tt_vars = ( node          => $node,
497                    version       => $curr_version,
498                    not_deletable => 1,
499                    not_editable  => 1,
500                    deter_robots  => 1,
501                    history       => \@history );
502    return %tt_vars if $args{return_tt_vars};
503    my $output = $self->process_template(
504                                          id       => $node,
505                                          template => "node_history.tt",
506                                          tt_vars  => \%tt_vars,
507                                        );
508    return $output if $return_output;
509    print $output;
510}
511
512=item B<display_rss>
513
514  # Last ten non-minor edits to Hammersmith pages.
515  $guide->display_rss(
516                       items              => 10,
517                       ignore_minor_edits => 1,
518                       locale             => "Hammersmith",
519                     );
520
521  # All edits bob has made to pub pages in the last week.
522  $guide->display_rss(
523                       days     => 7,
524                       username => "bob",
525                       category => "Pubs",
526                     );
527
528As with other methods, the C<return_output> parameter can be used to
529return the output instead of printing it to STDOUT.
530
531=cut
532
533sub display_rss {
534    my ($self, %args) = @_;
535    use Data::Dumper;warn Dumper \%args;
536    my $return_output = $args{return_output} ? 1 : 0;
537
538    my $items = $args{items} || "";
539    my $days  = $args{days}  || "";
540    my $ignore_minor_edits = $args{ignore_minor_edits} ? 1 : 0;
541    my $username = $args{username} || "";
542    my $category = $args{category} || "";
543    my $locale   = $args{locale}   || "";
544    my %criteria = (
545                     items              => $items,
546                     days               => $days,
547                     ignore_minor_edits => $ignore_minor_edits,
548                   );
549    my %filter;
550    $filter{username} = $username if $username;
551    $filter{category} = $category if $category;
552    $filter{locale}   = $locale   if $locale;
553    if ( scalar keys %filter ) {
554        $criteria{filter_on_metadata} = \%filter;
555    }
556
557    my $rdf_writer = OpenGuides::RDF->new( wiki   => $self->wiki,
558                                           config => $self->config );
559    my $output = "Content-type: text/plain\n\n";
560    $output .= $rdf_writer->make_recentchanges_rss( %criteria );
561    return $output if $return_output;
562    print $output;
563}
564
565=item B<commit_node>
566
567  $guide->commit_node(
568                       id      => $node,
569                       cgi_obj => $q,
570                     );
571
572As with other methods, parameters C<return_tt_vars> and
573C<return_output> can be used to return these things instead of
574printing the output to STDOUT.
575
576=cut
577
578sub commit_node {
579    my ($self, %args) = @_;
580    my $node = $args{id};
581    my $q = $args{cgi_obj};
582    my $return_output = $args{return_output};
583    my $wiki = $self->wiki;
584    my $config = $self->config;
585
586    my $content  = $q->param("content");
587    $content =~ s/\r\n/\n/gs;
588    my $checksum = $q->param("checksum");
589
590    my %metadata = OpenGuides::Template->extract_metadata_vars(
591        wiki    => $wiki,
592        config  => $config,
593        cgi_obj => $q
594    );
595
596    $metadata{opening_hours_text} = $q->param("hours_text") || "";
597
598    # Pick out the unmunged versions of lat/long if they're set.
599    # (If they're not, it means they weren't munged in the first place.)
600    $metadata{latitude} = delete $metadata{latitude_unmunged}
601        if $metadata{latitude_unmunged};
602    $metadata{longitude} = delete $metadata{longitude_unmunged}
603        if $metadata{longitude_unmunged};
604
605    # Check to make sure all the indexable nodes are created
606    foreach my $type (qw(Category Locale)) {
607        my $lctype = lc($type);
608        foreach my $index (@{$metadata{$lctype}}) {
609            $index =~ s/(.*)/\u$1/;
610            my $node = $type . " " . $index;
611            # Uppercase the node name before checking for existence
612            $node =~ s/ (\S+)/ \u$1/g;
613            unless ( $wiki->node_exists($node) ) {
614                my $category = $type eq "Category" ? "Category" : "Locales";
615                $wiki->write_node( $node,
616                                   "\@INDEX_LINK [[$node]]",
617                                   undef,
618                                   { username => "Auto Create",
619                                     comment  => "Auto created $lctype stub page",
620                                     category => $category
621                                   }
622                );
623            }
624        }
625    }
626       
627    foreach my $var ( qw( username comment edit_type ) ) {
628        $metadata{$var} = $q->param($var) || "";
629    }
630    $metadata{host} = $ENV{REMOTE_ADDR};
631
632    # CGI::Wiki::Plugin::RSS::ModWiki wants "major_change" to be set.
633    $metadata{major_change} = ( $metadata{edit_type} eq "Normal edit" )
634                            ? 1
635                            : 0;
636
637    my $written = $wiki->write_node($node, $content, $checksum, \%metadata );
638
639    if ($written) {
640        my $output = $self->redirect_to_node($node);
641        return $output if $return_output;
642        print $output;
643    } else {
644        my %node_data = $wiki->retrieve_node($node);
645        my %tt_vars = ( checksum       => $node_data{checksum},
646                        new_content    => $content,
647                        stored_content => $node_data{content} );
648        foreach my $mdvar ( keys %metadata ) {
649            if ($mdvar eq "locales") {
650                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{locale};
651                $tt_vars{"new_$mdvar"}    = $metadata{locale};
652            } elsif ($mdvar eq "categories") {
653                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{category};
654                $tt_vars{"new_$mdvar"}    = $metadata{category};
655            } elsif ($mdvar eq "username" or $mdvar eq "comment"
656                      or $mdvar eq "edit_type" ) {
657                $tt_vars{$mdvar} = $metadata{$mdvar};
658            } else {
659                $tt_vars{"stored_$mdvar"} = $node_data{metadata}{$mdvar}[0];
660                $tt_vars{"new_$mdvar"}    = $metadata{$mdvar};
661            }
662        }
663        return %tt_vars if $args{return_tt_vars};
664        my $output = $self->process_template(
665                                              id       => $node,
666                                              template => "edit_conflict.tt",
667                                              tt_vars  => \%tt_vars,
668                                            );
669        return $output if $args{return_output};
670        print $output;
671    }
672}
673
674
675=item B<delete_node>
676
677  $guide->delete_node(
678                       id       => "FAQ",
679                       version  => 15,
680                       password => "beer",
681                     );
682
683C<version> is optional - if it isn't supplied then all versions of the
684node will be deleted; in other words the node will be entirely
685removed.
686
687If C<password> is not supplied then a form for entering the password
688will be displayed.
689
690=cut
691
692sub delete_node {
693    my ($self, %args) = @_;
694    my $node = $args{id} or croak "No node ID supplied for deletion";
695
696    my %tt_vars = (
697                    not_editable  => 1,
698                    not_deletable => 1,
699                    deter_robots  => 1,
700                  );
701    $tt_vars{delete_version} = $args{version} || "";
702
703    my $password = $args{password};
704
705    if ($password) {
706        if ($password ne $self->config->{_}->{admin_pass}) {
707            print $self->process_template(
708                                     id       => $node,
709                                     template => "delete_password_wrong.tt",
710                                     tt_vars  => \%tt_vars,
711                                   );
712        } else {
713            $self->wiki->delete_node(
714                                      name    => $node,
715                                      version => $args{version},
716                                    );
717            # Check whether any versions of this node remain.
718            my %check = $self->wiki->retrieve_node( name => $node );
719            $tt_vars{other_versions_remain} = 1 if $check{version};
720            print $self->process_template(
721                                     id       => $node,
722                                     template => "delete_done.tt",
723                                     tt_vars  => \%tt_vars,
724                                   );
725        }
726    } else {
727        print $self->process_template(
728                                 id       => $node,
729                                 template => "delete_confirm.tt",
730                                 tt_vars  => \%tt_vars,
731                               );
732    }
733}
734
735sub process_template {
736    my ($self, %args) = @_;
737    my %output_conf = ( wiki     => $self->wiki,
738                        config   => $self->config,
739                        node     => $args{id},
740                        template => $args{template},
741                        vars     => $args{tt_vars},
742                        cookies  => $args{cookies},
743    );
744    if ( $args{content_type} ) {
745        $output_conf{content_type} = "";
746        my $output = "Content-Type: $args{content_type}\n\n"
747                     . OpenGuides::Template->output( %output_conf );
748    } else {
749        return OpenGuides::Template->output( %output_conf );
750    }
751}
752
753sub redirect_to_node {
754    my ($self, $node) = @_;
755    my $script_url = $self->config->{_}->{script_url};
756    my $script_name = $self->config->{_}->{script_name};
757    my $formatter = $self->wiki->formatter;
758    my $param = $formatter->node_name_to_node_param( $node );
759    return CGI->redirect( "$script_url$script_name?$param" );
760}
761
762sub get_cookie {
763    my $self = shift;
764    my $config = $self->config;
765    my $pref_name = shift or return "";
766    my %cookie_data = OpenGuides::CGI->get_prefs_from_cookie(config=>$config);
767    return $cookie_data{$pref_name};
768}
769
770
771=back
772
773=head1 BUGS AND CAVEATS
774
775At the moment, the location data uses a United-Kingdom-specific module,
776so the location features might not work so well outside the UK.
777
778=head1 SEE ALSO
779
780=over 4
781
782=item * L<http://london.openguides.org/|The Open Guide to London>, the first and biggest OpenGuides site.
783
784=item * L<http://openguides.org/|The OpenGuides website>, with a list of all live OpenGuides installs.
785
786=item * L<CGI::Wiki>, the Wiki toolkit which does the heavy lifting for OpenGuides
787
788=back
789
790=head1 FEEDBACK
791
792If you have a question, a bug report, or a patch, or you're interested
793in joining the development team, please contact openguides-dev@openguides.org
794(moderated mailing list, will reach all current developers but you'll have
795to wait for your post to be approved) or kake@earth.li (a real person who
796may take a little while to reply to your mail if she's busy).
797
798=head1 AUTHOR
799
800The OpenGuides Project (openguides-dev@openguides.org)
801
802=head1 COPYRIGHT
803
804     Copyright (C) 2003-4 The OpenGuides Project.  All Rights Reserved.
805
806The OpenGuides distribution is free software; you can redistribute it
807and/or modify it under the same terms as Perl itself.
808
809=head1 CREDITS
810
811Programming by Dominic Hargreaves, Earle Martin, Kake Pugh, and Ivor
812Williams.  Testing and bug reporting by Billy Abbott, Jody Belka,
813Kerry Bosworth, Simon Cozens, Cal Henderson, Steve Jolly, and Bob
814Walker (among others).  Much of the Module::Build stuff copied from
815the Siesta project L<http://siesta.unixbeard.net/>
816
817=cut
818
8191;
Note: See TracBrowser for help on using the repository browser.