File Coverage

blib/lib/OpenGuides/JSON.pm
Criterion Covered Total %
statement 99 101 98.0
branch 14 14 100.0
condition 42 52 80.7
subroutine 16 17 94.1
pod 7 7 100.0
total 178 191 93.1


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