Bug 17600: Standardize our EXPORT_OK
[srvgit] / Koha / Filter / MARC / ViewPolicy.pm
1 package Koha::Filter::MARC::ViewPolicy;
2
3 # Copyright 2015 Mark Tompsett
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20 =head1 NAME
21
22 Koha::Filter::MARC::ViewPolicy - this filters a MARC record.
23
24 =head1 VERSION
25
26 version 1.0
27
28 =head1 SYNOPSIS
29
30 my $processor = Koha::RecordProcessor->new( { filters => ('ViewPolicy') } );
31
32 =head1 DESCRIPTION
33
34 Filter to remove fields based on the 'Advance constraints'
35 settings found when editing a particular subfield definition of
36 a MARC bibliographic framework found under the Koha administration
37 menu.
38
39 =cut
40
41 use Modern::Perl;
42 use C4::Biblio qw( GetMarcStructure );
43
44 use base qw(Koha::RecordProcessor::Base);
45 our $NAME    = 'MARC_ViewPolicy';
46 our $VERSION = '3.23';              # Master version I hope it gets in.
47
48 use constant FIRST_NONCONTROL_TAG => 10;    # tags < 10 are control tags.
49
50 =head1 SUBROUTINES/METHODS
51
52 =head2 filter
53
54     my $processor = Koha::RecordProcessor->new( { filters => ('ViewPolicy') } );
55 ...
56     my $newrecord = $processor->filter($record);
57     my $newrecords = $processor->filter(\@records);
58
59 This returns a filtered copy of the record based on the Advanced constraints
60 visibility settings.
61
62 =cut
63
64 sub filter {
65     my $self    = shift;
66     my $precord = shift;
67     my @records;
68
69     if ( !$precord ) {
70         return $precord;
71     }
72
73     if ( ref($precord) eq 'ARRAY' ) {
74         @records = @{$precord};
75     }
76     else {
77         push @records, $precord;
78     }
79
80     my $params = $self->params;
81     my $interface     = $params->{options}->{interface} // 'opac';
82     my $frameworkcode = $params->{options}->{frameworkcode} // q{};
83
84     foreach my $current_record (@records) {
85         my $result        = $current_record;
86         my $hide          = _should_hide_on_interface();
87
88         my $marcsubfieldstructure = C4::Biblio::GetMarcStructure( 0, $frameworkcode, { unsafe => 1 } );
89
90         #if ($marcsubfieldstructure->{'000'}->{'@'}->{hidden}>0) {
91         # LDR field is excluded from $current_record->fields().
92         # if we hide it here, the MARCXML->MARC::Record->MARCXML
93         # transformation blows up.
94         #}
95         foreach my $field ( $result->fields() ) {
96             _filter_field(
97                 {
98                     field                 => $field,
99                     marcsubfieldstructure => $marcsubfieldstructure,
100                     hide                  => $hide,
101                     interface             => $interface,
102                     result                => $result
103                 }
104             );
105         }
106     }
107     return;
108 }
109
110 sub _filter_field {
111     my ($parameter) = @_;
112
113     my $field                 = $parameter->{field};
114     my $marcsubfieldstructure = $parameter->{marcsubfieldstructure};
115     my $hide                  = $parameter->{hide};
116     my $interface             = $parameter->{interface};
117     my $result                = $parameter->{result};
118
119     my $tag = $field->tag();
120     if ( $tag >= FIRST_NONCONTROL_TAG ) {
121         foreach my $subpairs ( $field->subfields() ) {
122             my ( $subtag, $value ) = @{$subpairs};
123
124             # visibility is a "level" (-9 to +9), default to 0
125             # -8 is flagged, and 9/-9 are not implemented.
126             my $visibility =
127               $marcsubfieldstructure->{$tag}->{$subtag}->{hidden};
128             $visibility //= 0;
129             if ( $hide->{$interface}->{$visibility} ) {
130
131                 # deleting last subfield doesn't delete field, so
132                 # this detects that case to delete the field.
133                 if ( scalar $field->subfields() <= 1 ) {
134                     $result->delete_fields($field);
135                 }
136                 else {
137                     $field->delete_subfield( code => $subtag );
138                 }
139             }
140         }
141     }
142
143     # control tags don't have subfields, use @ trick.
144     else {
145         # visibility is a "level" (-9 to +9), default to 0
146         # -8 is flagged, and 9/-9 are not implemented.
147         my $visibility = $marcsubfieldstructure->{$tag}->{q{@}}->{hidden};
148         $visibility //= 0;
149         if ( $hide->{$interface}->{$visibility} ) {
150             $result->delete_fields($field);
151         }
152
153     }
154     return;
155 }
156
157 # Copied and modified from 3.10.x help file
158 # marc_subfields_structure.hidden
159 # allows you to select from 19 possible visibility conditions, 17 of which are implemented. They are the following:
160 # -9 => Future use
161 # -8 => Flag
162 # -7 => OPAC !Intranet !Editor Collapsed
163 # -6 => OPAC Intranet !Editor !Collapsed
164 # -5 => OPAC Intranet !Editor Collapsed
165 # -4 => OPAC !Intranet !Editor !Collapsed
166 # -3 => OPAC !Intranet Editor Collapsed
167 # -2 => OPAC !Intranet Editor !Collapsed
168 # -1 => OPAC Intranet Editor Collapsed
169 # 0 => OPAC Intranet Editor !Collapsed
170 # 1 => !OPAC Intranet Editor Collapsed
171 # 2 => !OPAC !Intranet Editor !Collapsed
172 # 3 => !OPAC !Intranet Editor Collapsed
173 # 4 => !OPAC Intranet Editor !Collapsed
174 # 5 => !OPAC !Intranet !Editor Collapsed
175 # 6 => !OPAC Intranet !Editor !Collapsed
176 # 7 => !OPAC Intranet !Editor Collapsed
177 # 8 => !OPAC !Intranet !Editor !Collapsed
178 # 9 => Future use
179 # ( ! means 'not visible' or in the case of Collapsed 'not Collapsed')
180
181 sub _should_hide_on_interface {
182     my $hide = {
183         opac => {
184             '-8' => 1,
185             '1'  => 1,
186             '2'  => 1,
187             '3'  => 1,
188             '4'  => 1,
189             '5'  => 1,
190             '6'  => 1,
191             '7'  => 1,
192             '8'  => 1,
193         },
194         intranet => {
195             '-8' => 1,
196             '-7' => 1,
197             '-4' => 1,
198             '-3' => 1,
199             '-2' => 1,
200             '2'  => 1,
201             '3'  => 1,
202             '5'  => 1,
203             '8'  => 1,
204         },
205     };
206     return $hide;
207 }
208
209 =head2 should_hide_marc
210
211 Return a hash reference of whether a field, built from
212 kohafield and tag, is hidden (1) or not (0) for a given
213 interface
214
215   my $OpacHideMARC =
216     should_hide_marc( {
217                         frameworkcode => $frameworkcode,
218                         interface     => 'opac',
219                       } );
220
221   if ($OpacHideMARC->{'stocknumber'}==1) {
222        print "Hidden!\n";
223   }
224
225 C<$OpacHideMARC> is a ref to a hash which contains a series
226 of key value pairs indicating if that field (key) is
227 hidden (value == 1) or not (value == 0).
228
229 C<$frameworkcode> is the framework code.
230
231 C<$interface> is the interface. It defaults to 'opac' if
232 nothing is passed. Valid values include 'opac' or 'intranet'.
233
234 =cut
235
236 sub should_hide_marc {
237     my ( $self, $parms ) = @_;
238     my $frameworkcode = $parms->{frameworkcode} // q{};
239     my $interface     = $parms->{interface}     // 'opac';
240     my $hide          = _should_hide_on_interface();
241
242     my %shouldhidemarc;
243     my $marc_subfield_structure = GetMarcStructure( 0, $frameworkcode );
244     foreach my $tag ( keys %{$marc_subfield_structure} ) {
245         foreach my $subtag ( keys %{ $marc_subfield_structure->{$tag} } ) {
246             my $subfield_record = $marc_subfield_structure->{$tag}->{$subtag};
247             if ( ref $subfield_record eq 'HASH' ) {
248                 my $kohafield = $subfield_record->{'kohafield'};
249                 if ($kohafield) {
250                     my @tmpsplit   = split /[.]/xsm, $kohafield;
251                     my $field      = $tmpsplit[-1];
252                     my $hidden     = $subfield_record->{'hidden'};
253                     my $shouldhide = $hide->{$interface}->{$hidden};
254                     if ($shouldhide) {
255                         $shouldhidemarc{$field} = 1;
256                     }
257                     elsif ( !exists $shouldhidemarc{$field} ) {
258                         $shouldhidemarc{$field} = 0;
259                     }
260                 }
261             }
262         }
263     }
264
265     return \%shouldhidemarc;
266 }
267
268 =head1 DIAGNOSTICS
269
270  $ prove -v t/RecordProcessor.t
271  $ prove -v t/db_dependent/Filter_MARC_ViewPolicy.t
272
273 =head1 CONFIGURATION AND ENVIRONMENT
274
275 Install Koha. This filter will be used appropriately by the OPAC or staff interface.
276
277 =head1 INCOMPATIBILITIES
278
279 This is designed for MARC::Record filtering currently. It will not handle MARC::MARCXML.
280
281 =head1 DEPENDENCIES
282
283 The following Perl libraries are required: Modern::Perl and Carp.
284 The following Koha libraries are required: C4::Biblio, Koha::RecordProcessor, and Koha::RecordProcessor::Base.
285 These should all be installed if the koha-common package is installed or Koha is otherwise installed.
286
287 =head1 BUGS AND LIMITATIONS
288
289 This is the initial version. Please feel free to report bugs
290 at http://bugs.koha-community.org/.
291
292 =head1 AUTHOR
293
294 Mark Tompsett
295
296 =head1 LICENSE AND COPYRIGHT
297
298 Copyright 2015 Mark Tompsett
299
300 This file is part of Koha.
301
302 Koha is free software; you can redistribute it and/or modify it
303 under the terms of the GNU General Public License as published by
304 the Free Software Foundation; either version 3 of the License, or
305 (at your option) any later version.
306
307 Koha is distributed in the hope that it will be useful, but
308 WITHOUT ANY WARRANTY; without even the implied warranty of
309 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
310 GNU General Public License for more details.
311
312 You should have received a copy of the GNU General Public License
313 along with Koha; if not, see <http://www.gnu.org/licenses>.
314
315 =cut
316
317 1;