Bug 23846: Add a check to the data inconsistencies script
[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 qw( SanitizeRecord );
24 use C4::Context;
25 use DBI;
26 use C4::Biblio;
27 use Getopt::Long;
28 use Pod::Usage;
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 $record = C4::Biblio::GetMarcBiblio({ biblionumber => $biblionumber });
114     unless ($record) {
115         say " skipping. ERROR: Invalid record." if $verbose;
116         next;
117     }
118
119     my ( $cleaned_record, $has_been_modified ) =
120       C4::Charset::SanitizeRecord( $record, $biblionumber );
121     if ($has_been_modified) {
122         my $frameworkcode = C4::Biblio::GetFrameworkCode($record);
123
124         C4::Biblio::ModBiblio( $cleaned_record, $biblionumber, $frameworkcode )
125             if $confirm;
126         push @changes, $biblionumber;
127         say " Done!" if $verbose;
128     }
129     else {
130         say " Nothing to do." if $verbose;
131     }
132 }
133
134 if ($verbose) {
135     say "Total: "
136       . @changes
137       . " records "
138       . ( $confirm ? "cleaned!" : "to clean." );
139 }
140
141 if ( $reindex and $confirm and @changes ) {
142     say "Now, reindexing using -b -v" if $verbose;
143     my $kohapath = C4::Context->config('intranetdir');
144     my $cmd      = qq|
145         $kohapath/misc/migration_tools/rebuild_zebra.pl -b -v -where "biblionumber IN ( |
146       . join( ',', @changes ) . q| )"
147     |;
148     system($cmd);
149 }
150
151 sub biblios_to_sanitize {
152     my $dbh   = C4::Context->dbh;
153     my $query = q{
154         SELECT biblionumber
155         FROM biblio_metadata
156         WHERE format = 'marcxml'
157             AND `schema` = ?
158             AND metadata LIKE "%&amp;amp;%"
159         };
160     return @{ $dbh->selectcol_arrayref( $query, { Slice => {} }, C4::Context->preference('marcflavour') ) };
161 }
162
163 =head1 NAME
164
165 sanitize_records - This script sanitizes a record.
166
167 =head1 SYNOPSIS
168
169 sanitize_records.pl [-h|--help] [-v|--verbose] [-c|--confirm] [--biblionumbers=BIBLIONUMBER_LIST] [-f|--filename=FILENAME] [--auto-search] [--reindex] [--fix-ampersand]
170
171 You can either give some biblionumbers or a file with biblionumbers or ask for an auto-search.
172
173 =head1 OPTIONS
174
175 =over
176
177 =item B<-h|--help>
178
179 Print a brief help message
180
181 =item B<-v|--verbose>
182
183 Verbose mode.
184
185 =item B<-c|--confirm>
186
187 This flag must be provided in order for the script to actually
188 sanitize records. If it is not supplied, the script will
189 only report on the record list to process.
190
191 =item B<--biblionumbers=BIBLIONUMBER_LIST>
192
193 Give a biblionumber list using this parameter. They must be separated by
194 commas.
195
196 =item B<-f|--filename=FILENAME>
197
198 Give a biblionumber list using a filename. One biblionumber by line or separate them with a whitespace character.
199
200 =item B<--auto-search>
201
202 Automatically search records containing "&amp;" in biblio_metadata.metadata or in the specified fields.
203
204 =item B<--fix-ampersand>
205
206 Replace '&amp;' by '&' in the records.
207 Replace '&amp;amp;amp;etc.' with '&amp;' in the records.
208
209 =item B<--reindex>
210
211 Reindex the modified records.
212
213 =back
214
215 =head1 AUTHOR
216
217 Alex Arnaud <alex.arnaud@biblibre.com>
218 Christophe Croullebois <christophe.croullebois@biblibre.com>
219 Jonathan Druart <jonathan.druart@biblibre.com>
220
221 =head1 COPYRIGHT
222
223 Copyright 2014 BibLibre
224
225 =head1 LICENSE
226
227 This file is part of Koha.
228
229 Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
230 Foundation; either version 3 of the License, or (at your option) any later version.
231
232 You should have received a copy of the GNU General Public License along
233 with Koha; if not, write to the Free Software Foundation, Inc.,
234 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
235
236 =cut