File Coverage

blib/lib/Template/Plugin/MARC.pm
Criterion Covered Total %
statement 64 64 100.0
branch 15 16 93.7
condition n/a
subroutine 14 14 100.0
pod 5 5 100.0
total 98 99 98.9


line stmt bran cond sub pod time code
1             package Template::Plugin::MARC;
2              
3 1     1   118145 use 5.010000;
  1         4  
  1         40  
4 1     1   6 use strict;
  1         2  
  1         606  
5 1     1   7 use warnings;
  1         6  
  1         51  
6              
7             =head1 NAME
8              
9             Template::Plugin::MARC - Template::Toolkit plugin to make MARC friendly
10              
11             =head1 SYNOPSIS
12              
13             [% USE record = MARC(mymarc) %]
14            

[% record.f245.sa %]

15             [% record.f245.all %]
16             [% FOREACH link IN record.f856s %]
17             [% link.sy %]
18             [% END %]
19             [% FOREACH contents IN record.f505s %]
20             [% FOREACH subf IN contents.subfields %]
21             [% SWITCH subf.code %]
22             [% CASE 'a' %]
23             [% subf.value %]
24             [% CASE 't' %]
25             [% subf.value %]
26             [% CASE 'r' %]
27             [% subf.value %]
28             [% END %]
29             [% END %]
30             [% END %]
31             [% FOREACH subj IN record.f6xxs %]
32             [% subj.sa %]
33             [% END %]
34             [% FOREACH field IN record.fields %]
35             [% SWITCH field.tag %]
36             [% CASE '600' %]
37             Subject: [% field.all %] is what we are all about
38             [% CASE '700' %]
39             Co-author: [% field.all %], I presume?
40             [% END %]
41             [% END %]
42              
43             =head1 DESCRIPTION
44              
45             A Template::Toolkit plugin which given a MARC::Record object parses it into a
46             hash that can be accessed directly in Template::Toolkit.
47              
48             =head1 ACCESSORS
49              
50             By using some clever AUTOLOAD acrobatics, this plugin offers the user six
51             types of accessors.
52              
53             =head2 Direct accessors
54              
55             [% record.f245.sa %]
56            
57             print $record->f245->sa;
58              
59             By prefixing field numbers with an 'f' and subfield codes with an 's', the first
60             field/subfield with a given tag/code can be accessed.
61              
62             =head2 Concatenated accessors
63              
64             [% record.f245.all %]
65            
66             print $record->f245->all;
67              
68             A string consisting of all subfields concatenated together is accessible through
69             the all member of field objects.
70              
71             =head2 Subfield iterators
72              
73             [% FOREACH subfield IN record.f245.subfields %]
74             [% subfield.code %] = [% subfield.value %]
75             [% END %]
76              
77             foreach my $subfield ($record->f245) {
78             print $subfield->code, ' = ', $subfield->value;
79             }
80              
81             Subfield iterators are accessible through the subfields member of field objects.
82              
83             =head2 Field iterators
84              
85             [% FOREACH field IN record.f500s %]
86             [% field.all %]
87             [% END %]
88              
89             foreach my $field ($record->f500s) {
90             print $field->all;
91             }
92              
93             Field iterators are accessible by adding an 's' to the end of field names:
94             f500s, etc.
95              
96             =head2 Section iterators
97              
98             [% FOREACH field IN record.f5xxs %]
99             [% field.all %]
100             [% END %]
101              
102             foreach my $field ($record->f5xxs) {
103             print $field->all;
104             }
105              
106             All the fields in a section (identified by the first digit of the tag) can
107             be accessed with 'fNxxs' and then iterated through.
108              
109             =head2 Complete field list
110              
111             [% FOREACH field IN record.fields %]
112             [% field.all %]
113             [% END %]
114              
115             foreach my $field ($record->fields) {
116             print $field->all;
117             }
118              
119             All the fields in a record can be accessed via the fields object method.
120              
121             =head1 WHAT THIS PLUGIN DOES NOT DO
122              
123             This plugin will not sanity-check your code to make sure that you are accessing
124             fields and subfields with proper allowances for repetition. If you access a value
125             using [% record.f505.st %] it is presumed that was intentional, and there will be
126             no warning or error of any sort.
127              
128             However, the flip-side of this is that this plugin will not dictate your code
129             style. You can access the data using direct (non-repeatable) accessors, by
130             iterating over subfields, by iterating over subfields of a specific tag, by
131             iterating over fields in a particular block (0xx, 1xx, 2xx, etc.), or by
132             iterating over all fields.
133              
134             =cut
135              
136 1     1   4 use MARC::Record;
  1         2  
  1         42  
137 1     1   5 use MARC::Field;
  1         2  
  1         27  
