430d89d6a7cb7195244774ddd2d6082b7c51fa7b
[koha.git] / misc / maintenance / sanitize_records.pl
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Copyright 2014 BibLibre
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 Modern::Perl;
21
22 use Koha::Script;
23 use C4::Charset;
24 use C4::Context;
25 use C4::Biblio;
26 use Koha::Biblios;
27 use Getopt::Long qw( GetOptions );
28 use Pod::Usage qw( pod2usage );
29
30 my ( $help, $verbose, $confirm, $biblionumbers, $reindex, $filename,
31     $auto_search, $fix_ampersand );
32 my $result = GetOptions(
33     'h|help'          => \$help,
34     'v|verbose'       => \$verbose,
35     'c|confirm'       => \$confirm,
36     'biblionumbers:s' => \$biblionumbers,
37     'reindex'         => \$reindex,
38     'f|filename:s'    => \$filename,
39     'auto-search'     => \$auto_search,
40     'fix-ampersand'   => \$fix_ampersand,
41 ) || pod2usage(1);
42
43 # This script only fix ampersand at the moment.
44 # It is enabled by default.
45 $fix_ampersand = 1;
46
47 if ($help) {
48     pod2usage(0);
49 }
50
51 unless ( $filename or $biblionumbers or $auto_search ) {
52     pod2usage(
53         -exitval => 1,
54         -message =>
55           qq{\n\tAt least one record number source should be provided.\n}
56     );
57 }
58
59 if (   $filename and $biblionumbers
60     or $filename and $auto_search
61     or $biblionumbers and $auto_search )
62 {
63     pod2usage(
64         -exitval => 1,
65         -message => qq{\n\tOnly one record number source should be provided.\n}
66     );
67 }
68
69 my @biblionumbers;
70
71 # We first detect if we have a file or biblos directly entered by command line
72 #or if we want to use findAmp() sub
73 if ($auto_search) {
74     @biblionumbers = biblios_to_sanitize();
75 }
76 elsif ($filename) {
77     if ( -e $filename ) {
78         open( my $fh, '<', $filename ) || die("Can't open $filename ($!)");
79         while (<$fh>) {
80             chomp;
81             my $line = $_;
82             push @biblionumbers, split( " |,", $line );
83         }
84         close $fh;
85     }
86     else {
87         pod2usage(
88             -exitval => 1,
89             -message =>
90 qq{\n\tThis filename does not exist. Please verify the path is correct.\n}
91         );
92     }
93 }
94 else {
95     @biblionumbers = split m|,|, $biblionumbers if $biblionumbers;
96 }
97
98 # We remove spaces
99 s/(^\s*|\s*$)//g for @biblionumbers;
100
101 # Remove empty lines
102 @biblionumbers = grep { !/^$/ } @biblionumbers;
103
104 say @biblionumbers . " records to process" if $verbose;
105
106 my @changes;
107 for my $biblionumber (@biblionumbers) {
108     print "processing record $biblionumber..." if $verbose;
109     unless ( $biblionumber =~ m|^\d+$| ) {
110         say " skipping. ERROR: Invalid biblionumber." if $verbose;
111         next;
112     }
113     my $biblio = Koha::Biblios->find($biblionumber);
114     unless ( $biblio ) {
115         say " skipping. ERROR: biblionumber not found." if $verbose;
116         next;
117     }
118     my $record = $biblio->metadata->record;
119     unless ($record) {
120         say " skipping. ERROR: Invalid record." if $verbose;
121         next;
122     }
123
124     my ( $cleaned_record, $has_been_modified ) =
125       C4::Charset::SanitizeRecord( $record, $biblionumber );
126     if ($has_been_modified) {
127         my $frameworkcode = C4::Biblio::GetFrameworkCode($record);
128
129         C4::Biblio::ModBiblio( $cleaned_record, $biblionumber, $frameworkcode )
130             if $confirm;
131         push @changes, $biblionumber;
132         say " Done!" if $verbose;
133     }
134     else {
135         say " Nothing to do." if $verbose;
136     }
137 }
138
139 if ($verbose) {
140     say "Total: "
141       . @changes
142       . " records "
143       . ( $confirm ? "cleaned!" : "to clean." );
144 }
145
146 if ( $reindex and $confirm and @changes ) {
147     say "Now, reindexing using -b -v" if $verbose;
148     my $kohapath = C4::Context->config('intranetdir');
149     my $cmd      = qq|
150         $kohapath/misc/migration_tools/rebuild_zebra.pl -b -v -where "biblionumber IN ( |
151       . join( ',', @changes ) . q| )"
152     |;
153     system($cmd);
154 }
155
156 sub biblios_to_sanitize {
157     my $dbh   = C4::Context->dbh;
158     my $query = q{
159         SELECT biblionumber
160         FROM biblio_metadata
161         WHERE format = 'marcxml'
162             AND `schema` = ?
163             AND metadata LIKE "%&amp;amp;%"
164         };
165     return @{ $dbh->selectcol_arrayref( $query, { Slice => {} }, C4::Context->preference('marcflavour') ) };
166 }
167
168 =head1 NAME
169
170 sanitize_records - This script sanitizes a record.
171
172 =head1 SYNOPSIS
173
174 sanitize_records.pl [-h|--help] [-v|--verbose] [-c|--confirm] [--biblionumbers=BIBLIONUMBER_LIST] [-f|--filename=FILENAME] [--auto-search] [--reindex] [--fix-ampersand]
175
176 You can either give some biblionumbers or a file with biblionumbers or ask for an auto-search.
177
178 =head1 OPTIONS
179
180 =over
181
182 =item B<-h|--help>
183
184 Print a brief help message
185
186 =item B<-v|--verbose>
187
188 Verbose mode.
189
190 =item B<-c|--confirm>
191
192 This flag must be provided in order for the script to actually
193 sanitize records. If it is not supplied, the script will
194 only report on the record list to process.
195
196 =item B<--biblionumbers=BIBLIONUMBER_LIST>
197
198 Give a biblionumber list using this parameter. They must be separated by
199 commas.
200
201 =item B<-f|--filename=FILENAME>
202
203 Give a biblionumber list using a filename. One biblionumber by line or separate them with a whitespace character.
204
205 =item B<--auto-search>
206
207 Automatically search records containing "&amp;" in biblio_metadata.metadata or in the specified fields.
208
209 =item B<--fix-ampersand>
210
211 Replace '&amp;' by '&' in the records.
212 Replace '&amp;amp;amp;etc.' with '&amp;' in the records.
213
214 =item B<--reindex>
215
216 Reindex the modified records.
217
218 =back
219
220 =head1 AUTHOR
221
222 Alex Arnaud <alex.arnaud@biblibre.com>
223 Christophe Croullebois <christophe.croullebois@biblibre.com>
224 Jonathan Druart <jonathan.druart@biblibre.com>
225
226 =head1 COPYRIGHT
227
228 Copyright 2014 BibLibre
229
230 =head1 LICENSE
231
232 This file is part of Koha.
233
234 # Koha is free software; you can redistribute it and/or modify it
235 # under the terms of the GNU General Public License as published by
236 # the Free Software Foundation; either version 3 of the License, or
237 # (at your option) any later version.
238 #
239 # Koha is distributed in the hope that it will be useful, but
240 # WITHOUT ANY WARRANTY; without even the implied warranty of
241 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
242 # GNU General Public License for more details.
243 #
244 # You should have received a copy of the GNU General Public License
245 # along with Koha; if not, see <http://www.gnu.org/licenses>.
246
247 =cut