File Coverage

blib/lib/News/GroupInfo.pm
Criterion Covered Total %
statement 12 87 13.7
branch 0 54 0.0
condition 0 19 0.0
subroutine 4 19 21.0
pod 14 14 100.0
total 30 193 15.5


line stmt bran cond sub pod time code
1             $VERSION = "0.11";
2             package News::GroupInfo;
3             our $VERSION = "0.11";
4              
5             # -*- Perl -*- Tue May 25 12:40:24 CDT 2004
6             ###############################################################################
7             # Written by Tim Skirvin . Copyright 2003-2004,
8             # Tim Skirvin. Redistribution terms are below.
9             ###############################################################################
10              
11             =head1 NAME
12              
13             News::GroupInfo - keep track of newsgroup information
14              
15             =head1 SYNOPSIS
16              
17             use News::GroupInfo;
18             my $groupinfo= News::Active->new( '/home/tskirvin/kiboze/newsgroups' );
19             $groupinfo->subscribe("humanities.philosophy.objectivism");
20             $groupinfo->write;
21              
22             See below for more information.
23              
24             =head1 DESCRIPTION
25              
26             News::GroupInfo is used to keep track of passive newsgroup information in
27             an external file. It contains many C objects, one
28             for each newsgroup we are subscribed to. It should be a fairly simple
29             module to use and understand, as it is only a subsection of
30             C.
31              
32             =head1 USAGE
33              
34             =head2 Variables
35              
36             =over 4
37              
38             =item $News::GroupInfo::DEBUG - default value for c in new objects.
39              
40             =item $News::Active::READONLY - default value for C in new objects.
41              
42              
43             =back
44              
45             =cut
46              
47             ###############################################################################
48             ### main() ####################################################################
49             ###############################################################################
50              
51 1     1   6 use strict;
  1         2  
  1         32  
52 1     1   690 use News::GroupInfo::Entry;
  1         2  
  1         27  
53 1     1   7 use Net::NNTP::Functions qw( wildmat );
  1         5  
  1         188  
54 1     1   7 use vars qw( $DEBUG $READONLY );
  1         2  
  1         1465  
