File Coverage

lib/Path/IsDev/Object.pm
Criterion Covered Total %
statement 54 66 81.8
branch 6 10 60.0
condition n/a
subroutine 14 15 93.3
pod 2 2 100.0
total 76 93 81.7


line stmt bran cond sub pod time code
1 12     12   7156 use 5.008; # utf8
  12         43  
  12         546  
2 12     12   68 use strict;
  12         24  
  12         452  
3 12     12   64 use warnings;
  12         25  
  12         415  
4 12     12   3246 use utf8;
  12         51  
  12         89  
5              
6             package Path::IsDev::Object;
7              
8             our $VERSION = '1.001002';
9              
10             # ABSTRACT: Object Oriented guts for IsDev export
11              
12             our $AUTHORITY = 'cpan:KENTNL'; # AUTHORITY
13              
14              
15              
16              
17              
18              
19              
20              
21              
22              
23              
24              
25              
26             our $ENV_KEY_DEBUG = 'PATH_ISDEV_DEBUG';
27             our $DEBUG = ( exists $ENV{$ENV_KEY_DEBUG} ? $ENV{$ENV_KEY_DEBUG} : undef );
28              
29             our $ENV_KEY_DEFAULT = 'PATH_ISDEV_DEFAULT_SET';
30             our $DEFAULT =
31             ( exists $ENV{$ENV_KEY_DEFAULT} ? $ENV{$ENV_KEY_DEFAULT} : 'Basic' );
32              
33              
34              
35              
36              
37              
38              
39              
40              
41             use Class::Tiny 0.010 {
42 10         1508 set => sub { $DEFAULT },
43 11         2838 set_prefix => sub { 'Path::IsDev::HeuristicSet' },
44             set_module => sub {
45 11         4994 require Module::Runtime;
46 11         4530 return Module::Runtime::compose_module_name( $_[0]->set_prefix => $_[0]->set );
47             },
48             loaded_set_module => sub {
49 11         12834 require Module::Runtime;
50 11         19765 return Module::Runtime::use_module( $_[0]->set_module );
51             },
52 12     12   17131 };
  12         49445  
  12         226  
53              
54              
55              
56              
57              
58              
59              
60              
61              
62              
63              
64              
65              
66              
67              
68              
69              
70              
71              
72             my $instances = {};
73             my $instance_id = 0;
74              
75 0     0   0 sub _carp { require Carp; goto &Carp::carp; }
  0         0  
