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   3062 use strict;
  3         8  
  3         90  
4              
5 3     3   16 use vars qw( $VERSION );
  3         6  
  3         143  
6             $VERSION = '0.05';
7              
8 3     3   2326 use Wiki::Toolkit::Plugin::JSON;
  3         17196  
  3         90  
9 3     3   19 use Time::Piece;
  3         7  
  3         13  
10 3     3   170 use URI::Escape;
  3         8  
  3         146  
11 3     3   16 use Carp 'croak';
  3         6  
  3         109  
12 3     3   27 use JSON;
  3         5  
  3         14  
13 3     3   275 use OpenGuides::CGI;
  3         5  
  3         3441  
14              
15             sub new {
16 5     5 1 6797 my ( $class, @args ) = @_;
17 5         10 my $self = {};
18 5         12 bless $self, $class;
19 5         18 $self->_init(@args);
20             }
21              
22             sub _init {
23 5     5   23 my ( $self, %args ) = @_;
24              
25 5         11 my $wiki = $args{wiki};
26              
27 5 100 66     45 unless ( $wiki && UNIVERSAL::isa( $wiki, "Wiki::Toolkit" ) ) {
28 1         193 croak "No Wiki::Toolkit object supplied.";
29             }
30 4         22 $self->{wiki} = $wiki;
31              
32 4         8 my $config = $args{config};
33              
34 4 100 66     30 unless ( $config && UNIVERSAL::isa( $config, "OpenGuides::Config" ) ) {
35 1         116 croak "No OpenGuides::Config object supplied.";
36             }
37 3         8 $self->{config} = $config;
38              
39             $self->{make_node_url} = sub {
40 12     12   2783 my ( $node_name, $version ) = @_;
41              
42 12         20 my $config = $self->{config};
43              
44 12         36 my $node_url = $config->script_url;
45 12 100       33 if ( $config->script_name ) {
46 8         145 $node_url .= uri_escape( $config->script_name ) . '?';
47             }
48 12 100       188 $node_url .= 'id=' if defined $version;
49             $node_url .=
50             uri_escape(
51 12         40 $self->{wiki}->formatter->node_name_to_node_param($node_name) );
52 12 100       416 $node_url .= ';version=' . uri_escape($version) if defined $version;
53              
54 12         79 $node_url;
55 3         23 };
56 3         16 $self->{site_name} = $config->site_name;
57 3   100     43 $self->{default_city} = $config->default_city || "";
58 3   100     49 $self->{default_country} = $config->default_country || "";
59 3   50     45 $self->{site_description} = $config->site_desc || "";
60 3         47 $self->{og_version} = $args{og_version};
61              
62 3         13 $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 1328 my ( $self, %args ) = @_;
75              
76 3         6 my $node_name = $args{node};
77 3         8 my $wiki = $self->{wiki};
78              
79 3         17 my %node_data = $wiki->retrieve_node($node_name);
80 3         5212 my $data = {};
81 3   100     23 $data->{phone} = $node_data{metadata}{phone}[0] || '';
82 3   50     22 $data->{fax} = $node_data{metadata}{fax}[0] || '';
83 3   100     17 $data->{website} = $node_data{metadata}{website}[0] || '';
84 3   100     17 $data->{opening_hours_text} = $node_data{metadata}{opening_hours_text}[0]
85             || '';
86 3   50     18 $data->{address} = $node_data{metadata}{address}[0] || '';
87 3   100     17 $data->{postcode} = $node_data{metadata}{postcode}[0] || '';
88 3   33     21 $data->{city} = $node_data{metadata}{city}[0] || $self->{default_city};
89             $data->{country} = $node_data{metadata}{country}[0]
90 3   33     21 || $self->{default_country};
91 3   100     14 $data->{latitude} = $node_data{metadata}{latitude}[0] || '';
92 3   100     15 $data->{longitude} = $node_data{metadata}{longitude}[0] || '';
93 3         9 $data->{version} = $node_data{version};
94 3   100     17 $data->{username} = $node_data{metadata}{username}[0] || '';
95 3   100     16 $data->{os_x} = $node_data{metadata}{os_x}[0] || '';
96 3   100     19 $data->{os_y} = $node_data{metadata}{os_y}[0] || '';
97 3   50     18 $data->{categories} = $node_data{metadata}{category} || [];
98 3   100     19 $data->{locales} = $node_data{metadata}{locale} || [];
99 3   100     19 $data->{summary} = $node_data{metadata}{summary}[0] || '';
100 3         6 $data->{content} = $node_data{content};
101 3         15 $data->{formatted_content} = $wiki->format($node_data{content});
102 3   100     40563 $data->{node_image} = $node_data{metadata}{node_image}[0]|| '';
103 3   100     21 $data->{node_image_url} = $node_data{metadata}{node_image_url}[0]|| '';
104 3   100     16 $data->{node_image_licence} = $node_data{metadata}{node_image_licence}[0]|| '';
105              
106 3         8 $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       11 if ( $data->{timestamp} ) {
112 2         21 my $time = Time::Piece->strptime( $data->{timestamp}, $timestamp_fmt );
113 2         76 $data->{timestamp} = $time->strftime("%Y-%m-%dT%H:%M:%S");
114             }
115              
116 3         100 $data->{url} = $self->{make_node_url}->( $node_name, $data->{version} );
117 3         9 $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 84 my ( $self, %args ) = @_;
129 1         3 return $self->json_maker->make_json(\%args);
130             }
131              
132             sub json_maker {
133 5     5 1 8 my $self = shift;
134              
135             # OAOO, please.
136 5 100       15 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         11 );
148             }
149              
150 5         282 return $self->{json_maker};
151             }
152              
153             sub make_prefs_json {
154 3     3 1 584 my $self = shift;
155             my %prefs = OpenGuides::CGI->get_prefs_from_cookie(
156 3         20 config => $self->{config} );
157 3         56 return encode_json( \%prefs );
158             }
159              
160             sub make_recentchanges_json {
161 1     1 1 103 my ( $self, %args ) = @_;
162              
163 1         4 $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;