File Coverage

blib/lib/Wiki/Toolkit/Feed/Listing.pm
Criterion Covered Total %
statement 6 82 7.3
branch 0 26 0.0
condition 0 2 0.0
subroutine 2 13 15.3
pod 10 11 90.9
total 18 134 13.4


line stmt bran cond sub pod time code
1             package Wiki::Toolkit::Feed::Listing;
2              
3 6     6   19 use strict;
  6         10  
  6         155  
4 6     6   17 use Carp qw( croak );
  6         6  
  6         3799  
5              
6             =head1 NAME
7              
8             Wiki::Toolkit::Feed::Listing - parent class for Feeds from Wiki::Toolkit.
9              
10             =head1 DESCRIPTION
11              
12             Handles common data fetching tasks, so that child classes need only
13             worry about formatting the feeds.
14              
15             Also enforces some common methods that must be implemented.
16              
17             =head1 METHODS
18              
19             =head2 C
20              
21             Based on the supplied criteria, fetch a list of the recently changed nodes
22              
23             =cut
24              
25             sub fetch_recently_changed_nodes {
26 0     0 1   my ($self, %args) = @_;
27              
28 0           my $wiki = $self->{wiki};
29              
30 0           my %criteria = (
31             ignore_case => 1,
32             );
33              
34             # If we're not passed any parameters to limit the items returned,
35             # default to 15.
36             $args{days} ? $criteria{days} = $args{days}
37 0 0 0       : $criteria{last_n_changes} = $args{items} || 15;
38              
39 0           my %was_filter;
40 0 0         if ( $args{filter_on_metadata} ) {
41 0           %was_filter = %{ $args{filter_on_metadata} };
  0            
42             }
43              
44 0 0         if ( $args{ignore_minor_edits} ) {
45 0           %was_filter = ( %was_filter, major_change => 1 );
46             }
47            
48 0           $criteria{metadata_was} = \%was_filter;
49              
50 0           my @changes = $wiki->list_recent_changes(%criteria);
51              
52 0           return @changes;
53             }
54              
55             =head2 C
56              
57             Based on the supplied criteria (but not using all of those used by
58             B), find the newest node from the recently
59             changed nodes set. Normally used for dating the whole of a Feed.
60              
61             =cut
62              
63             sub fetch_newest_for_recently_changed {
64 0     0 1   my ($self, %args) = @_;
65              
66 0           my @changes = $self->fetch_recently_changed_nodes( %args );
67 0           return $changes[0];
68             }
69              
70              
71             =head2 C
72              
73             For a given node (name or ID), return all the versions there have been,
74             including all metadata required for it to go into a "recent changes"
75             style listing.
76              
77             =cut
78              
79             sub fetch_node_all_versions {
80 0     0 1   my ($self, %args) = @_;
81              
82             # Check we got the right options
83 0 0         unless($args{'name'}) {
84 0           return ();
85             }
86              
87             # Do the fetch
88             my @nodes = $self->{wiki}->list_node_all_versions(
89 0           name => $args{'name'},
90             with_content => 0,
91             with_metadata => 1,
92             );
93              
94             # Ensure that all the metadata fields are arrays and not strings
95 0           foreach my $node (@nodes) {
96 0           foreach my $mdk (keys %{$node->{'metadata'}}) {
  0            
97 0 0         unless(ref($node->{'metadata'}->{$mdk}) eq "ARRAY") {
98 0           $node->{'metadata'}->{$mdk} = [ $node->{'metadata'}->{$mdk} ];
99             }
100             }
101             }
102              
103 0           return @nodes;
104             }
105              
106              
107             =head2 C
108              
109             Build an Atom Feed of the recent changes to the Wiki::Toolkit instance,
110             using any supplied parameters to narrow the results.
111              
112             If the argument "also_return_timestamp" is supplied, it will return an
113             array of the feed, and the feed timestamp. Otherwise it just returns the feed.
114              
115             =cut
116              
117             sub recent_changes {
118 0     0 1   my ($self, %args) = @_;
119              
120 0           my @changes = $self->fetch_recently_changed_nodes(%args);
121 0           my $feed_timestamp = $self->feed_timestamp(
122             $self->fetch_newest_for_recently_changed(%args)
123             );
124              
125 0           my $feed = $self->generate_node_list_feed($feed_timestamp, @changes);
126              
127 0 0         if ($args{'also_return_timestamp'}) {
128 0           return ($feed,$feed_timestamp);
129             } else {
130 0           return $feed;
131             }
132             }
133              
134              
135             =head2 C
136              
137             Build an Atom Feed of all the different versions of a given node.
138              
139             If the argument "also_return_timestamp" is supplied, it will return an
140             array of the feed, and the feed timestamp. Otherwise it just returns the feed.
141              
142             =cut
143              
144             sub node_all_versions {
145 0     0 1   my ($self, %args) = @_;
146              
147 0           my @all_versions = $self->fetch_node_all_versions(%args);
148 0           my $feed_timestamp = $self->feed_timestamp( $all_versions[0] );
149              
150 0           my $feed = $self->generate_node_list_feed($feed_timestamp, @all_versions);
151              
152 0 0         if($args{'also_return_timestamp'}) {
153 0           return ($feed,$feed_timestamp);
154             } else {
155 0           return $feed;
156             }
157             }
158              
159             =head2 C
160              
161             Using the geo and space xml namespaces, format the supplied node metadata
162             into geo: and space: tags, suitable for inclusion in a feed with those
163             namespaces imported.
164              
165             =cut
166              
167             sub format_geo {
168 0     0 1   my ($self, @args) = @_;
169              
170 0           my %metadata;
171 0 0         if(ref($args[0]) eq "HASH") {
172 0           %metadata = %{$_[1]};
  0            
173             } else {
174 0           %metadata = @args;
175             }
176              
177 0           my %mapping = (
178             "os_x" => "space:os_x",
179             "os_y" => "space:os_y",
180             "latitude" => "geo:lat",
181             "longitude" => "geo:long",
182             "distance" => "space:distance",
183             );
184              
185 0           my $feed = "";
186              
187 0           foreach my $geo (keys %metadata) {
188 0           my $geo_val = $metadata{$geo};
189 0 0         if(ref($geo_val) eq "ARRAY") {
190 0           $geo_val = $geo_val->[0];
191             }
192              
193 0 0         if($mapping{$geo}) {
194 0           my $tag = $mapping{$geo};
195 0           $feed .= " <$tag>$geo_val\n";
196             }
197             }
198              
199 0           return $feed;
200             }
201              
202             # Utility method, to help with argument passing where one of a list of
203             # arguments must be supplied
204              
205             sub handle_supply_one_of {
206 0     0 0   my ($self,$mref,$aref) = @_;
207 0           my %mustoneof = %{$mref};
  0            
208 0           my %args = %{$aref};
  0            
209              
210 0           foreach my $oneof (keys %mustoneof) {
211 0           my $val = undef;
212 0           foreach my $poss (@{$mustoneof{$oneof}}) {
  0            
213 0 0         unless($val) {
214 0 0         if($args{$poss}) { $val = $args{$poss}; }
  0            
215             }
216             }
217 0 0         if($val) {
218 0           $self->{$oneof} = $val;
219             } else {
220 0           croak "No $oneof supplied, or one of its equivalents (".join(",", @{$mustoneof{$oneof}}).")";
  0            
221             }
222             }
223             }
224              
225              
226             =pod
227              
228             The following are methods that any feed renderer must provide:
229              
230             =head2 C
231              
232             All implementing feed renderers must implement a method to produce a
233             feed specific timestamp, based on the supplied node
234              
235             =cut
236              
237 0     0 1   sub feed_timestamp { die("Not implemented by feed renderer!"); }
238              
239             =head2 C
240              
241             All implementing feed renderers must implement a method to produce a
242             feed from the supplied list of nodes
243              
244             =cut
245              
246 0     0 1   sub generate_node_list_feed { die("Not implemented by feed renderer!"); }
247              
248             =head2 C
249              
250             All implementing feed renderers must implement a method to produce a
251             stripped down feed from the supplied list of node names, and optionally
252             locations and distance from a reference point.
253              
254             =cut
255              
256 0     0 1   sub generate_node_name_distance_feed { die("Not implemented by feed renderer!"); }
257              
258             =head2 C
259              
260             Take a feed_timestamp and return a Time::Piece object.
261              
262             =cut
263              
264 0     0 1   sub parse_feed_timestamp { die("Not implemented by feed renderer!"); }
265              
266             1;
267              
268             __END__