76              
77              
78              
79              
80              
81              
82              
83              
84              
85              
86              
87              
88             sub _instance_id {
89 2     2   3242 my ($self) = @_;
90 2         16 require Scalar::Util;
91 2         12 my $addr = Scalar::Util::refaddr($self);
92 2 50       12 return $instances->{$addr} if exists $instances->{$addr};
93 2         19 $instances->{$addr} = sprintf '%x', $instance_id++;
94 2         9 return $instances->{$addr};
95             }
96              
97              
98              
99              
100              
101              
102              
103              
104              
105              
106              
107             sub _debug {
108 250     250   3563 my ( $self, $message ) = @_;
109              
110 250 50       1331 return unless $DEBUG;
111 0         0 my $id = $self->_instance_id;
112 0         0 return *STDERR->printf( qq{[Path::IsDev=%s] %s\n}, $id, $message );
113             }
114              
115              
116              
117              
118              
119              
120              
121              
122              
123              
124              
125              
126             sub _with_debug {
127 16     16   33 my ( $self, $code ) = @_;
128 16         1591 require Path::IsDev;
129             ## no critic (ProhibitNoWarnings)
130 12     12   13137 no warnings 'redefine';
  12         40  
  12         5741  
131             local *Path::IsDev::debug = sub {
132 229     229   1180 $self->_debug(@_);
133 16         95 };
134 16         56 return $code->();
135             }
136              
137              
138              
139              
140              
141              
142              
143              
144              
145              
146             sub BUILD {
147 11     11 1 2524 my ($self) = @_;
148 11 50       87 return $self unless $DEBUG;
149 0         0 $self->_debug('{');
150 0         0 $self->_debug( ' set => ' . $self->set );
151 0         0 $self->_debug( ' set_prefix => ' . $self->set_prefix );
152 0         0 $self->_debug( ' set_module => ' . $self->set_module );
153 0         0 $self->_debug( ' loaded_set_module => ' . $self->loaded_set_module );
154 0         0 $self->_debug('}');
155 0         0 return $self;
156             }
157              
158              
159              
160              
161              
162              
163              
164              
165              
166              
167              
168             sub _matches {
169 16     16   2272 my ( $self, $path ) = @_;
170 16         7349 require Path::IsDev::Result;
171 16         222 my $result_object = Path::IsDev::Result->new( path => $path );
172 16         111 my $result;
173             $self->_with_debug(
174             sub {
175              
176 16     16   448 $self->_debug( 'Matching ' . $result_object->path );
177 16         479 $result = $self->loaded_set_module->matches($result_object);
178             },
179 16         125 );
180 16 50       714 if ( !!$result != !!$result_object->result ) {
181 0         0 _carp(q[Result and Result Object missmatch]);
182             }
183 16         161 return $result_object;
184             }
185              
186              
187              
188              
189              
190              
191              
192              
193              
194              
195              
196             sub matches {
197 15     15 1 15433 my ( $self, $path ) = @_;
198              
199 15         63 my $result_object = $self->_matches($path);
200              
201 15 100       478 if ( not $result_object->result ) {
202 3         29 $self->_debug('no match found');
203 3         43 return;
204             }
205              
206 12         336 return $result_object->result;
207             }
208              
209             1;
210              
211             __END__
212              
213             =pod
214              
215             =encoding UTF-8
216              
217             =head1 NAME
218              
219             Path::IsDev::Object - Object Oriented guts for IsDev export
220              
221             =head1 VERSION
222              
223             version 1.001002
224              
225             =head1 SYNOPSIS
226              
227             use Path::IsDev::Object;
228              
229             my $dev = Path::IsDev::Object->new();
230             my $dev = Path::IsDev::Object->new( set => 'MySet' );
231              
232             if ( $dev->matches($path) ){
233             print "$path is dev";
234             }
235              
236             =head1 DESCRIPTION
237              
238             Exporting functions is handy for end users, but quickly
239             becomes a huge headache when you're trying to chain them.
240              
241             e.g: If you're writing an exporter yourself, and you want to wrap
242             responses from an exported symbol, while passing through user
243             configuration => Huge headache.
244              
245             So the exporter based interface is there for people who don't need anything fancy,
246             while the Object based interface is there for people with more complex requirements.
247              
248             =head1 METHODS
249              
250             =head2 C<matches>
251              
252             Determine if a given path satisfies the C<set>
253              
254             if( $o->matches($path) ){
255             print "We have a match!";
256             }
257              
258             =head1 ATTRIBUTES
259              
260             =head2 C<set>
261              
262             The name of the C<HeuristicSet::> to use.
263              
264             Default is C<Basic>, or the value of C<$ENV{PATH_ISDEV_DEFAULT_SET}>
265              
266             =head2 C<set_prefix>
267              
268             The C<HeuristicSet> prefix to use to expand C<set> to a module name.
269              
270             Default is C<Path::IsDev::HeuristicSet>
271              
272             =head2 C<set_module>
273              
274             The fully qualified module name.
275              
276             Composed by joining C<set> and C<set_prefix>
277              
278             =head2 C<loaded_set_module>
279              
280             An accessor which returns a module name after loading it.
281              
282             =head1 PRIVATE METHODS
283              
284             =head2 C<_instance_id>
285              
286             An opportunistic sequence number for help with debug messages.
287              
288             Note: This is not guaranteed to be unique per instance, only guaranteed
289             to be constant within the life of the object.
290              
291             Based on C<refaddr>, and giving out new ids when new C<refaddr>'s are seen.
292              
293             =head2 C<_debug>
294              
295             The debugger callback.
296              
297             export PATH_ISDEV_DEBUG=1
298              
299             to get debug info.
300              
301             =head2 C<_with_debug>
302              
303             Wrap calls to Path::IsDev::debug to have a prefix with an object identifier.
304              
305             $ob->_with_debug(sub{
306             # Path::Tiny::debug now localised.
307              
308             });
309              
310             =head2 C<BUILD>
311              
312             C<BUILD> is an implementation detail of C<Class::Tiny>.
313              
314             This module hooks C<BUILD> to give a self report of the object
315             to C<*STDERR> after C<< ->new >> when under C<$DEBUG>
316              
317             =head2 C<_matches>
318              
319             my $result = $o->matches( $path );
320              
321             $result here will be a constructed C<Path::IsDev::Result>.
322              
323             Note this method may be handy for debugging, but you should still call C<matches> for all real code.
324              
325             =begin MetaPOD::JSON v1.1.0
326              
327             {
328             "namespace":"Path::IsDev::Object",
329             "interface":"class",
330             "inherits":"Class::Tiny::Object"
331             }
332              
333              
334             =end MetaPOD::JSON
335              
336             =head1 AUTHOR
337              
338             Kent Fredric <kentfredric@gmail.com>
339              
340             =head1 COPYRIGHT AND LICENSE
341              
342             This software is copyright (c) 2014 by Kent Fredric <kentfredric@gmail.com>.
343              
344             This is free software; you can redistribute it and/or modify it under
345             the same terms as the Perl 5 programming language system itself.
346              
347             =cut