138              
139 1     1   769 use Template::Plugin;
  1         658  
  1         30  
140 1     1   7 use base qw( Template::Plugin );
  1         3  
  1         71  
141 1     1   596 use Template::Plugin::MARC::Field;
  1         3  
  1         479  
142              
143             our $VERSION = '0.04';
144              
145             our $AUTOLOAD;
146              
147             =head1 METHODS
148              
149             =head2 load
150              
151             Used by Template::Toolkit for loading this plugin.
152              
153             =cut
154              
155             sub load {
156 2     2 1 97016 my ($class, $context) = @_;
157 2         12 return $class;
158             }
159              
160             =head2 new
161              
162             Instantiates a new object for the given MARC::Record. Can be called
163             using any of the following declarations:
164              
165             [% USE MARC(mymarc) %]
166             [% USE marc(mymarc) %]
167             [% USE MARC mymarc %]
168             [% USE MARC(marc=mymarc) %]
169             [% USE MARC marc=mymarc %]
170              
171             When run from Perl, the object can be created with either of the following
172             two calling conventions:
173              
174             $record = Template::Plugin::MARC->new({}, $marc, [\%config]);
175             $record = Template::Plugin::MARC->new([$context], { marc => $marc });
176              
177             The $context hashref passed as the first argument is mandatory when using
178             positional parameters and optional when using named parameters.
179              
180             =cut
181              
182             sub new {
183 3 100   3 1 33 my $config = ref($_[-1]) eq 'HASH' ? pop(@_) : { };
184 3         8 my ($class, $context, $marc) = @_;
185              
186             # marc can be a positional or named argument
187 3 100       13 $marc = $config->{'marc'} unless defined $marc;
188              
189 3         20 return bless {
190             %$config,
191             marc => $marc,
192             }, $class;
193             }
194              
195             =head2 init
196              
197             Initializes the MARC object. This is called only on the first access attempt
198             on the object, to avoid unnecessary processing.
199              
200             =cut
201              
202             sub init {
203 20     20 1 50 my $self = shift;
204 20 100       66 return $self if $self->{'record'};
205              
206 2         7 my $recordhash = { fields => [] };
207              
208 2 50       10 if ( ref $self->{'marc'} eq 'MARC::Record' ) {
209 2         15 foreach my $field ($self->{'marc'}->fields()) {
210 18         80 my $fieldobj = Template::Plugin::MARC::Field->new($field);
211 18         99 my $tag = $fieldobj->tag();
212 18         44 my $section = 'f' . substr($tag, 0, 1) . 'xxs';
213 18 100       74 $recordhash->{"f$tag"} = $fieldobj unless $recordhash->{"f$tag"};
214 18 100       66 $recordhash->{"f$tag" . 's'} = [] unless $recordhash->{"f$tag" . 's'};
215 18         21 push @{$recordhash->{"f$tag" . 's'}}, $fieldobj;
  18         62  
216 18 100       60 $recordhash->{"$section"} = [] unless $recordhash->{"$section"};
217 18         22 push @{$recordhash->{"$section"}}, $fieldobj;
  18         35  
218 18         21 push @{$recordhash->{'fields'}}, $fieldobj;
  18         49  
219             }
220             }
221              
222 2         7 $self->{'record'} = $recordhash;
223 2         5 return $self;
224             }
225              
226             =head2 filter
227              
228             $record->filter({ '4' => 'edt' })->[0]->sa
229              
230             [% record.filter('4'='edt').0.sa
231              
232             Filters a set of fields according to the specified criteria
233              
234             =cut
235              
236             sub filter {
237 6     6 1 11 my ($self, $selectors) = @_;
238              
239 6         12 $self->init();
240              
241 6         10 my $fields = $self->{'record'}->{'fields'};
242 6         19 foreach my $selector (keys %$selectors) {
243 6         8 my $possibilities = [];
244 6         11 foreach my $testfield (@$fields) {
245 47 100       128 push @$possibilities, $testfield if $testfield->has($selector, $selectors->{$selector});
246             }
247 6         15 $fields = $possibilities;
248             }
249              
250 6         47 return $fields;
251             }
252              
253             =head2 marc
254              
255             Returns the MARC::Record object associated with the instance.
256              
257             =cut
258              
259             sub marc {
260 2     2 1 547 my $self = shift;
261 2         20 return $self->{'marc'};
262             }
263              
264             sub AUTOLOAD {
265 14     14   651 my $self = shift;
266 14         70 (my $a = $AUTOLOAD) =~ s/.*:://;
267              
268 14         117 $self->init;
269            
270 14         133 return $self->{'record'}->{"$a"};
271             }
272              
273             1;
274             __END__