Bug 22155: Adapt uses of biblio_metadata.marcflavour to schema
[koha.git] / misc / migration_tools / switch_marc21_series_info.pl
1 #!/usr/bin/perl
2
3 # Copyright 2013 Michael Hafen <mdhafen@tech.washk12.org>
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 use strict;
21 use warnings;
22
23 # Script to switch the MARC21 440$anv and 490$av information
24
25 BEGIN {
26     # find Koha's Perl modules
27     # test carefully before changing this
28     use FindBin;
29     eval { require "$FindBin::Bin/../kohalib.pl" };
30 }
31
32 use C4::Biblio;
33 use C4::Context;
34 use Getopt::Long;
35
36 my $commit;
37 my $add_links;
38 my $update_frameworks;
39 my $show_help;
40 my $verbose;
41 my $result = GetOptions(
42     'c'      => \$commit,
43     'l'      => \$add_links,
44     'f'      => \$update_frameworks,
45     'h|help' => \$show_help,
46     'v'      => \$verbose,
47     );
48
49 # warn and exit if we're running UNIMARC
50 if (C4::Context->preference('MARCFLAVOUR') eq 'UNIMARC') {
51     print "This script is useless when you're running UNIMARC\n";
52     exit 0;
53 }
54 if ( ! $result || $show_help ) {
55     print_usage();
56     exit 0;
57 }
58
59 my $dbh = C4::Context->dbh;
60
61 my $count_sth = $dbh->prepare(
62     q|
63     SELECT COUNT(biblionumber)
64     FROM biblio_metadata
65     WHERE format='marcxml'
66         AND `schema`=?
67         AND (
68             ExtractValue(metadata,'//datafield[@tag="440"]/subfield[@code="a"]')
69                 OR ExtractValue(metadata,'//datafield[@tag="440"]/subfield[@code="v"]')
70                 OR ExtractValue(metadata,'//datafield[@tag="440"]/subfield[@code="n"]')
71                 OR ExtractValue(metadata,'//datafield[@tag="490"]/subfield[@code="a"]')
72                 OR ExtractValue(metadata,'//datafield[@tag="490"]/subfield[@code="v"]')
73             )
74     |
75 );
76
77 my $bibs_sth = $dbh->prepare(
78     q|
79     SELECT biblionumber
80     FROM biblio_metadata
81     WHERE format='marcxml'
82         AND `schema`=?
83         AND (
84             ExtractValue(metadata,'//datafield[@tag="440"]/subfield[@code="a"]')
85                 OR ExtractValue(metadata,'//datafield[@tag="440"]/subfield[@code="v"]')
86                 OR ExtractValue(metadata,'//datafield[@tag="440"]/subfield[@code="n"]')
87                 OR ExtractValue(metadata,'//datafield[@tag="490"]/subfield[@code="a"]')
88                 OR ExtractValue(metadata,'//datafield[@tag="490"]/subfield[@code="v"]')
89             )
90     |
91 );
92
93 unless ( $commit ) {
94     print_usage();
95 }
96
97 print "Examining MARC records...\n";
98 $count_sth->execute( C4::Context->preference('marcflavour') );
99 my ( $num_records ) = $count_sth->fetchrow;
100
101 unless ( $commit ) {
102     if ( $num_records ) {
103         print "This action would change $num_records MARC records\n";
104     }
105     else {
106         print "There appears to be no series information to change\n";
107     }
108     print "Please run this again with the '-c' option to change the records\n";
109     exit 0;
110 }
111
112 print "Changing $num_records MARC records...\n";
113
114 #  MARC21 specific
115 my %fields = (
116     '440' => {
117         'a' => 'title',
118         'n' => 'number',
119         'p' => 'part',
120         'v' => 'volume',
121         'x' => 'issn',
122         '6' => 'link',
123         '8' => 'ln',
124         'w' => 'control',
125         '0' => 'auth',
126     },
127     '490' => {
128         'a' => 'title',
129         'v' => 'volume',
130         'x' => 'issn',
131         '6' => 'link',
132         '8' => 'ln',
133     },
134     );
135
136 $bibs_sth->execute( C4::Context->preference('marcflavour') );
137 while ( my ( $biblionumber ) = $bibs_sth->fetchrow ) {
138     my $framework = GetFrameworkCode( $biblionumber ) || '';
139     my ( @newfields );
140
141     # Get biblio marc
142     my $biblio = GetMarcBiblio({ biblionumber => $biblionumber });
143
144     foreach my $field ( $biblio->field( '440' ) ) {
145         my @newsubfields;
146         my @linksubfields;
147         my $has_links = '0';
148         foreach my $subfield ( sort keys %{ $fields{'440'} } ) {
149             my @values = $field->subfield( $subfield );
150
151             if ( $add_links && @values ) {
152                 if ( $subfield eq 'w' || $subfield eq '0' ) {
153                     $has_links = '1';
154                 }
155                 foreach my $v ( @values ) {
156                     push @linksubfields, ( $subfield, $v );
157                 }
158             }
159
160             if ( $subfield eq 'a' ) {
161                 my @numbers = $field->subfield( 'n' );
162                 my @parts = $field->subfield( 'p' );
163                 my $i = 0;
164                 while ( $i < @numbers || $i < @parts ) {
165                     my @strings = grep {$_} ( $values[$i], $numbers[$i], $parts[$i] );
166                     $values[$i] = join ' ', @strings;
167                     $i++;
168                 }
169             }
170
171             if ( $fields{'490'}{$subfield} ) {
172                 foreach my $v ( @values ) {
173                     push @newsubfields, ( $subfield, $v );
174                 }
175             }
176         }
177
178         if ( $has_links && @linksubfields ) {
179             my $link_field = MARC::Field->new(
180                 '830',
181                 $field->indicator(1), $field->indicator(2),
182                 @linksubfields
183                 );
184             push @newfields, $link_field;
185         }
186
187         if ( @newsubfields ) {
188             my $new_field = MARC::Field->new( '490', $has_links, '',
189                                               @newsubfields );
190             push @newfields, $new_field;
191         }
192
193         $biblio->delete_fields( $field );
194     }
195
196     foreach my $field ( $biblio->field( '490' ) ) {
197         my @newsubfields;
198         foreach my $subfield ( sort keys %{ $fields{'490'} } ) {
199             my @values = $field->subfield( $subfield );
200
201             if ( $fields{'440'}{$subfield} ) {
202                 foreach my $v ( @values ) {
203                     push @newsubfields, ( $subfield, $v );
204                 }
205             }
206         }
207
208         if ( @newsubfields ) {
209             my $new_field = MARC::Field->new( '440', '', '',
210                                               @newsubfields );
211             push @newfields, $new_field;
212         }
213
214         $biblio->delete_fields( $field );
215     }
216     $biblio->insert_fields_ordered( @newfields );
217
218     if ( $verbose ) {
219         print "Changing MARC for biblio number $biblionumber.\n";
220     }
221     else {
222         print ".";
223     }
224     ModBiblioMarc( $biblio, $biblionumber, $framework );
225 }
226 print "\n";
227
228 if ( $update_frameworks ) {
229     print "Updating Koha to MARC mappings for seriestitle and volume\n";
230
231     # set new mappings for koha fields
232     $dbh->do(
233 "UPDATE marc_subfield_structure SET kohafield='seriestitle'
234   WHERE tagfield='490' AND tagsubfield='a'"
235     );
236     $dbh->do(
237 "UPDATE marc_subfield_structure SET kohafield='volume'
238   WHERE tagfield='490' AND tagsubfield='v'"
239     );
240
241     # empty old koha fields
242     $dbh->do(
243 "UPDATE marc_subfield_structure SET kohafield=''
244   WHERE kohafield='seriestitle' AND tagfield='440' AND tagsubfield='a'"
245         );
246     $dbh->do(
247 "UPDATE marc_subfield_structure SET kohafield=''
248   WHERE kohafield='volume' AND tagfield='440' AND tagsubfield='v'"
249         );
250 }
251
252 sub print_usage {
253     print <<_USAGE_;
254 $0: switch MARC21 440 tag and 490 tag contents
255
256 Parameters:
257     -c            Commit the changes to the marc records.
258
259     -l            Add 830 tags with authority information from 440.  Otherwise
260                   this information will be ignored.
261
262     -f            Also update the Koha field to MARC framework mappings for the
263                   seriestitle and volume Koha fields.
264
265     -v            Show more information as the records are being changed.
266
267     --help or -h  show this message.
268
269 _USAGE_
270 }