File Coverage

blib/lib/App/Rssfilter/Group.pm
Criterion Covered Total %
statement 107 107 100.0
branch 21 32 65.6
condition 8 15 53.3
subroutine 27 27 100.0
pod n/a
total 163 181 90.0


line stmt bran cond sub pod time code
1             # ABSTRACT: associate one or more rules with more than one feed
2              
3 6     6   1267985 use strict;
  6         15  
  6         256  
4 6     6   37 use warnings;
  6         14  
  6         382  
5              
6              
7             package App::Rssfilter::Group;
8             {
9             $App::Rssfilter::Group::VERSION = '0.07';
10             }
11 6     6   2733 use Moo;
  6         57341  
  6         55  
12             with 'App::Rssfilter::Logger';
13             with 'App::Rssfilter::FromHash';
14             with 'App::Rssfilter::FromYaml';
15 6     6   31044 use Method::Signatures;
  6         246660  
  6         51  
16              
17 6     6   642303 method BUILDARGS( @options ) {
  12     12   9675483  
  12         68  
18 12 100       59 if( 1 == @options ) {
19 5         15 unshift @options, 'name';
20             }
21 12         264 return { @options };
22             }
23              
24              
25 6 50 33 6   68529 method update( ArrayRef :$rules = [], :$storage = $self->storage ) {
  3 50 33 3   211  
  3 100       20  
  3 50       93  
  3 50       18091  
  3         11  
  3         24  
  3         9  
  3         16  
  3         15  
26 3         59 my $child_storage = $storage->path_push( $self->name );
27 3         242 my @rules = map { @{ $_ } } $rules, $self->rules;
  6         9  
  6         19  
28 3         24 $self->logger->debugf( 'filtering feeds in %s', $self->name );
29 3         173 $_->update( rules => \@rules, storage => $child_storage ) for @{ $self->groups };
  3         41  
30 3         201 $_->update( rules => \@rules, storage => $child_storage ) for @{ $self->feeds };
  3         33  
31             }
32              
33              
34              
35             has name => (
36             is => 'ro',
37             default => sub { '.' },
38             );
39              
40              
41             has storage => (
42             is => 'ro',
43             default => method { App::Rssfilter::Feed::Storage->new },
44             );
45              
46              
47             has groups => (
48             is => 'ro',
49             default => sub { [] },
50             );
51 6 50   6   29034  
  8     8   197882  
  8         41  
  8         16  
  8         27  
52 6     6   655  
  6         16  
  6         1065  
53 8 100 66     109 method add_group( $app_rssfilter_group, @group_options ) {
54 2         6 use Scalar::Util qw< blessed >;
55 2         53 if ( ! blessed( $app_rssfilter_group ) or ! $app_rssfilter_group->isa( 'App::Rssfilter::Group' ) ) {
56             unshift @group_options, $app_rssfilter_group; # restore original @_
57             $app_rssfilter_group = App::Rssfilter::Group->new( @group_options );
58 8         203 }
  8         46  
59 8         32  
60             push @{ $self->groups }, $app_rssfilter_group;
61             return $self;
62             }
63 6 50   6   28222  
  2 50   2   73  
  2         8  
  2         4  
  2         6  
64 6     6   861  
  6         14  
  6         839  
65 2     5   12 method group( $name ) {
  5         27  
  2         16  
66             use List::Util qw< first >;
67             first { $_->name eq $name } reverse @{ $self->groups };
68             }
69              
70              
71             has rules => (
72             is => 'ro',
73             default => sub { [] },
74             );
75 6 50   6   24159  
  4     4   6671  
  4         17  
  4         9  
  4         16  
76 6     6   675  
  6         14  
  6         1167  
