File Coverage

blib/lib/DDG/Block.pm
Criterion Covered Total %
statement 74 83 89.1
branch 21 30 70.0
condition n/a
subroutine 13 15 86.6
pod 5 8 62.5
total 113 136 83.0


line stmt bran cond sub pod time code
1             package DDG::Block;
2             our $AUTHORITY = 'cpan:DDG';
3             # ABSTRACT: Block to bundle plugins with triggers
4             $DDG::Block::VERSION = '1016';
5 10     10   61733 use Moo::Role;
  10         12722  
  10         46  
6 10     10   2377 use Carp;
  10         12  
  10         485  
7 10     10   1179 use Class::Load ':all';
  10         32055  
  10         1388  
8 10     10   3973 use POSIX qw(strftime);
  10         44572  
  10         43  
9              
10             requires qw(
11             request
12             );
13              
14             sub BUILD {
15 3     3 0 15 my ( $self ) = @_;
16 3         41 $self->_plugin_objs;
17             $self->trace('Loaded block',
18             ref $self,
19             map {
20 3 100       8 $_.':'.( $self->$_ ? 1 : 0 ),
  9         46  
21             } qw( return_one allow_missing_plugins allow_duplicate ),
22             );
23             }
24              
25              
26             has plugins => (
27             #isa => 'ArrayRef[Str|HashRef]',
28             is => 'ro',
29             lazy => 1,
30             builder => '_build_plugins',
31             );
32              
33 0     0   0 sub _build_plugins { die (ref shift)." requires plugins" }
34              
35              
36             has allow_missing_plugins => (
37             #isa => 'Bool',
38             is => 'ro',
39             default => sub { 0 },
40             );
41              
42              
43             has return_one => (
44             #isa => 'Bool',
45             is => 'ro',
46             default => sub { 1 },
47             );
48              
49              
50             has allow_duplicate => (
51             #isa => 'Bool',
52             is => 'ro',
53             default => sub { 0 },
54             );
55              
56              
57             has debug_trace => (
58             #isa => 'Bool',
59             is => 'ro',
60             default => sub { defined $ENV{DDG_BLOCK_TRACE} && $ENV{DDG_BLOCK_TRACE} ? 1 : 0 },
61             );
62              
63             sub trace {
64 596     596 0 415 my $self = shift;
65 596 50       1134 return unless $self->debug_trace;
66 0 0       0 print STDERR ("[".$self->trace_name."] ",join(" ",map { defined $_ ? $_ : 'undef' } @_),"\n");
  0         0  
67             }
68              
69 0     0 0 0 sub trace_name { ref(shift) }
70              
71              
72             has before_build => (
73             #isa => 'CodeRef',
74             is => 'ro',
75             predicate => 'has_before_build',
76             );
77              
78              
79             has after_build => (
80             #isa => 'CodeRef',
81             is => 'ro',
82             predicate => 'has_after_build',
83             );
84              
85              
86             has _plugin_objs => (
87             # like ArrayRef[ArrayRef[$trigger,DDG::Block::Plugin]]',
88             is => 'ro',
89             lazy => 1,
90             builder => '_build__plugin_objs',
91             );
92 34     34 1 439 sub plugin_objs { shift->_plugin_objs }
93              
94             sub _build__plugin_objs {
95 16     16   94 my ( $self ) = @_;
96 16         16 my @plugin_objs;
97 16         20 for (@{$self->plugins}) {
  16         207  
98 36         104 my $class;
99             my %args;
100 36 50       70 if (ref $_ eq 'HASH') {
101 0 0       0 croak "require a class key in hash" unless defined $_->{class};
102 0         0 $class = delete $_->{class};
103 0         0 %args = %{$_};
  0         0  
104             } else {
105 36         33 $class = $_;
106             }
107 36         29 my $plugin;
108 36 50       51 if (ref $class) {
109 0         0 $plugin = $class;
110             } else {
111 36 100       92 unless (try_load_class($class)) {
112 3 100       852 if ($self->allow_missing_plugins) {
113 2 100       8 if (ref $self->allow_missing_plugins eq 'CODE') {
114 1         5 $self->allow_missing_plugins->($self,$class);
115             }
116             } else {
117 1         14 die "Can't load plugin ".$class;
118             }
119 2         16 next;
120             }
121 33         4331 $args{block} = $self;
122 33 100       98 if ($self->has_before_build) {
123 8         12 for ($class) {
124 8         19 $self->before_build->($self,$class);
125             }
126             }
127 33         3608 $plugin = $class->new(\%args);
128             }
129 33 100       14268 if ($self->has_after_build) {
130 8         14 for ($plugin) {
131 8         20 $self->after_build->($self,$plugin);
132             }
133             }
134 33         2943 my @triggers = $self->get_triggers_of_plugin($plugin);
135 33 100       69 @triggers = $self->empty_trigger unless @triggers;
136 33         32 my @parsed_triggers;
137 33         48 for (@triggers) {
138 33         62 push @parsed_triggers, $self->parse_trigger($_);
139             }
140 33 50       132 push @plugin_objs, [
141             \@parsed_triggers,
142             $plugin,
143             ] if @parsed_triggers;
144             }
145 15         64 return \@plugin_objs;
146             }
147              
148              
149             has only_plugin_objs => (
150             is => 'ro',
151             lazy => 1,
152             builder => '_build_only_plugin_objs',
153             );
154             sub _build_only_plugin_objs {
155 1     1   28 my ( $self ) = @_;
156 1         1 my @plugins;
157 1         1 for (@{$self->_plugin_objs}) {
  1         12  
158 2         7 push @plugins, $_->[1];
159             }
160 1         3 return \@plugins;
161             }
162              
163              
164 31     31 1 26 sub get_triggers_of_plugin { shift; shift->get_triggers }
  31         83  
165              
166              
167 30     30 1 27 sub parse_trigger { shift; shift; }
  30         51  
168              
169              
170 2     2 1 4 sub empty_trigger { return undef }
171              
172              
173             sub handle_request_matches {
174 46     46 1 69 my ( $self, $plugin, $request, @args ) = @_;
175 46         71 my $plugin_class = ref $plugin;
176 46         120 $self->trace('Handle request matches:',$plugin_class,"'".$request->query_raw."'",@args);
177 46 50       91 unless ($self->allow_duplicate) {
178 46 100       30 if (grep { $_ eq $plugin_class } @{$request->seen_plugins}) {
  5         29  
  46         669  
179 1         3 $self->trace("The request already saw",$plugin_class);
180 1         3 return ();
181             }
182             }
183 45         42 push @{$request->seen_plugins}, $plugin_class;
  45         552  
184 45         265 my @results = $plugin->handle_request_matches($request, @args);
185 45         372 $self->trace("Got",scalar @results,"results");
186 45         104 return @results;
187             }
188              
189             around request => sub {
190             my $orig = shift;
191             my ( $self, $request ) = @_;
192             $self->trace( "Query raw:", "'".$request->query_raw."'" );
193             my @results = $orig->(@_);
194             $self->trace( "Query", "'".$request->query_raw."'", "produced", scalar @results, "results" );
195             return @results;
196             };
197              
198             1;
199              
200             __END__