source: trunk/lib/OpenGuides/JSON.pm @ 1225

Last change on this file since 1225 was 1225, checked in by nick, 13 years ago

Rename functions in json module to be more appropriate

File size: 9.1 KB
Line 
1package OpenGuides::JSON;
2
3use strict;
4
5use vars qw( $VERSION );
6$VERSION = '0.01';
7
8use Wiki::Toolkit::Plugin::JSON;
9use Time::Piece;
10use URI::Escape;
11use Carp 'croak';
12
13sub new {
14    my ( $class, @args ) = @_;
15    my $self = {};
16    bless $self, $class;
17    $self->_init(@args);
18}
19
20sub _init {
21    my ( $self, %args ) = @_;
22
23    my $wiki = $args{wiki};
24
25    unless ( $wiki && UNIVERSAL::isa( $wiki, "Wiki::Toolkit" ) ) {
26        croak "No Wiki::Toolkit object supplied.";
27    }
28    $self->{wiki} = $wiki;
29
30    my $config = $args{config};
31
32    unless ( $config && UNIVERSAL::isa( $config, "OpenGuides::Config" ) ) {
33        croak "No OpenGuides::Config object supplied.";
34    }
35    $self->{config} = $config;
36
37    $self->{make_node_url} = sub {
38        my ( $node_name, $version ) = @_;
39
40        my $config = $self->{config};
41
42        my $node_url = $config->script_url;
43        if ( $config->script_name ) {
44            $node_url .= uri_escape( $config->script_name ) . '?';
45        }
46        $node_url .= 'id=' if defined $version;
47        $node_url .=
48          uri_escape(
49            $self->{wiki}->formatter->node_name_to_node_param($node_name) );
50        $node_url .= ';version=' . uri_escape($version) if defined $version;
51
52        $node_url;
53    };
54    $self->{site_name}        = $config->site_name;
55    $self->{default_city}     = $config->default_city || "";
56    $self->{default_country}  = $config->default_country || "";
57    $self->{site_description} = $config->site_desc || "";
58    $self->{og_version}       = $args{og_version};
59
60    $self;
61}
62
63sub emit_json {
64    my ( $self, %args ) = @_;
65
66    my $node_name = $args{node};
67    my $wiki      = $self->{wiki};
68
69    my %node_data = $wiki->retrieve_node($node_name);
70    my $data      = {};
71    $data->{phone}   = $node_data{metadata}{phone}[0]   || '';
72    $data->{fax}     = $node_data{metadata}{fax}[0]     || '';
73    $data->{website} = $node_data{metadata}{website}[0] || '';
74    $data->{opening_hours_text} = $node_data{metadata}{opening_hours_text}[0]
75      || '';
76    $data->{address}  = $node_data{metadata}{address}[0]  || '';
77    $data->{postcode} = $node_data{metadata}{postcode}[0] || '';
78    $data->{city} = $node_data{metadata}{city}[0] || $self->{default_city};
79    $data->{country} = $node_data{metadata}{country}[0]
80      || $self->{default_country};
81    $data->{latitude}   = $node_data{metadata}{latitude}[0]  || '';
82    $data->{longitude}  = $node_data{metadata}{longitude}[0] || '';
83    $data->{version}    = $node_data{version};
84    $data->{username}   = $node_data{metadata}{username}[0]  || '';
85    $data->{os_x}       = $node_data{metadata}{os_x}[0]      || '';
86    $data->{os_y}       = $node_data{metadata}{os_y}[0]      || '';
87    $data->{categories} = $node_data{metadata}{category}     || [];
88    $data->{locales}    = $node_data{metadata}{locale}       || [];
89    $data->{summary}    = $node_data{metadata}{summary}[0]   || '';
90
91    $data->{timestamp} = $node_data{last_modified};
92
93    # Make a Time::Piece object.
94    my $timestamp_fmt = $Wiki::Toolkit;
95
96    if ( $data->{timestamp} ) {
97        my $time = Time::Piece->strptime( $data->{timestamp}, $timestamp_fmt );
98        $data->{timestamp} = $time->strftime("%Y-%m-%dT%H:%M:%S");
99    }
100
101    $data->{url} = $self->{make_node_url}->( $node_name, $data->{version} );
102    $data->{version_indpt_url} = $self->{make_node_url}->($node_name);
103    return $self->json_maker->make_json($data);
104}
105
106sub json_maker {
107    my $self = shift;
108
109    # OAOO, please.
110    unless ( $self->{json_maker} ) {
111        $self->{json_maker} = Wiki::Toolkit::Plugin::JSON->new(
112            wiki                => $self->{wiki},
113            site_name           => $self->{site_name},
114            site_url            => $self->{config}->script_url,
115            site_description    => $self->{site_description},
116            make_node_url       => $self->{make_node_url},
117            recent_changes_link => $self->{config}->script_url . '?action=rc',
118            software_name       => 'OpenGuides',
119            software_homepage   => 'http://openguides.org/',
120            software_version    => $self->{og_version},
121        );
122    }
123
124    return $self->{json_maker};
125}
126
127sub make_recentchanges_json {
128    my ( $self, %args ) = @_;
129
130    $self->json_maker->recent_changes(%args);
131}
132
133sub json_timestamp {
134    my ( $self, %args ) = @_;
135
136    # RSS and JSON timestamps are close, I think...
137    $self->json_maker->rss_timestamp(%args);
138}
139
140=head1 NAME
141
142OpenGuides::JSON - An OpenGuides plugin to output JSON.
143
144=head1 DESCRIPTION
145
146Does all the JSON stuff for OpenGuides.  Distributed and installed as
147part of the OpenGuides project, not intended for independent
148installation.  This documentation is probably only useful to OpenGuides
149developers.
150
151=head1 SYNOPSIS
152
153    use Wiki::Toolkit;
154    use OpenGuides::Config;
155    use OpenGuides::JSON;
156
157    my $wiki = Wiki::Toolkit->new( ... );
158    my $config = OpenGuides::Config->new( file => "wiki.conf" );
159    my $json_writer = OpenGuides::JSON->new( wiki   => $wiki,
160                                         config => $config );
161
162    # JSON version of a node.
163    print "Content-Type: application/javascript\n\n";
164    print $json_writer->emit_json( node => "Masala Zone, N1 0NU" );
165
166    # Ten most recent changes.
167    print "Content-Type: application/javascript\n";
168    print "Last-Modified: " . $self->json_timestamp( items => 10 ) . "\n\n";
169    print $json_writer->make_recentchanges_json( items => 10 );
170
171=head1 METHODS
172
173=over 4
174
175=item B<new>
176
177    my $json_writer = OpenGuides::JSON->new( wiki   => $wiki,
178                                           config => $config );
179
180C<wiki> must be a L<Wiki::Toolkit> object and C<config> must be an
181L<OpenGuides::Config> object.  Both arguments mandatory.
182
183
184=item B<emit_json>
185
186    $wiki->write_node( "Masala Zone, N1 0NU",
187                     "Quick and tasty Indian food",
188                     $checksum,
189                     { comment  => "New page",
190                       username => "Kake",
191                       locale   => "Islington" }
192    );
193
194    print "Content-Type: application/javascript\n\n";
195    print $json_writer->emit_json( node => "Masala Zone, N1 0NU" );
196
197B<Note:> Some of the fields emitted by the JSON generator are taken
198from the node metadata. The form of this metadata is I<not> mandated
199by L<Wiki::Toolkit>. Your wiki application should make sure to store some or
200all of the following metadata when calling C<write_node>:
201
202=over 4
203
204=item B<postcode> - The postcode or zip code of the place discussed by the node.  Defaults to the empty string.
205
206=item B<city> - The name of the city that the node is in.  If not supplied, then the value of C<default_city> in the config object supplied to C<new>, if available, otherwise the empty string.
207
208=item B<country> - The name of the country that the node is in.  If not supplied, then the value of C<default_country> in the config object supplied to C<new> will be used, if available, otherwise the empty string.
209
210=item B<username> - An identifier for the person who made the latest edit to the node.  This person will be listed as a contributor (Dublin Core).  Defaults to empty string.
211
212=item B<locale> - The value of this can be a scalar or an arrayref, since some places have a plausible claim to being in more than one locale.  Each of these is put in as a C<Neighbourhood> attribute.
213
214=item B<phone> - Only one number supported at the moment.  No validation.
215
216=item B<website> - No validation.
217
218=item B<opening_hours_text> - A freeform text field.
219
220=back
221
222=item B<json_maker>
223
224Returns a raw L<Wiki::Toolkit::Plugin::JSON> object created with the values you
225invoked this module with.
226
227=item B<make_recentchanges_json>
228
229    # Ten most recent changes.
230    print "Content-Type: application/javascript\n";
231    print "Last-Modified: " . $json_writer->json_timestamp( items => 10 ) . "\n\n";
232    print $json_writer->make_recentchanges_json( items => 10 );
233
234    # All the changes made by bob in the past week, ignoring minor edits.
235
236    my %args = (
237                 days               => 7,
238                 ignore_minor_edits => 1,
239                 filter_on_metadata => { username => "bob" },
240               );
241
242    print "Content-Type: application/javascript\n";
243    print "Last-Modified: " . $json_writer->json_timestamp( %args ) . "\n\n";
244    print $json_writer->make_recentchanges_json( %args );
245
246=item B<json_timestamp>
247
248    print "Last-Modified: " . $json_writer->json_timestamp( %args ) . "\n\n";
249
250Returns the timestamp of the RSS feed in POSIX::strftime style ("Tue, 29 Feb 2000
25112:34:56 GMT"), which is equivalent to the timestamp of the most recent item
252in the feed. Takes the same arguments as make_recentchanges_json(). You will most
253likely need this to print a Last-Modified HTTP header so user-agents can determine
254whether they need to reload the feed or not.
255
256=back
257
258=head1 SEE ALSO
259
260=over 4
261
262=item * L<Wiki::Toolkit>
263
264=item * L<http://openguides.org/>
265
266=item * L<http://chefmoz.org/>
267
268=back
269
270=head1 AUTHOR
271
272The OpenGuides Project (openguides-dev@openguides.org)
273
274=head1 COPYRIGHT
275
276Copyright (C) 2003-2005 The OpenGuides Project.  All Rights Reserved.
277
278This module is free software; you can redistribute it and/or modify it
279under the same terms as Perl itself.
280
281=head1 CREDITS
282
283Code in this module is mostly pirated from OpenGuides::RDF, those authors deserve all the credit. Chris Prather
284did the pirating.
285
286=cut
287
2881;
Note: See TracBrowser for help on using the repository browser.