File Coverage

blib/lib/App/Rssfilter/Feed/Storage.pm
Criterion Covered Total %
statement 67 67 100.0
branch 19 28 67.8
condition 4 6 66.6
subroutine 20 20 100.0
pod n/a
total 110 121 90.9


line stmt bran cond sub pod time code
1 17     17   7034 use strict;
  17         41  
  17         462  
2 17     17   92 use warnings;
  17         39  
  17         874  
3              
4             # ABSTRACT: load and save RSS feeds as files
5              
6              
7             package App::Rssfilter::Feed::Storage;
8             $App::Rssfilter::Feed::Storage::VERSION = '0.08'; # TRIAL
9 17     17   1884 use Method::Signatures;
  17         141531  
  17         126  
10 17     17   11025 use Moo;
  17         27359  
  17         149  
11             with 'App::Rssfilter::Logger';
12 17     17   51087 use Mojo::DOM;
  17         142878  
  17         506  
13 17     17   13054 use Path::Class::File 0.26;
  17         512346  
  17         494  
14 17     17   145 use Path::Class::Dir;
  17         37  
  17         416  
15 17     17   12694 use HTTP::Date;
  17         33311  
  17         3464  
16              
17              
18              
19             has path => (
20             is => 'ro',
21             default => sub { Path::Class::Dir->new() },
22             coerce => sub {
23             return $_[0] if 'Path::Class::Dir' eq ref $_[0];
24             if ( 1 == @_ && 'Array' eq ref $_[0] ) {
25             @_ = @{ $_[0] };
26             }
27             Path::Class::Dir->new( @_ )
28             },
29             );
30              
31              
32 17     17   1506298 method path_push( @paths ) {
  1     1   2514  
  1         5  
33 1         9 return App::Rssfilter::Feed::Storage->new(
34             path => $self->path->subdir( @paths ),
35             name => $self->name,
36             );
37             }
38              
39              
40             has name => (
41             is => 'ro',
42             );
43              
44              
45 17 50   17   41202 method set_name( $new_name ) {
  4 50   4   7817  
  4         16  
  4         6  
  4         13  
46 4 100 66     48 return $self if defined($self->name) && defined($new_name) ? $self->name eq $new_name : ! defined($self->name) && ! defined($new_name);
    100 66        
47 2         50 return App::Rssfilter::Feed::Storage->new(
48             name => $new_name,
49             path => $self->path,
50             );
51             }
52              
53             has _file_path => (
54             is => 'lazy',
55             init_arg => undef,
56             );
57              
58 17 50   17   12477 method _build__file_path {
  1     1   410  
  1         5  
59 1 50       10 die "no name" if not defined $self->name;
60 1 50       5 die "no path" if not defined $self->path;
61 1         9 $self->path->file( $self->name .'.rss' );
62             }
63              
64              
65             has last_modified => (
66             is => 'lazy',
67             init_arg => undef,
68             clearer => '_clear_last_modified',
69             );
70              
71 17 50   17   10876 method _build_last_modified {
  2     2   4789  
  2         10  
72 2 100       25 if ( my $stat = $self->_file_path->stat ) {
73 1         414 return time2str $stat->mtime;
74             }
75 1         123 return time2str 0;
76             }
77              
78              
79 17 50   17   10855 method load_existing {
  2     2   3813  
  2         9  
80 2         9 $self->logger->debugf( 'loading '. $self->_file_path );
81 2         28205 my $stat = $self->_file_path->stat;
82              
83 2 100       437 return Mojo::DOM->new if not defined $stat;
84              
85 1         10 $self->_clear_last_modified;
86 1         758 return Mojo::DOM->new( scalar $self->_file_path->slurp );
87             }
88              
89              
90 17 50   17   37813 method save_feed( $feed ) {
  2 50   2   7300  
  2         15  
  2         6  
  2         11  
91 2         14 $self->logger->debugf( 'writing out new filtered feed to '. $self->_file_path );
92 2         400 my $target_dir = $self->_file_path->dir;
93 2 100       49 if( not defined $target_dir->stat ) {
94 1         101 $self->logger->debug( "no $target_dir directory! making one" );
95 1         74 $target_dir->mkpath;
96             }
97 2         493 $self->_file_path->spew( $feed->to_string );
98 2         1136 $self->_clear_last_modified;
99             }
100              
101             1;
102              
103             __END__
104              
105             =pod
106              
107             =encoding UTF-8
108              
109             =head1 NAME
110              
111             App::Rssfilter::Feed::Storage - load and save RSS feeds as files
112              
113             =head1 VERSION
114              
115             version 0.08
116              
117             =head1 SYNOPSIS
118              
119             use App::Rssfilter::Feed::Storage;
120              
121             my $fs = App::Rssfilter::Feed::Storage->new(
122             path => 'Hi-type feeds',
123             name => 'Hello',
124             );
125              
126             print 'last update of feed was ', $fs->last_modified, "\n";
127             print 'what we got last time: ', $fs->load_existing, "\n";
128              
129             $fs->save_feed( Mojo::DOM->new( "<hi>hello</hi>" ) );
130             print 'now it is: ', $fs->load_existing, "\n";
131              
132             =head1 DESCRIPTION
133              
134             This module saves and loads RSS feeds to and from files, where the file name is based on a group and feed name. It is the default implementation used by L<App::Rssfilter::Feed> for storing & retreiving feeds.
135              
136             It consumes the L<App::Rssfilter::Logger> role.
137              
138             =head1 ATTRIBUTES
139              
140             =head2 logger
141              
142             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.
143              
144             =head2 path
145              
146             This is the directory path to the stored feed file. If not specified, the current working directory will be used. It is coerced into a L<Path::Class::Dir> object, if it is a string specifying an absolute or relative directory path, or an array or arrayref of directory names (which will be joined to form a directory path).
147              
148             =head2 name
149              
150             This is the name of the feed, and will be used as the filename to store the feed under.
151              
152             =head2 last_modified
153              
154             This is the last time the stored RSS feed was saved, as a HTTP date string suitable for use in a C<Last-Modified> header. If the feed has never been saved, returns C<Thu, 01 Jan 1970 00:00:00 GMT>. It cannot be set from the constructor.
155              
156             =head1 METHODS
157              
158             =head2 path_push
159              
160             my $new_fs = $fs->path_push( @paths );
161              
162             Returns a clone of this object whose path has had C<@paths> appended to it.
163              
164             =head2 set_name
165              
166             my $new_fs = $fs->set_name( $new_name );
167              
168             Returns this object if its name is already C<$new_name>, else returns a clone of this object with its name set to C<$name>.
169              
170             =head2 load_existing
171              
172             print $fs->load_existing->to_string;
173              
174             Returns a L<Mojo::DOM> object initialised with the content of the previously-saved feed. If the feed has never been saved, returns a L<Mojo::DOM> object initialised with an empty string.
175              
176             =head2 save_feed
177              
178             $fs->save_feed( Mojo::DOM->new( '<rss> ... </rss>' ) );
179              
180             Saves a L<Mojo::DOM> object (or anything with a C<to_string> method), and updates C<last_modified()>.
181              
182             =head1 AUTHOR
183              
184             Daniel Holz <dgholz@gmail.com>
185              
186             =head1 COPYRIGHT AND LICENSE
187              
188             This software is copyright (c) 2015 by Daniel Holz.
189              
190             This is free software; you can redistribute it and/or modify it under
191             the same terms as the Perl 5 programming language system itself.
192              
193             =cut