77 4 100 66     43 method add_rule( $app_rssfilter_rule, @rule_options ) {
78 1         4 use Scalar::Util qw< blessed >;
79 6     6   5623 if ( ! blessed( $app_rssfilter_rule ) or ! $app_rssfilter_rule->isa( 'App::Rssfilter::Rule' ) ) {
  6         20  
  6         650  
80 1         11 unshift @rule_options, $app_rssfilter_rule; # restore original @_
81             use App::Rssfilter::Rule;
82             $app_rssfilter_rule = App::Rssfilter::Rule->new( @rule_options );
83 4         78 }
  4         24  
84 4         22  
85             push @{ $self->rules }, $app_rssfilter_rule;
86             return $self;
87             }
88              
89              
90             has feeds => (
91             is => 'ro',
92             default => sub { [] },
93             );
94 6 50   6   20424  
  9     9   13709  
  9         44  
  9         22  
  9         51  
95 6     6   704  
  6         14  
  6         669  
96 9 100 66     104 method add_feed( $app_rssfilter_feed, @feed_options ) {
97 2         7 use Scalar::Util qw< blessed >;
98 6     6   14837 if ( ! blessed( $app_rssfilter_feed ) or ! $app_rssfilter_feed->isa( 'App::Rssfilter::Feed' ) ) {
  6         24  
  6         498  
99 2         41 unshift @feed_options, $app_rssfilter_feed; # restore original @_
100             use App::Rssfilter::Feed;
101             $app_rssfilter_feed = App::Rssfilter::Feed->new( @feed_options );
102 9         202 }
  9         56  
103 9         34  
104             push @{ $self->feeds }, $app_rssfilter_feed;
105             return $app_rssfilter_feed;
106             }
107 6 50   6   13436  
  2 50   2   78  
  2         9  
  2         4  
  2         8  
108 6     6   634  
  6         13  
  6         842  
