(bug 1532) Reserves Updates Ported From Dev_Week
[koha.git] / misc / migration_tools / bulkauthimport.pl
1 #!/usr/bin/perl
2 # small script that import an iso2709 file into koha 2.0
3
4 use strict;
5 BEGIN {
6     # find Koha's Perl modules
7     # test carefully before changing this
8     use FindBin;
9     eval { require "$FindBin::Bin/kohalib.pl" };
10 }
11
12 # Koha modules used
13 use Unicode::Normalize;
14 use MARC::File::USMARC;
15 use MARC::File::XML;
16 use MARC::Record;
17 use MARC::Batch;
18 use C4::Context;
19 use C4::Charset;
20 use C4::AuthoritiesMarc;
21 use Time::HiRes qw(gettimeofday);
22 use Getopt::Long;
23 use IO::File;
24
25 my ( $input_marc_file, $number) = ('',0);
26 my ($version, $delete, $test_parameter,$char_encoding, $verbose, $format, $commit);
27 $| = 1;
28 GetOptions(
29     'file:s'    => \$input_marc_file,
30     'n:i' => \$number,
31     'h' => \$version,
32     'd' => \$delete,
33     't' => \$test_parameter,
34     'c:s' => \$char_encoding,
35     'v:s' => \$verbose,
36     'm:s' => \$format,
37     'commit:f' => \$commit,
38 );
39
40 if ($version || ($input_marc_file eq '')) {
41     print <<EOF
42 small script to import an iso2709 file into Koha.
43 parameters :
44 \th : this version/help screen
45 \tfile /path/to/file/to/dump : the file to dump
46 \tv : verbose mode. Valid modes are 1 and 2
47 \tn : the number of the record to import. If missing, the whole file is imported
48 \tt : test mode : parses the file, saying what it would do, but doing nothing.
49 \tc : the MARC flavour. At the moment, MARC21 and UNIMARC supported. MARC21 by default.
50 \td : delete EVERYTHING related to authorities in koha-DB before import
51 \tm : format, MARCXML or ISO2709
52 \tcommit : the number of records to wait before performing a 'commit' operation
53 IMPORTANT : don't use this script before you've entered and checked twice (or more) your MARC parameters tables.
54 If you fail the test, the import won't work correctly and you will get invalid datas.
55
56 SAMPLE : ./bulkmarcimport.pl -file /home/paul/koha.dev/local/npl -n 1
57 EOF
58 ;#'
59 die;
60 }
61
62 my $dbh = C4::Context->dbh;
63
64 if ($delete) {
65     print "deleting authorities\n";
66     $dbh->do("truncate auth_header");
67 }
68 if ($test_parameter) {
69     print "TESTING MODE ONLY\n    DOING NOTHING\n===============\n";
70 }
71
72 my $marcFlavour = C4::Context->preference('marcflavour') || 'MARC21';
73 $char_encoding = 'MARC21' unless ($char_encoding);
74 print "CHAR : $char_encoding\n" if $verbose;
75 my $starttime = gettimeofday;
76 my $fh = IO::File->new($input_marc_file); # don't let MARC::Batch open the file, as it applies the ':utf8' IO layer
77 my $batch;
78 if ($format =~ /XML/i) {
79     # ugly hack follows -- MARC::File::XML, when used by MARC::Batch,
80     # appears to try to convert incoming XML records from MARC-8
81     # to UTF-8.  Setting the BinaryEncoding key turns that off
82     # TODO: see what happens to ISO-8859-1 XML files.
83     # TODO: determine if MARC::Batch can be fixed to handle
84     #       XML records properly -- it probably should be
85     #       be using a proper push or pull XML parser to
86     #       extract the records, not using regexes to look
87     #       for <record>.*</record>.
88     $MARC::File::XML::_load_args{BinaryEncoding} = 'utf-8';
89     $batch = MARC::Batch->new( 'XML', $fh );
90 } else {
91     $batch = MARC::Batch->new( 'USMARC', $fh );
92 }
93 $batch->warnings_off();
94 $batch->strict_off();
95 my $i=0;
96
97 $dbh->{AutoCommit} = 0;
98 my $commitnum = 50;
99 if ($commit) {
100     $commitnum = $commit;
101 }
102
103 RECORD: while ( my $record = $batch->next() ) {
104     $i++;
105     print ".";
106     print "\r$i" unless $i % 100;
107
108     if ($record->encoding() eq 'MARC-8') {
109         my ($guessed_charset, $charset_errors);
110         ($record, $guessed_charset, $charset_errors) = MarcToUTF8Record($record, $marcFlavour);
111         if ($guessed_charset eq 'failed') {
112             warn "ERROR: failed to perform character conversion for record $i\n";
113             next RECORD;            
114         }
115     }
116
117     warn "$i ==>".$record->as_formatted() if $verbose eq 2;
118     my $authtypecode;
119     if (C4::Context->preference('marcflavour') eq 'MARC21') {
120         $authtypecode="PERSO_NAME" if ($record->field('100'));
121         $authtypecode="CORPO_NAME" if ($record->field('110'));
122         $authtypecode="MEETI_NAME" if ($record->field('111'));
123         $authtypecode="UNIF_TITLE" if ($record->field('130'));
124         $authtypecode="CHRON_TERM" if ($record->field('148') or $record->field('182'));
125         $authtypecode="TOPIC_TERM" if ($record->field('150') or $record->field('180'));
126         $authtypecode="GEOGR_NAME" if ($record->field('151') or $record->field('181'));
127         $authtypecode="GENRE/FORM" if ($record->field('155') or $record->field('185'));
128         next unless $authtypecode; # skip invalid records FIXME: far too simplistic
129     }
130     else {
131         $authtypecode=substr($record->leader(),9,1);
132         $authtypecode="NP" if ($authtypecode eq 'a'); # personnes
133         $authtypecode="CO" if ($authtypecode eq 'b'); # collectivit�
134         $authtypecode="NG" if ($authtypecode eq 'c'); # g�graphique
135         $authtypecode="NM" if ($authtypecode eq 'd'); # marque
136         $authtypecode="NF" if ($authtypecode eq 'e'); # famille
137         $authtypecode="TI" if ($authtypecode eq 'f'); # Titre uniforme
138         $authtypecode="TI" if ($authtypecode eq 'h'); # auteur/titre
139         $authtypecode="MM" if ($authtypecode eq 'j'); # mot mati�e
140     }
141
142     unless ($test_parameter) {
143         my ($authid) = AddAuthority($record,0,$authtypecode);
144         warn "ADDED authority NB $authid in DB\n" if $verbose;
145         $dbh->commit() if (0 == $i % $commitnum);
146     }
147
148     last if $i ==  $number;
149 }
150 $dbh->commit();
151
152 my $timeneeded = gettimeofday - $starttime;
153 print "\n$i MARC record done in $timeneeded seconds\n";