root/trunk/plagger/lib/Plagger/Plugin.pm

Revision 2057 (checked in by tokuhirom, 3 years ago)

Plagger::Plugin: follw symlinks in assets_dir

  • Property svn:keywords set to Id Revision
Line 
1 package Plagger::Plugin;
2 use strict;
3 use base qw( Class::Accessor::Fast );
4
5 __PACKAGE__->mk_accessors( qw(conf rule rule_hook cache) );
6
7 use Plagger::Cookies;
8 use Plagger::Crypt;
9 use Plagger::Rule;
10 use Plagger::Rules;
11
12 use FindBin;
13 use File::Find::Rule ();
14 use File::Spec;
15 use Scalar::Util qw(blessed);
16
17 sub new {
18     my($class, $opt) = @_;
19     my $self = bless {
20         conf => $opt->{config} || {},
21         rule => $opt->{rule},
22         rule_op => $opt->{rule_op} || 'AND',
23         rule_hook => '',
24         meta => {},
25     }, $class;
26     $self->init();
27     $self;
28 }
29
30 sub init {
31     my $self = shift;
32
33     if (my $rule = $self->{rule}) {
34         $rule = [ $rule ] if ref($rule) eq 'HASH';
35         my $op = $self->{rule_op};
36         $self->{rule} = Plagger::Rules->new($op, @$rule);
37     } else {
38         $self->{rule} = Plagger::Rule->new({ module => 'Always' });
39     }
40
41     $self->walk_config_encryption();
42 }
43
44 sub walk_config_encryption {
45     my $self = shift;
46     my $conf = $self->conf;
47
48     $self->do_walk($conf);
49 }
50
51 sub do_walk {
52     my($self, $data) = @_;
53     return unless defined($data) && ref $data;
54
55     if (ref($data) eq 'HASH') {
56         for my $key (keys %$data) {
57             if ($key =~ /password/) {
58                 $self->decrypt_config($data, $key);
59             }
60             $self->do_walk($data->{$key});
61         }
62     } elsif (ref($data) eq 'ARRAY') {
63         for my $value (@$data) {
64             $self->do_walk($value);
65         }
66     }
67 }
68
69 sub decrypt_config {
70     my($self, $data, $key) = @_;
71
72     my $context = Plagger->context;
73     my $decrypted = Plagger::Crypt->decrypt($data->{$key});
74     if ($decrypted eq $data->{$key}) {
75         $context->add_rewrite_task($key, $decrypted, Plagger::Crypt->encrypt($decrypted, $context->conf->{encrypt} || 'base64'));
76     } else {
77         $data->{$key} = $decrypted;
78     }
79 }
80
81 sub conf { $_[0]->{conf} }
82 sub rule { $_[0]->{rule} }
83
84 sub dispatch_rule_on {
85     my($self, $hook) = @_;
86     $self->rule_hook && $self->rule_hook eq $hook;
87 }
88
89 sub class_id {
90     my $self = shift;
91
92     my $pkg = ref($self) || $self;
93        $pkg =~ s/Plagger::Plugin:://;
94     my @pkg = split /::/, $pkg;
95
96     return join '-', @pkg;
97 }
98
99 # subclasses may overload to avoid cache sharing
100 sub plugin_id {
101     my $self = shift;
102     $self->class_id;
103 }
104
105 sub assets_dir {
106     my $self = shift;
107     my $context = Plagger->context;
108
109     if ($self->conf->{assets_path}) {
110         return $self->conf->{assets_path}; # look at config:assets_path first
111     }
112
113     my $assets_base =
114         $context->conf->{assets_path} ||              # or global:assets_path
115         File::Spec->catfile($FindBin::Bin, "assets"); # or "assets" under plagger script
116
117     return File::Spec->catfile(
118         $assets_base, "plugins", $self->class_id,
119     );
120 }
121
122 sub log {
123     my $self = shift;
124     Plagger->context->log(@_, caller => ref($self));
125 }
126
127 sub cookie_jar {
128     my $self = shift;
129
130     my $agent_conf = Plagger->context->conf->{user_agent} || {};
131     if ($agent_conf->{cookies}) {
132         return Plagger::Cookies->create($agent_conf->{cookies});
133     }
134
135     return $self->cache->cookie_jar;
136 }
137
138 sub templatize {
139     my($self, $file, $vars) = @_;
140
141     my $context = Plagger->context;
142     $vars->{context} ||= $context;
143
144     my $template = Plagger::Template->new($context, $self);
145     $template->process($file, $vars, \my $out) or $context->error($template->error);
146
147     $out;
148 }
149
150 sub load_assets {
151     my($self, $rule, $callback) = @_;
152
153     unless (blessed($rule) && $rule->isa('File::Find::Rule')) {
154         $rule = File::Find::Rule->name($rule)->extras({follow => 1});
155     }
156
157     # ignore .svn directories
158      $rule->or(
159          $rule->new->directory->name('.svn')->prune->discard,
160          $rule->new,
161      );
162
163     # $rule isa File::Find::Rule
164     for my $file ($rule->in($self->assets_dir)) {
165         my $base = File::Basename::basename($file);
166         $callback->($file, $base);
167     }
168 }
169
170 1;
171
172 __END__
173
174 =head1 NAME
175
176 Plagger::Plugin - Base class for Plagger Plugins
177
178 =head1 SYNOPSIS
179
180   package Plagger::Plugin::Something;
181   use base qw(Plagger::Plugin);
182
183   # register hooks
184   sub register {
185     my ($self, $context) = @_;
186     $context->register_hook( $self,
187        'thingy.wosit'  => $self->can('doodad'),
188     )
189   }
190
191   sub doodad { ... }
192
193 =head1 DESCRIPTION
194
195 This is the base class for plagger plugins.  Pretty much everything is done
196 by plugins in Plagger.
197
198 To write a new plugin, simply inherit from Plagger::Plugin:
199
200   package Plagger::Plugin;
201   use base qw(Plagger::Plugin);
202
203 Then register some hooks:
204
205   # register hooks
206   sub register {
207     my ($self, $context) = @_;
208     $context->register_hook( $self,
209        'thingy.wosit'  => $self->can('doodad'),
210     )
211   }
212
213
214 This means that the "doodad" method will be called at the
215 "thingy.wosit" stage.
216
217 There is a handy L<tools/plugin-start.pl> tool that creates the
218 template of I<.pm> file, dependency YAML file and test files for you.
219
220   > ./tools/plugin-start.pl Foo::Bar
221
222 =head2 Methods
223
224 =over
225
226 =item new
227
228 Standard constructor.  Calls init.
229
230 =item init
231
232 Initializes the plugin
233
234 =item walk_config_encryption
235
236 =item do_walk
237
238 =item decrypt_config
239
240 =item conf
241
242 =item rule
243
244 =item rule_hook
245
246 =item cache
247
248 =item dispatch_rule_on
249
250 =item class_id
251
252 =item assets_dir
253
254 =item log
255
256 =item cookie_jar
257
258 Access the Plagger::Cookies object.
259
260 =item templatize
261
262 =item load_assets
263
264 =back
265
266 =head1 AUTHOR
267
268 Tatsuhiko Miyagawa E<lt>miyagawa@bulknews.netE<gt>
269
270 See I<AUTHORS> file for the name of all the contributors.
271
272 =head1 LICENSE
273
274 Except where otherwise noted, Plagger is free software; you can
275 redistribute it and/or modify it under the same terms as Perl itself.
276
277 =head1 SEE ALSO
278
279 L<http://plagger.org/>
280
281 =cut
Note: See TracBrowser for help on using the browser.