File Coverage

blib/lib/WWW/Mechanize/Plugin/Cache.pm
Criterion Covered Total %
statement 19 21 90.4
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 26 28 92.8


line stmt bran cond sub pod time code
1             package WWW::Mechanize::Plugin::Cache;
2              
3             our $VERSION = '0.06';
4 2     2   94762 use base qw(Class::Accessor::Fast);
  2         5  
  2         1786  
5             __PACKAGE__->mk_accessors(qw(caching_initialized cache_args cache cached));
6              
7 2     2   13325 use warnings;
  2         5  
  2         62  
8 2     2   9 use strict;
  2         10  
  2         48  
9 2     2   12 use Carp;
  2         4  
  2         179  
10 2     2   4845 use Data::Dump::Streamer;
  2         149691  
  2         17  
11 2     2   2194 use Cache::FileCache;
  2         57494  
  2         81  
12 2     2   793 use WWW::Mechanize;
  0            
  0            
13              
14             my $prehook_closure = sub { prehook(@_) };
15             my $posthook_closure = sub { posthook(@_) };
16              
17             sub import { } # This plugin does not have any import options
18              
19             sub init {
20             my ($class, $pluggable, %args) = @_;
21              
22             # Set up the one-time pre-hook.
23             $pluggable->pre_hook('get', $prehook_closure);
24             $pluggable->post_hook('get', $posthook_closure);
25              
26             {
27             no strict 'refs';
28             # Used to capture the cache arguments on the current statement.
29             *{caller(). '::cache_args'} = \&cache_args;
30              
31             # Whether or not a given request came from the cache.
32             *{caller(). '::cached'} = \&cached;
33              
34             # The cache object itself.
35             *{caller(). '::cache'} = \&cache;
36              
37             # Whether or not the Mech object is sufficiently set up to
38             # allow caching to work.
39             *{caller(). '::caching_initialized'} = \&caching_initialized;
40             }
41              
42             # Grab the arguments now, and process them later.
43             $pluggable->cache_args($args{'cache'});
44              
45             # Note that the Mech object is not yet initialized enough to
46             # support caching.
47             $pluggable->caching_initialized(0);
48              
49             # And we've processed this.
50             return qw(cache);
51             }
52              
53             sub _make_cache_key {
54             # We'll just use the URL as the key, since that's what we have.
55             my ($pluggable, $mech, @args) = @_;
56             return $args[0];
57             }
58              
59             sub _create_cache {
60             my($pluggable, $args) = @_;
61              
62             if ($args) {
63             # We have a cache argument.
64             if (ref $args) {
65             # It points to something that might be a cache.
66             if ( $args->isa('Cache::FileCache')) {
67             # Yes, it is. Set up the cache.
68             $pluggable->cache($args);
69             }
70             else {
71             # Not a good cache object.
72             die "The supplied object is not a valid cache\n";
73             }
74             }
75             elsif ($args) {
76             # A true value, which means "start caching, dude."
77             # Buld a new cache.
78             my $cache = Cache::FileCache->new(
79             {default_expires_in => "1d",
80             namespace => 'www-mechanize-cached'},
81             );
82             # Save it in the Mech::Pluggable object.
83             $pluggable->cache($cache);
84             }
85             }
86             }
87              
88             sub prehook {
89             my ($pluggable, $mech, @args) = @_;
90              
91             # Are we supposed to have a cache?
92             if (my $args = $pluggable->cache_args) {
93             $pluggable->cache(_create_cache($pluggable, $args));
94              
95             # Don't create the cache again.
96             $pluggable->cache_args(0);
97             }
98              
99             # Is there a cache available?
100             if (my $cache = $pluggable->cache) {
101             my $cache_key = _make_cache_key(@_);
102             my $cached = $cache->get($cache_key);
103            
104             # Did we find the current request in the cache?
105             if ($cached) {
106             if (!$pluggable->caching_initialized) {
107             $pluggable->caching_initialized(1);
108             # Commit enough surgery on the Mech object to
109             # get all of it methods to work even without a
110             # real get.
111             #
112             # Currently we're not doing anything...
113             }
114             # Yes. Return it and don't call the method.
115             $mech->get('file://.');
116             $mech->update_html($cached);
117             $pluggable->cached(1);
118             return -1;
119             }
120             else {
121             # No. Go ahead and call the method.
122             $pluggable->cached(0);
123             return 0;
124             }
125             }
126             # If there was no cache, just return as usual.
127             else {
128             return 0;
129             }
130             }
131              
132             sub posthook {
133             my($pluggable, $mech, @args) = @_;
134             # If we got to this point, we've actually
135             # done either a get or a submit_form. We
136             # should save the current page, unless it's
137             # already in the cache.
138             unless ($pluggable->cached) {
139             # It's not in the cache. Save it --
140             # if there actually *IS* a cache.
141             my $cache = $pluggable->cache;
142             if ($cache) {
143             $cache->set($args[0],$mech->content);
144             # Don't mark it, because we haven't
145             # tried to fetch it from the cache.
146             # We've only stored it.
147             }
148             }
149             }
150              
151             1; # Magic true value required at end of module
152             __END__