root/wiki-toolkit/trunk/lib/Wiki/Toolkit/Feed/Listing.pm @ 367

Revision 367, 6.9 KB (checked in by sheldon, 6 years ago)

Added parse_feed_timestamp that will turn a feed_timestamp into a Time::Piece object.

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