109 2     5   11 method feed( $name ) {
  5         22  
  2         12  
110             use List::Util qw< first >;
111             first { $_->name eq $name } reverse @{ $self->feeds };
112             }
113              
114              
115              
116             1;
117              
118             __END__
119              
120             =pod
121              
122             =encoding UTF-8
123              
124             =head1 NAME
125              
126             App::Rssfilter::Group - associate one or more rules with more than one feed
127              
128             =head1 VERSION
129              
130             version 0.07
131              
132             =head1 SYNOPSIS
133              
134             use App::RssFilter::Group;
135              
136             my $news_group = App::Rssfilter::Group->new( 'news' );
137             # shorthand for
138             $news_group = App::Rssfilter::Group( name => 'news' );
139              
140             $news_group->add_group( 'USA' );
141             # shorthand for
142             $news_group->add_group(
143             App::Rssfilter::Group->new(
144             name => 'USA',
145             )
146             );
147             my $uk_news_group = $news_group->add_group( name => 'UK' );
148              
149             $uk_news_group->add_rule( 'Category[Politics]' => 'MarkTitle' );
150             # shorthand for
151             $uk_news_group->add_rule(
152             App::Rssfilter::Rule->new(
153             condition => 'Category[Politics]',
154             action => 'MarkTitle',
155             )
156             );
157              
158             my $dupe_rule = $news_group->group( 'USA' )->add_rule( condition => 'Duplicate', action => 'DeleteItem' );
159             $uk_news_group->add_rule( $dupe_rule );
160              
161             $news_group->group( 'USA' )->add_feed( WashPost => 'http://feeds.washingtonpost.com/rss/national' );
162             # shorthand for
163             $news_group->group( 'USA' )->add_feed(
164             App::Rssfilter::Feed->new(
165             name => 'WashPost',
166             url => 'http://feeds.washingtonpost.com/rss/national',
167             )
168             );
169             $news_group->group( 'USA' )->add_feed( name => 'NYTimes', url => 'http://www.nytimes.com/services/xml/rss/nyt/HomePage.xml' );
170              
171             $uk_news_group->add_feed( $news_group->group( 'USA' )->feed( 'WashPost' ) );
172              
173             $news_group->update;
174              
175             =head1 DESCRIPTION
176              
177             This module groups together feeds so that the same rules will be used to constrain them.
178              
179             It consumes the L<App::Rssfilter::Logger> role.
180              
181             Use a group to:
182              
183             =over 4
184              
185             =item *
186              
187             allow rules which retain state (e.g. L<Duplicates|App::Rssfilter::Match::Duplicates>) to constrain over multiple feeds
188              
189             =item *
190              
191             apply the same rules configuration to multiple feeds
192              
193             =back
194              
195             =head1 ATTRIBUTES
196              
197             =head2 logger
198              
199             This is a object used for logging; it defaults to a L<Log::Any> object. It is provided by the L<App::Rssfilter::Logger> role.
200              
201             =head2 name
202              
203             This is the name of the group. Group names are used when storing a feed so that feeds from the same group are kept together. The default value is '.' (a single period).
204              
205             =head2 storage
206              
207             This is a feed storage object for feeds to use when they are updated. The default value is a fresh instance of L<App::Rssfilter::Feed::Storage>. See L</update> for details on when the default value is used.
208              
209             =head2 groups
210              
211             This is an arrayref of subgroups attatched to this group.
212              
213             =head2 rules
214              
215             This is an arrayref of rules to apply to the feeds in this group (and subgroups).
216              
217             =head2 feeds
218              
219             This is an arrayref of feeds.
220              
221             =head1 METHODS
222              
223             =head2 update
224              
225             $group->update( rules => $rules, storage => $storage );
226              
227             Recursively calls C<update> on the feeds and subgroups of this group.
228              
229             C<$rules> is an arrayref of additional rules to constrain the feed and groups, in addition to the group's current list of rules.
230              
231             C<$storage> is the feed storage object that feeds and subgroups will use to store their updated contents. If not specified, groups will use their default C<storage>. The group's C<name> is appended to the current path of C<$storage> before being passed to feeds and subgroups.
232              
233             =head2 add_group
234              
235             $group = $group->add_group( $app_rssfilter_group | %group_options );
236              
237             Adds C<$app_rssfilter_group> (or creates a new App::RssFilter::Group instance from the C<%group_options>) to the list of subgroups for this group. Returns this group (for chaining).
238              
239             =head2 group
240              
241             my $subgroup = $group->group( $name );
242              
243             Returns the last subgroup added to this group whose name is C<$name>, or C<undef> if no matching group.
244              
245             =head2 add_rule
246              
247             $group = $group->add_rule( $app_rssfilter_rule | %rule_options )
248              
249             Adds C<$app_rssfilter_rule> (or creates a new App::RssFilter::Rule instance from the C<%rule_options>) to the list of rules for this group. Returns this group (for chaining).
250              
251             =head2 add_feed
252              
253             $group = $group->add_feed( $app_rssfilter_feed | %feed_options );
254              
255             Adds C<$app_rssfilter_feed> (or creates a new App::RssFilter::Feed instance from the C<%feed_options>) to the list of feeds for this group. Returns this group (for chaining).
256              
257             =head2 feed
258              
259             my $feed = $group->feed( $name );
260              
261             Returns the last feed added to this group whose name is C<$name>, or C<undef> if no matching feed.
262              
263             =head2 from_hash
264              
265             my $group = App::Rssfilter::Group::from_hash( %config );
266              
267             Returns a new instance of this class with the feeds, rules, and subgroups specifed in C<%config>. This method is provided by L<App::Rssfilter::FromHash/from_hash>, which has additional documentation & examples.
268              
269             =head2 from_yaml
270              
271             my $group = App::Rssfilter::Group::from_yaml( $yaml_config );
272              
273             Returns a new instance of this class with the feeds, rules, and subgroups specifed in C<$yaml_config>. This method is provided by L<App::Rssfilter::FromYaml/from_yaml>, which has additional documentation & examples.
274              
275             =head1 SEE ALSO
276              
277             =over 4
278              
279             =item *
280              
281             L<App::RssFilter::Rule>
282              
283             =item *
284              
285             L<App::RssFilter::Feed>
286              
287             =item *
288              
289             L<App::RssFilter>
290              
291             =back
292              
293             =head1 AUTHOR
294              
295             Daniel Holz <dgholz@gmail.com>
296              
297             =head1 COPYRIGHT AND LICENSE
298              
299             This software is copyright (c) 2013 by Daniel Holz.
300              
301             This is free software; you can redistribute it and/or modify it under
302             the same terms as the Perl 5 programming language system itself.
303              
304             =cut