55              
56             $DEBUG = 0;
57             $READONLY = 0;
58              
59             =head2 Basic Functions
60              
61             The following functions give us access to the object class
62              
63             =over 4
64              
65             =item new ( FILE )
66              
67             Creates and returns a new News::GroupInfo object. C is the filename
68             (later accessed with C) that we will load old information from
69             and save to when we close the object. It will be created if it doesn't
70             already exist, and read (with C) from if it does.
71              
72             If C is offered, its possible values:
73            
74             debug Print debugging information when using this
75             object. Defaults to $DEBUG.
76             readonly Don't write anything back out with this object
77             when we're done with it. Defaults to $READONLY.
78              
79             Returns undef on failure, or the object on success.
80              
81             =cut
82              
83             sub new {
84 0     0 1   my ($proto, $file, %hash) = @_;
85 0 0         return undef unless $file;
86 0   0       my $class = ref($proto) || $proto;
87 0   0       my $self = {
      0        
88             Groups => { },
89             FileName => $file,
90             Debug => $hash{'debug'} || $DEBUG || 0,
91             ReadOnly => $hash{'readonly'} || $READONLY || 0,
92             };
93 0           bless $self, $class;
94 0           $self->read($file);
95 0           $self;
96             }
97              
98             =item groups ()
99              
100             Returns a hash reference containing all subscribed newsgroups; the keys
101             are the group names, and the values are B objects.
102              
103             =item filename ()
104              
105             Returns the filename used for loading and saving our News::GroupInfo
106             information.
107              
108             =item debug ()
109              
110             Returns true if we want to print debugging information, false otherwise.
111              
112             =item readonly ()
113              
114             Returns true if we shouldn't write out the information later, false
115             otherwise.
116              
117             =cut
118              
119 0 0   0 1   sub groups { shift->{Groups} || {} }
120 0 0   0 1   sub filename { shift->{FileName} || undef }
121 0 0   0 1   sub debug { shift->{Debug} || 0 }
122 0 0   0 1   sub readonly { shift->{ReadOnly} || 0 }
123              
124             =item entry ( GROUP )
125              
126             Returns the News::GroupInfo::Entry object for C, or undef if none
127             exists.
128              
129             =cut
130              
131             sub entry {
132 0     0 1   my ($self, $group) = @_;
133 0 0         $self->groups->{$group} || undef
134             }
135              
136             =item entries ( PATTERN )
137              
138             Returns an array of News::GroupInfo::Entry objects whose newsgroup names
139             match the given pattern C (using
140             C.
141              
142             =cut
143              
144             sub entries {
145 0     0 1   my ($self, $pattern) = @_;
146 0           my @return;
147 0           foreach (sort keys %{$self->groups}) {
  0            
148 0 0 0       next unless wildmat($pattern || "*", $_);
149 0           push @return, $self->entry($_);
150             }
151 0           @return;
152             }
153              
154             =back
155              
156             =head2 Newsgroup Functions
157              
158             The following functions implement the functions that we actually want to
159             use this module for, ie adding groups and articles to the active file.
160              
161             =over 4
162              
163             =item subscribe ( GROUP )
164              
165             Adds a News::GroupInfo::Entry entry for the given C, thus adding it
166             to our subscription list. Returns 1 on success, undef otherwise.
167              
168             =cut
169              
170             sub subscribe {
171 0     0 1   my ($self, $group, @info) = @_;
172 0 0         return undef unless $group;
173 0 0         return 1 if $self->subscribed($group);
174 0 0         print "Subscribing to $group\n" if $self->debug;
175 0           $self->groups->{$group} =
176             new News::GroupInfo::Entry(join("::", $group, @info));
177 0           1;
178             }
179              
180             =item unsubscribe ( GROUP )
181              
182             Unsubscribe from C by making sure there is no
183             News::GroupInfo::Entry entry for that groupname. Returns 1 on success or
184             if we were already unsubscribed, undef otherwise.
185              
186             =cut
187              
188             sub unsubscribe {
189 0     0 1   my ($self, $group) = @_;
190 0 0         return undef unless $group;
191 0 0         return 1 unless $self->groups->{$group};
192 0 0         print "Unsubscribing from $group\n" if $self->debug;
193 0           delete $self->groups->{$group};
194 0           1;
195             }
196              
197             =item subscribed ( GROUP )
198              
199             Returns 1 if we are subscribed to C, 0 otherwise.
200              
201             =cut
202              
203             sub subscribed {
204 0     0 1   my ($self, $group) = @_;
205 0 0         return 0 unless $group;
206 0 0         $self->groups->{$group} ? 1 : 0;
207             }
208              
209             =back
210              
211             =head2 Input/Output Functions
212              
213             The following functions are used for reading, displaying, and saving
214             information from News::GroupInfo and News::GroupInfo::Entry.
215              
216             =over 4
217              
218             =item read ( [FILE] )
219              
220             Reads News::GroupInfo::Entry information from C (or the value of
221             C), populating the News::GroupInfo object. This file contains
222             lines that each contain the output from a single
223             C call. Returns 1 on success, undef
224             otherwise.
225              
226             =cut
227              
228             sub read {
229 0     0 1   my ($self, $file) = @_;
230 0   0       $file ||= $self->filename;
231 0 0         return undef unless $file;
232 0           $$self{Groups} = {};
233 0 0         print "Reading from $file\n" if $self->debug;
234 0 0 0       open(FILE, $file) or (warn "Couldn't read from $file: $!\n" && return undef);
235 0           foreach () {
236 0           chomp;
237 0           s/#.*$//; # Trim comments
238 0           s/^\s+//; # ...and leading whitespace
239 0 0         next unless $_;
240 0 0         my $entry = new News::GroupInfo::Entry($_) or next;
241 0           $self->groups->{$entry->name} = $entry;
242             }
243 0           close FILE;
244 0           1;
245             }
246              
247             =item printable ()
248              
249             Returns an array (or arrayref, depending on invocation) containing the
250             value of C on each entry within the
251             News::GroupInfo object. These are then suitable for printing.
252              
253             =cut
254              
255             sub printable {
256 0     0 1   my ($self) = @_;
257 0           my @return;
258 0           foreach (sort keys %{$self->groups}) {
  0            
259 0           my $info = $self->entry($_)->print;
260 0           push @return, $info;
261             }
262 0 0         wantarray ? @return : join("\n", @return);
263             }
264              
265             =item output ()
266              
267             Returns an array (or arrayref, depending on invocation) containing the
268             value of C on each entry within the
269             News::GroupInfo object. These are then suitable for saving to a database
270             and later reloading.
271              
272             =cut
273              
274             sub output {
275 0     0 1   my ($self) = @_;
276 0           my @return;
277 0           foreach (sort keys %{$self->groups}) {
  0            
278 0           push @return, $self->entry($_)->output;
279             }
280 0 0         wantarray ? @return : join("\n", @return);
281             }
282              
283             =item write ( [FILE] )
284              
285             Using the information from output(), writes out to C (or the value
286             of C). Returns 1 on success, undef otherwise. If the readonly
287             flag is set, we don't actually write anything back out.
288              
289             Note that this function is called when the object is destroyed as well.
290              
291             =cut
292              
293             sub write {
294 0     0 1   my ($self, $file) = @_;
295 0 0         if ( $self->readonly ) {
296 0 0         warn "Not writing output, readonly!\n" if $self->debug;
297 0           return 1;
298             }
299 0   0       $file ||= $self->filename;
300 0 0         return undef unless $file;
301 0 0         print "Writing to $file\n" if $self->debug;
302 0 0 0       open(FILE, ">$file")
303             or (warn "Couldn't write to $file: $!\n" && return undef);
304 0           print FILE join("\n", $self->output);
305 0           close FILE;
306 0           1;
307             }
308              
309             =back
310              
311             =cut
312              
313             ###############################################################################
314             ### Internal Functions ########################################################
315             ###############################################################################
316              
317             ### DESTROY
318             # Item destructor. Make sure the file is written back out.
319 0     0     sub DESTROY { shift->write }
320              
321             1;
322              
323             =head1 NOTES
324              
325             This and C are fairly similar, but are meant to take care of
326             different types of information. The News::Active file is meant to be
327             modified regularly, every time a new article is added; in INN terms this
328             is the equivalent of the active file. The information in News::GroupInfo
329             is meant to only be modified occasionally, when something major changes;
330             in INN terms this is the equivalent of the newsgroups and active.times
331             files.
332              
333             =head1 TODO
334              
335             File locking would be nice.
336              
337             =head1 REQUIREMENTS
338              
339             C
340              
341             =head1 SEE ALSO
342              
343             B, B
344              
345             =head1 AUTHOR
346              
347             Tim Skirvin
348              
349             =head1 HOMEPAGE
350              
351             B
352              
353             =head1 LICENSE
354              
355             This code may be redistributed under the same terms as Perl itself.
356              
357             =head1 COPYRIGHT
358              
359             Copyright 2003-2004, Tim Skirvin.
360              
361             =cut
362              
363             ###############################################################################
364             ### Version History ###########################################################
365             ###############################################################################
366             # v0.05 Fri Oct 03 13:56:50 CDT 2003
367             ### First version of any code.
368             # v0.10 Wed Apr 28 10:50:09 CDT 2004
369             ### First documented version. Put in matching information with entries().
370             # v0.11 Tue May 25 12:40:12 CDT 2004
371             ### Added read-only stuff.