fix malformed call of XSLTParse4Display
[koha.git] / misc / migration_tools / rebuild_zebra.pl
1 #!/usr/bin/perl
2
3 use strict;
4 #use warnings; FIXME - Bug 2505
5
6 use C4::Context;
7 use Getopt::Long;
8 use File::Temp qw/ tempdir /;
9 use File::Path;
10 use C4::Biblio;
11 use C4::AuthoritiesMarc;
12
13
14 # script that checks zebradir structure & create directories & mandatory files if needed
15 #
16 #
17
18 $|=1; # flushes output
19
20 my $directory;
21 my $nosanitize;
22 my $skip_export;
23 my $keep_export;
24 my $reset;
25 my $biblios;
26 my $authorities;
27 my $noxml;
28 my $noshadow;
29 my $do_munge;
30 my $want_help;
31 my $as_xml;
32 my $process_zebraqueue;
33 my $do_not_clear_zebraqueue;
34 my $verbose_logging;
35 my $zebraidx_log_opt = " -v none,fatal,warn ";
36 my $result = GetOptions(
37     'd:s'           => \$directory,
38     'reset'         => \$reset,
39     's'             => \$skip_export,
40     'k'             => \$keep_export,
41     'nosanitize'    => \$nosanitize,
42     'b'             => \$biblios,
43     'noxml'         => \$noxml,
44     'w'             => \$noshadow,
45     'munge-config'  => \$do_munge,
46     'a'             => \$authorities,
47     'h|help'        => \$want_help,
48         'x'                             => \$as_xml,
49     'y'             => \$do_not_clear_zebraqueue,
50     'z'             => \$process_zebraqueue,
51     'v'             => \$verbose_logging,
52 );
53
54
55 if (not $result or $want_help) {
56     print_usage();
57     exit 0;
58 }
59
60 if (not $biblios and not $authorities) {
61     my $msg = "Must specify -b or -a to reindex bibs or authorities\n";
62     $msg   .= "Please do '$0 --help' to see usage.\n";
63     die $msg;
64 }
65
66 if ($authorities and $as_xml) {
67     my $msg = "Cannot specify both -a and -x\n";
68     $msg   .= "Please do '$0 --help' to see usage.\n";
69     die $msg;
70 }
71
72 if ( !$as_xml and $nosanitize ) {
73     my $msg = "Cannot specify both -no_xml and -nosanitize\n";
74     $msg   .= "Please do '$0 --help' to see usage.\n";
75     die $msg;
76 }
77
78 if ($process_zebraqueue and ($skip_export or $reset)) {
79     my $msg = "Cannot specify -r or -s if -z is specified\n";
80     $msg   .= "Please do '$0 --help' to see usage.\n";
81     die $msg;
82 }
83
84 if ($process_zebraqueue and $do_not_clear_zebraqueue) {
85     my $msg = "Cannot specify both -y and -z\n";
86     $msg   .= "Please do '$0 --help' to see usage.\n";
87     die $msg;
88 }
89
90 if ($noshadow) {
91     $noshadow = ' -n ';
92 }
93
94 #  -v is for verbose, which seems backwards here because of how logging is set
95 #    on the CLI of zebraidx.  It works this way.  The default is to not log much
96 if ($verbose_logging) {
97     $zebraidx_log_opt = '';
98 }
99
100 my $use_tempdir = 0;
101 unless ($directory) {
102     $use_tempdir = 1;
103     $directory = tempdir(CLEANUP => ($keep_export ? 0 : 1));
104
105
106
107 my $biblioserverdir = C4::Context->zebraconfig('biblioserver')->{directory};
108 my $authorityserverdir = C4::Context->zebraconfig('authorityserver')->{directory};
109
110 my $kohadir = C4::Context->config('intranetdir');
111 my $dbh = C4::Context->dbh;
112 my ($biblionumbertagfield,$biblionumbertagsubfield) = &GetMarcFromKohaField("biblio.biblionumber","");
113 my ($biblioitemnumbertagfield,$biblioitemnumbertagsubfield) = &GetMarcFromKohaField("biblioitems.biblioitemnumber","");
114
115 if ( $verbose_logging ) {
116     print "Zebra configuration information\n";
117     print "================================\n";
118     print "Zebra biblio directory      = $biblioserverdir\n";
119     print "Zebra authorities directory = $authorityserverdir\n";
120     print "Koha directory              = $kohadir\n";
121     print "BIBLIONUMBER in :     $biblionumbertagfield\$$biblionumbertagsubfield\n";
122     print "BIBLIOITEMNUMBER in : $biblioitemnumbertagfield\$$biblioitemnumbertagsubfield\n";
123     print "================================\n";
124 }
125
126 if ($do_munge) {
127     munge_config();
128 }
129
130 if ($authorities) {
131     index_records('authority', $directory, $skip_export, $process_zebraqueue, $as_xml, $noxml, $nosanitize, $do_not_clear_zebraqueue, $verbose_logging, $zebraidx_log_opt);
132 } else {
133     print "skipping authorities\n" if ( $verbose_logging );
134 }
135
136 if ($biblios) {
137     index_records('biblio', $directory, $skip_export, $process_zebraqueue, $as_xml, $noxml, $nosanitize, $do_not_clear_zebraqueue, $verbose_logging, $zebraidx_log_opt);
138 } else {
139     print "skipping biblios\n" if ( $verbose_logging );
140 }
141
142
143 if ( $verbose_logging ) {
144     print "====================\n";
145     print "CLEANING\n";
146     print "====================\n";
147 }
148 if ($keep_export) {
149     print "NOTHING cleaned : the export $directory has been kept.\n";
150     print "You can re-run this script with the -s ";
151     if ($use_tempdir) {
152         print " and -d $directory parameters";
153     } else {
154         print "parameter";
155     }
156     print "\n";
157     print "if you just want to rebuild zebra after changing the record.abs\n";
158     print "or another zebra config file\n";
159 } else {
160     unless ($use_tempdir) {
161         # if we're using a temporary directory
162         # created by File::Temp, it will be removed
163         # automatically.
164         rmtree($directory, 0, 1);
165         print "directory $directory deleted\n";
166     }
167 }
168
169 sub index_records {
170     my ($record_type, $directory, $skip_export, $process_zebraqueue, $as_xml, $noxml, $nosanitize, $do_not_clear_zebraqueue, $verbose_logging, $zebraidx_log_opt) = @_;
171
172     my $num_records_exported = 0;
173     my $num_records_deleted = 0;
174     if ($skip_export && $verbose_logging) {
175         print "====================\n";
176         print "SKIPPING $record_type export\n";
177         print "====================\n";
178     } else {
179         if ( $verbose_logging ) {
180             print "====================\n";
181             print "exporting $record_type\n";
182             print "====================\n";
183         }
184         mkdir "$directory" unless (-d $directory);
185         mkdir "$directory/$record_type" unless (-d "$directory/$record_type");
186         if ($process_zebraqueue) {
187             my $entries = select_zebraqueue_records($record_type, 'deleted');
188             mkdir "$directory/del_$record_type" unless (-d "$directory/del_$record_type");
189             $num_records_deleted = generate_deleted_marc_records($record_type, $entries, "$directory/del_$record_type", $as_xml);
190             mark_zebraqueue_batch_done($entries);
191             $entries = select_zebraqueue_records($record_type, 'updated');
192             mkdir "$directory/upd_$record_type" unless (-d "$directory/upd_$record_type");
193             $num_records_exported = export_marc_records_from_list($record_type, 
194                                                                   $entries, "$directory/upd_$record_type", $as_xml, $noxml);
195             mark_zebraqueue_batch_done($entries);
196         } else {
197             my $sth = select_all_records($record_type);
198             $num_records_exported = export_marc_records_from_sth($record_type, $sth, "$directory/$record_type", $as_xml, $noxml, $nosanitize);
199             unless ($do_not_clear_zebraqueue) {
200                 mark_all_zebraqueue_done($record_type);
201             }
202         }
203     }
204     
205     #
206     # and reindexing everything
207     #
208     if ( $verbose_logging ) {
209         print "====================\n";
210         print "REINDEXING zebra\n";
211         print "====================\n";
212     }
213         my $record_fmt = ($as_xml) ? 'marcxml' : 'iso2709' ;
214     if ($process_zebraqueue) {
215         do_indexing($record_type, 'delete', "$directory/del_$record_type", $reset, $noshadow, $record_fmt, $zebraidx_log_opt) 
216             if $num_records_deleted;
217         do_indexing($record_type, 'update', "$directory/upd_$record_type", $reset, $noshadow, $record_fmt, $zebraidx_log_opt)
218             if $num_records_exported;
219     } else {
220         do_indexing($record_type, 'update', "$directory/$record_type", $reset, $noshadow, $record_fmt, $zebraidx_log_opt)
221             if ($num_records_exported or $skip_export);
222     }
223 }
224
225 sub select_zebraqueue_records {
226     my ($record_type, $update_type) = @_;
227
228     my $server = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
229     my $op = ($update_type eq 'deleted') ? 'recordDelete' : 'specialUpdate';
230
231     my $sth = $dbh->prepare("SELECT id, biblio_auth_number 
232                              FROM zebraqueue
233                              WHERE server = ?
234                              AND   operation = ?
235                              AND   done = 0
236                              ORDER BY id DESC");
237     $sth->execute($server, $op);
238     my $entries = $sth->fetchall_arrayref({});
239 }
240
241 sub mark_all_zebraqueue_done {
242     my ($record_type) = @_;
243
244     my $server = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
245
246     my $sth = $dbh->prepare("UPDATE zebraqueue SET done = 1
247                              WHERE server = ?
248                              AND done = 0");
249     $sth->execute($server);
250 }
251
252 sub mark_zebraqueue_batch_done {
253     my ($entries) = @_;
254
255     $dbh->{AutoCommit} = 0;
256     my $sth = $dbh->prepare("UPDATE zebraqueue SET done = 1 WHERE id = ?");
257     $dbh->commit();
258     foreach my $id (map { $_->{id} } @$entries) {
259         $sth->execute($id);
260     }
261     $dbh->{AutoCommit} = 1;
262 }
263
264 sub select_all_records {
265     my $record_type = shift;
266     return ($record_type eq 'biblio') ? select_all_biblios() : select_all_authorities();
267 }
268
269 sub select_all_authorities {
270     my $sth = $dbh->prepare("SELECT authid FROM auth_header");
271     $sth->execute();
272     return $sth;
273 }
274
275 sub select_all_biblios {
276     my $sth = $dbh->prepare("SELECT biblionumber FROM biblioitems ORDER BY biblionumber");
277     $sth->execute();
278     return $sth;
279 }
280
281 sub export_marc_records_from_sth {
282     my ($record_type, $sth, $directory, $as_xml, $noxml, $nosanitize) = @_;
283
284     my $num_exported = 0;
285     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
286     my $i = 0;
287     while (my ($record_number) = $sth->fetchrow_array) {
288         print "." if ( $verbose_logging );
289         print "\r$i" unless ($i++ %100 or !$verbose_logging);
290         if ( $nosanitize ) {
291             my $marcxml = $record_type eq 'biblio'
292                           ? GetXmlBiblio( $record_number )
293                           : GetAuthorityXML( $record_number );
294             if ( $marcxml ) {
295                 print OUT $marcxml if $marcxml;
296                 $num_exported++;
297             }
298             next;
299         }
300         my ($marc) = get_corrected_marc_record($record_type, $record_number, $noxml);
301         if (defined $marc) {
302             # FIXME - when more than one record is exported and $as_xml is true,
303             # the output file is not valid XML - it's just multiple <record> elements
304             # strung together with no single root element.  zebraidx doesn't seem
305             # to care, though, at least if you're using the GRS-1 filter.  It does
306             # care if you're using the DOM filter, which requires valid XML file(s).
307             print OUT ($as_xml) ? $marc->as_xml_record() : $marc->as_usmarc();
308             $num_exported++;
309         }
310     }
311     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
312     close OUT;
313     return $num_exported;
314 }
315
316 sub export_marc_records_from_list {
317     my ($record_type, $entries, $directory, $as_xml, $noxml) = @_;
318
319     my $num_exported = 0;
320     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
321     my $i = 0;
322     my %found = ();
323     foreach my $record_number ( map { $_->{biblio_auth_number} }
324                                 grep { !$found{ $_->{biblio_auth_number} }++ }
325                                 @$entries ) {
326         print "." if ( $verbose_logging );
327         print "\r$i" unless ($i++ %100 or !$verbose_logging);
328         my ($marc) = get_corrected_marc_record($record_type, $record_number, $noxml);
329         if (defined $marc) {
330             # FIXME - when more than one record is exported and $as_xml is true,
331             # the output file is not valid XML - it's just multiple <record> elements
332             # strung together with no single root element.  zebraidx doesn't seem
333             # to care, though, at least if you're using the GRS-1 filter.  It does
334             # care if you're using the DOM filter, which requires valid XML file(s).
335             print OUT ($as_xml) ? $marc->as_xml_record() : $marc->as_usmarc();
336             $num_exported++;
337         }
338     }
339     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
340     close OUT;
341     return $num_exported;
342 }
343
344 sub generate_deleted_marc_records {
345     my ($record_type, $entries, $directory, $as_xml) = @_;
346
347     my $num_exported = 0;
348     open (OUT, ">:utf8 ", "$directory/exported_records") or die $!;
349     my $i = 0;
350     foreach my $record_number (map { $_->{biblio_auth_number} } @$entries ) {
351         print "\r$i" unless ($i++ %100 or !$verbose_logging);
352         print "." if ( $verbose_logging );
353
354         my $marc = MARC::Record->new();
355         if ($record_type eq 'biblio') {
356             fix_biblio_ids($marc, $record_number, $record_number);
357         } else {
358             fix_authority_id($marc, $record_number);
359         }
360         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
361             fix_unimarc_100($marc);
362         }
363
364         print OUT ($as_xml) ? $marc->as_xml_record() : $marc->as_usmarc();
365         $num_exported++;
366     }
367     print "\nRecords exported: $num_exported\n" if ( $verbose_logging );
368     close OUT;
369     return $num_exported;
370     
371
372 }
373
374 sub get_corrected_marc_record {
375     my ($record_type, $record_number, $noxml) = @_;
376
377     my $marc = get_raw_marc_record($record_type, $record_number, $noxml); 
378
379     if (defined $marc) {
380         fix_leader($marc);
381         if ($record_type eq 'biblio') {
382             my $succeeded = fix_biblio_ids($marc, $record_number);
383             return unless $succeeded;
384         } else {
385             fix_authority_id($marc, $record_number);
386         }
387         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
388             fix_unimarc_100($marc);
389         }
390     }
391
392     return $marc;
393 }
394
395 sub get_raw_marc_record {
396     my ($record_type, $record_number, $noxml) = @_;
397   
398     my $marc; 
399     if ($record_type eq 'biblio') {
400         if ($noxml) {
401             my $fetch_sth = $dbh->prepare_cached("SELECT marc FROM biblioitems WHERE biblionumber = ?");
402             $fetch_sth->execute($record_number);
403             if (my ($blob) = $fetch_sth->fetchrow_array) {
404                 $marc = MARC::Record->new_from_usmarc($blob);
405                 $fetch_sth->finish();
406             } else {
407                 return; # failure to find a bib is not a problem -
408                         # a delete could have been done before
409                         # trying to process a record update
410             }
411         } else {
412             eval { $marc = GetMarcBiblio($record_number); };
413             if ($@) {
414                 # here we do warn since catching an exception
415                 # means that the bib was found but failed
416                 # to be parsed
417                 warn "error retrieving biblio $record_number";
418                 return;
419             }
420         }
421     } else {
422         eval { $marc = GetAuthority($record_number); };
423         if ($@) {
424             warn "error retrieving authority $record_number";
425             return;
426         }
427     }
428     return $marc;
429 }
430
431 sub fix_leader {
432     # FIXME - this routine is suspect
433     # It blanks the Leader/00-05 and Leader/12-16 to
434     # force them to be recalculated correct when
435     # the $marc->as_usmarc() or $marc->as_xml() is called.
436     # But why is this necessary?  It would be a serious bug
437     # in MARC::Record (definitely) and MARC::File::XML (arguably) 
438     # if they are emitting incorrect leader values.
439     my $marc = shift;
440
441     my $leader = $marc->leader;
442     substr($leader,  0, 5) = '     ';
443     substr($leader, 10, 7) = '22     ';
444     $marc->leader(substr($leader, 0, 24));
445 }
446
447 sub fix_biblio_ids {
448     # FIXME - it is essential to ensure that the biblionumber is present,
449     #         otherwise, Zebra will choke on the record.  However, this
450     #         logic belongs in the relevant C4::Biblio APIs.
451     my $marc = shift;
452     my $biblionumber = shift;
453     my $biblioitemnumber;
454     if (@_) {
455         $biblioitemnumber = shift;
456     } else {    
457         my $sth = $dbh->prepare(
458             "SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=?");
459         $sth->execute($biblionumber);
460         ($biblioitemnumber) = $sth->fetchrow_array;
461         $sth->finish;
462         unless ($biblioitemnumber) {
463             warn "failed to get biblioitemnumber for biblio $biblionumber";
464             return 0;
465         }
466     }
467
468     # FIXME - this is cheating on two levels
469     # 1. C4::Biblio::_koha_marc_update_bib_ids is meant to be an internal function
470     # 2. Making sure that the biblionumber and biblioitemnumber are correct and
471     #    present in the MARC::Record object ought to be part of GetMarcBiblio.
472     #
473     # On the other hand, this better for now than what rebuild_zebra.pl used to
474     # do, which was duplicate the code for inserting the biblionumber 
475     # and biblioitemnumber
476     C4::Biblio::_koha_marc_update_bib_ids($marc, '', $biblionumber, $biblioitemnumber);
477
478     return 1;
479 }
480
481 sub fix_authority_id {
482     # FIXME - as with fix_biblio_ids, the authid must be present
483     #         for Zebra's sake.  However, this really belongs
484     #         in C4::AuthoritiesMarc.
485     my ($marc, $authid) = @_;
486     unless ($marc->field('001') and $marc->field('001')->data() eq $authid){
487         $marc->delete_field($marc->field('001'));
488         $marc->insert_fields_ordered(MARC::Field->new('001',$authid));
489     }
490 }
491
492 sub fix_unimarc_100 {
493     # FIXME - again, if this is necessary, it belongs in C4::AuthoritiesMarc.
494     my $marc = shift;
495
496     my $string;
497     if ( length($marc->subfield( 100, "a" )) == 35 ) {
498         $string = $marc->subfield( 100, "a" );
499         my $f100 = $marc->field(100);
500         $marc->delete_field($f100);
501     }
502     else {
503         $string = POSIX::strftime( "%Y%m%d", localtime );
504         $string =~ s/\-//g;
505         $string = sprintf( "%-*s", 35, $string );
506     }
507     substr( $string, 22, 6, "frey50" );
508     unless ( length($marc->subfield( 100, "a" )) == 35 ) {
509         $marc->delete_field($marc->field(100));
510         $marc->insert_grouped_field(MARC::Field->new( 100, "", "", "a" => $string ));
511     }
512 }
513
514 sub do_indexing {
515     my ($record_type, $op, $record_dir, $reset_index, $noshadow, $record_format, $zebraidx_log_opt) = @_;
516
517     my $zebra_server  = ($record_type eq 'biblio') ? 'biblioserver' : 'authorityserver';
518     my $zebra_db_name = ($record_type eq 'biblio') ? 'biblios' : 'authorities';
519     my $zebra_config  = C4::Context->zebraconfig($zebra_server)->{'config'};
520     my $zebra_db_dir  = C4::Context->zebraconfig($zebra_server)->{'directory'};
521
522     system("zebraidx -c $zebra_config $zebraidx_log_opt -g $record_format -d $zebra_db_name init") if $reset_index;
523     system("zebraidx -c $zebra_config $zebraidx_log_opt $noshadow -g $record_format -d $zebra_db_name $op $record_dir");
524     system("zebraidx -c $zebra_config $zebraidx_log_opt -g $record_format -d $zebra_db_name commit") unless $noshadow;
525
526 }
527
528 sub print_usage {
529     print <<_USAGE_;
530 $0: reindex MARC bibs and/or authorities in Zebra.
531
532 Use this batch job to reindex all biblio or authority
533 records in your Koha database.  This job is useful
534 only if you are using Zebra; if you are using the 'NoZebra'
535 mode, this job should not be used.
536
537 Parameters:
538     -b                      index bibliographic records
539
540     -a                      index authority records
541
542     -z                      select only updated and deleted
543                             records marked in the zebraqueue
544                             table.  Cannot be used with -r
545                             or -s.
546
547     -r                      clear Zebra index before
548                             adding records to index
549
550     -d                      Temporary directory for indexing.
551                             If not specified, one is automatically
552                             created.  The export directory
553                             is automatically deleted unless
554                             you supply the -k switch.
555
556     -k                      Do not delete export directory.
557
558     -s                      Skip export.  Used if you have
559                             already exported the records 
560                             in a previous run.
561
562     -noxml                  index from ISO MARC blob
563                             instead of MARC XML.  This
564                             option is recommended only
565                             for advanced user.
566
567     -x                      export and index as xml instead of is02709 (biblios only).
568                             use this if you might have records > 99,999 chars,
569                                                         
570     -nosanitize             export biblio/authority records directly from DB marcxml
571                             field without sanitizing records. It speed up
572                             dump process but could fail if DB contains badly
573                             encoded records. Works only with -x,
574
575     -w                      skip shadow indexing for this batch
576
577     -y                      do NOT clear zebraqueue after indexing; normally,
578                             after doing batch indexing, zebraqueue should be
579                             marked done for the affected record type(s) so that
580                             a running zebraqueue_daemon doesn't try to reindex
581                             the same records - specify -y to override this.  
582                             Cannot be used with -z.
583
584     -v                      increase the amount of logging.  Normally only 
585                             warnings and errors from the indexing are shown.
586
587     -munge-config           Deprecated option to try
588                             to fix Zebra config files.
589     --help or -h            show this message.
590 _USAGE_
591 }
592
593 # FIXME: the following routines are deprecated and 
594 # will be removed once it is determined whether
595 # a script to fix Zebra configuration files is 
596 # actually needed.
597 sub munge_config {
598 #
599 # creating zebra-biblios.cfg depending on system
600 #
601
602 # getting zebraidx directory
603 my $zebraidxdir;
604 foreach (qw(/usr/local/bin/zebraidx
605         /opt/bin/zebraidx
606         /usr/bin/zebraidx
607         )) {
608     if ( -f $_ ) {
609         $zebraidxdir=$_;
610     }
611 }
612
613 unless ($zebraidxdir) {
614     print qq|
615     ERROR: could not find zebraidx directory
616     ERROR: Either zebra is not installed,
617     ERROR: or it's in a directory I don't checked.
618     ERROR: do a which zebraidx and edit this file to add the result you get
619 |;
620     exit;
621 }
622 $zebraidxdir =~ s/\/bin\/.*//;
623 print "Info : zebra is in $zebraidxdir \n";
624
625 # getting modules directory
626 my $modulesdir;
627 foreach (qw(/usr/local/lib/idzebra-2.0/modules/mod-grs-xml.so
628             /usr/local/lib/idzebra/modules/mod-grs-xml.so
629             /usr/lib/idzebra/modules/mod-grs-xml.so
630             /usr/lib/idzebra-2.0/modules/mod-grs-xml.so
631         )) {
632     if ( -f $_ ) {
633         $modulesdir=$_;
634     }
635 }
636
637 unless ($modulesdir) {
638     print qq|
639     ERROR: could not find mod-grs-xml.so directory
640     ERROR: Either zebra is not properly compiled (libxml2 is not setup and you don t have mod-grs-xml.so,
641     ERROR: or it's in a directory I don't checked.
642     ERROR: find where mod-grs-xml.so is and edit this file to add the result you get
643 |;
644     exit;
645 }
646 $modulesdir =~ s/\/modules\/.*//;
647 print "Info: zebra modules dir : $modulesdir\n";
648
649 # getting tab directory
650 my $tabdir;
651 foreach (qw(/usr/local/share/idzebra/tab/explain.att
652             /usr/local/share/idzebra-2.0/tab/explain.att
653             /usr/share/idzebra/tab/explain.att
654             /usr/share/idzebra-2.0/tab/explain.att
655         )) {
656     if ( -f $_ ) {
657         $tabdir=$_;
658     }
659 }
660
661 unless ($tabdir) {
662     print qq|
663     ERROR: could not find explain.att directory
664     ERROR: Either zebra is not properly compiled,
665     ERROR: or it's in a directory I don't checked.
666     ERROR: find where explain.att is and edit this file to add the result you get
667 |;
668     exit;
669 }
670 $tabdir =~ s/\/tab\/.*//;
671 print "Info: tab dir : $tabdir\n";
672
673 #
674 # AUTHORITIES creating directory structure
675 #
676 my $created_dir_or_file = 0;
677 if ($authorities) {
678     if ( $verbose_logging ) {
679         print "====================\n";
680         print "checking directories & files for authorities\n";
681         print "====================\n";
682     }
683     unless (-d "$authorityserverdir") {
684         system("mkdir -p $authorityserverdir");
685         print "Info: created $authorityserverdir\n";
686         $created_dir_or_file++;
687     }
688     unless (-d "$authorityserverdir/lock") {
689         mkdir "$authorityserverdir/lock";
690         print "Info: created $authorityserverdir/lock\n";
691         $created_dir_or_file++;
692     }
693     unless (-d "$authorityserverdir/register") {
694         mkdir "$authorityserverdir/register";
695         print "Info: created $authorityserverdir/register\n";
696         $created_dir_or_file++;
697     }
698     unless (-d "$authorityserverdir/shadow") {
699         mkdir "$authorityserverdir/shadow";
700         print "Info: created $authorityserverdir/shadow\n";
701         $created_dir_or_file++;
702     }
703     unless (-d "$authorityserverdir/tab") {
704         mkdir "$authorityserverdir/tab";
705         print "Info: created $authorityserverdir/tab\n";
706         $created_dir_or_file++;
707     }
708     unless (-d "$authorityserverdir/key") {
709         mkdir "$authorityserverdir/key";
710         print "Info: created $authorityserverdir/key\n";
711         $created_dir_or_file++;
712     }
713     
714     unless (-d "$authorityserverdir/etc") {
715         mkdir "$authorityserverdir/etc";
716         print "Info: created $authorityserverdir/etc\n";
717         $created_dir_or_file++;
718     }
719     
720     #
721     # AUTHORITIES : copying mandatory files
722     #
723     # the record model, depending on marc flavour
724     unless (-f "$authorityserverdir/tab/record.abs") {
725         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
726             system("cp -f $kohadir/etc/zebradb/marc_defs/unimarc/authorities/record.abs $authorityserverdir/tab/record.abs");
727             print "Info: copied record.abs for UNIMARC\n";
728         } else {
729             system("cp -f $kohadir/etc/zebradb/marc_defs/marc21/authorities/record.abs $authorityserverdir/tab/record.abs");
730             print "Info: copied record.abs for USMARC\n";
731         }
732         $created_dir_or_file++;
733     }
734     unless (-f "$authorityserverdir/tab/sort-string-utf.chr") {
735         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $authorityserverdir/tab/sort-string-utf.chr");
736         print "Info: copied sort-string-utf.chr\n";
737         $created_dir_or_file++;
738     }
739     unless (-f "$authorityserverdir/tab/word-phrase-utf.chr") {
740         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $authorityserverdir/tab/word-phrase-utf.chr");
741         print "Info: copied word-phase-utf.chr\n";
742         $created_dir_or_file++;
743     }
744     unless (-f "$authorityserverdir/tab/auth1.att") {
745         system("cp -f $kohadir/etc/zebradb/authorities/etc/bib1.att $authorityserverdir/tab/auth1.att");
746         print "Info: copied auth1.att\n";
747         $created_dir_or_file++;
748     }
749     unless (-f "$authorityserverdir/tab/default.idx") {
750         system("cp -f $kohadir/etc/zebradb/etc/default.idx $authorityserverdir/tab/default.idx");
751         print "Info: copied default.idx\n";
752         $created_dir_or_file++;
753     }
754     
755     unless (-f "$authorityserverdir/etc/ccl.properties") {
756 #         system("cp -f $kohadir/etc/zebradb/ccl.properties ".C4::Context->zebraconfig('authorityserver')->{ccl2rpn});
757         system("cp -f $kohadir/etc/zebradb/ccl.properties $authorityserverdir/etc/ccl.properties");
758         print "Info: copied ccl.properties\n";
759         $created_dir_or_file++;
760     }
761     unless (-f "$authorityserverdir/etc/pqf.properties") {
762 #         system("cp -f $kohadir/etc/zebradb/pqf.properties ".C4::Context->zebraconfig('authorityserver')->{ccl2rpn});
763         system("cp -f $kohadir/etc/zebradb/pqf.properties $authorityserverdir/etc/pqf.properties");
764         print "Info: copied pqf.properties\n";
765         $created_dir_or_file++;
766     }
767     
768     #
769     # AUTHORITIES : copying mandatory files
770     #
771     unless (-f C4::Context->zebraconfig('authorityserver')->{config}) {
772     open ZD,">:utf8 ",C4::Context->zebraconfig('authorityserver')->{config};
773     print ZD "
774 # generated by KOHA/misc/migration_tools/rebuild_zebra.pl 
775 profilePath:\${srcdir:-.}:$authorityserverdir/tab/:$tabdir/tab/:\${srcdir:-.}/tab/
776
777 encoding: UTF-8
778 # Files that describe the attribute sets supported.
779 attset: auth1.att
780 attset: explain.att
781 attset: gils.att
782
783 modulePath:$modulesdir/modules/
784 # Specify record type
785 iso2709.recordType:grs.marcxml.record
786 recordType:grs.xml
787 recordId: (auth1,Local-Number)
788 storeKeys:1
789 storeData:1
790
791
792 # Lock File Area
793 lockDir: $authorityserverdir/lock
794 perm.anonymous:r
795 perm.kohaadmin:rw
796 register: $authorityserverdir/register:4G
797 shadow: $authorityserverdir/shadow:4G
798
799 # Temp File area for result sets
800 setTmpDir: $authorityserverdir/tmp
801
802 # Temp File area for index program
803 keyTmpDir: $authorityserverdir/key
804
805 # Approx. Memory usage during indexing
806 memMax: 40M
807 rank:rank-1
808     ";
809         print "Info: creating zebra-authorities.cfg\n";
810         $created_dir_or_file++;
811     }
812     
813     if ($created_dir_or_file) {
814         print "Info: created : $created_dir_or_file directories & files\n";
815     } else {
816         print "Info: file & directories OK\n";
817     }
818     
819 }
820 if ($biblios) {
821     if ( $verbose_logging ) {
822         print "====================\n";
823         print "checking directories & files for biblios\n";
824         print "====================\n";
825     }
826
827     #
828     # BIBLIOS : creating directory structure
829     #
830     unless (-d "$biblioserverdir") {
831         system("mkdir -p $biblioserverdir");
832         print "Info: created $biblioserverdir\n";
833         $created_dir_or_file++;
834     }
835     unless (-d "$biblioserverdir/lock") {
836         mkdir "$biblioserverdir/lock";
837         print "Info: created $biblioserverdir/lock\n";
838         $created_dir_or_file++;
839     }
840     unless (-d "$biblioserverdir/register") {
841         mkdir "$biblioserverdir/register";
842         print "Info: created $biblioserverdir/register\n";
843         $created_dir_or_file++;
844     }
845     unless (-d "$biblioserverdir/shadow") {
846         mkdir "$biblioserverdir/shadow";
847         print "Info: created $biblioserverdir/shadow\n";
848         $created_dir_or_file++;
849     }
850     unless (-d "$biblioserverdir/tab") {
851         mkdir "$biblioserverdir/tab";
852         print "Info: created $biblioserverdir/tab\n";
853         $created_dir_or_file++;
854     }
855     unless (-d "$biblioserverdir/key") {
856         mkdir "$biblioserverdir/key";
857         print "Info: created $biblioserverdir/key\n";
858         $created_dir_or_file++;
859     }
860     unless (-d "$biblioserverdir/etc") {
861         mkdir "$biblioserverdir/etc";
862         print "Info: created $biblioserverdir/etc\n";
863         $created_dir_or_file++;
864     }
865     
866     #
867     # BIBLIOS : copying mandatory files
868     #
869     # the record model, depending on marc flavour
870     unless (-f "$biblioserverdir/tab/record.abs") {
871         if (C4::Context->preference("marcflavour") eq "UNIMARC") {
872             system("cp -f $kohadir/etc/zebradb/marc_defs/unimarc/biblios/record.abs $biblioserverdir/tab/record.abs");
873             print "Info: copied record.abs for UNIMARC\n";
874         } else {
875             system("cp -f $kohadir/etc/zebradb/marc_defs/marc21/biblios/record.abs $biblioserverdir/tab/record.abs");
876             print "Info: copied record.abs for USMARC\n";
877         }
878         $created_dir_or_file++;
879     }
880     unless (-f "$biblioserverdir/tab/sort-string-utf.chr") {
881         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $biblioserverdir/tab/sort-string-utf.chr");
882         print "Info: copied sort-string-utf.chr\n";
883         $created_dir_or_file++;
884     }
885     unless (-f "$biblioserverdir/tab/word-phrase-utf.chr") {
886         system("cp -f $kohadir/etc/zebradb/lang_defs/fr/sort-string-utf.chr $biblioserverdir/tab/word-phrase-utf.chr");
887         print "Info: copied word-phase-utf.chr\n";
888         $created_dir_or_file++;
889     }
890     unless (-f "$biblioserverdir/tab/bib1.att") {
891         system("cp -f $kohadir/etc/zebradb/biblios/etc/bib1.att $biblioserverdir/tab/bib1.att");
892         print "Info: copied bib1.att\n";
893         $created_dir_or_file++;
894     }
895     unless (-f "$biblioserverdir/tab/default.idx") {
896         system("cp -f $kohadir/etc/zebradb/etc/default.idx $biblioserverdir/tab/default.idx");
897         print "Info: copied default.idx\n";
898         $created_dir_or_file++;
899     }
900     unless (-f "$biblioserverdir/etc/ccl.properties") {
901 #         system("cp -f $kohadir/etc/zebradb/ccl.properties ".C4::Context->zebraconfig('biblioserver')->{ccl2rpn});
902         system("cp -f $kohadir/etc/zebradb/ccl.properties $biblioserverdir/etc/ccl.properties");
903         print "Info: copied ccl.properties\n";
904         $created_dir_or_file++;
905     }
906     unless (-f "$biblioserverdir/etc/pqf.properties") {
907 #         system("cp -f $kohadir/etc/zebradb/pqf.properties ".C4::Context->zebraconfig('biblioserver')->{ccl2rpn});
908         system("cp -f $kohadir/etc/zebradb/pqf.properties $biblioserverdir/etc/pqf.properties");
909         print "Info: copied pqf.properties\n";
910         $created_dir_or_file++;
911     }
912     
913     #
914     # BIBLIOS : copying mandatory files
915     #
916     unless (-f C4::Context->zebraconfig('biblioserver')->{config}) {
917     open ZD,">:utf8 ",C4::Context->zebraconfig('biblioserver')->{config};
918     print ZD "
919 # generated by KOHA/misc/migrtion_tools/rebuild_zebra.pl 
920 profilePath:\${srcdir:-.}:$biblioserverdir/tab/:$tabdir/tab/:\${srcdir:-.}/tab/
921
922 encoding: UTF-8
923 # Files that describe the attribute sets supported.
924 attset:bib1.att
925 attset:explain.att
926 attset:gils.att
927
928 modulePath:$modulesdir/modules/
929 # Specify record type
930 iso2709.recordType:grs.marcxml.record
931 recordType:grs.xml
932 recordId: (bib1,Local-Number)
933 storeKeys:1
934 storeData:1
935
936
937 # Lock File Area
938 lockDir: $biblioserverdir/lock
939 perm.anonymous:r
940 perm.kohaadmin:rw
941 register: $biblioserverdir/register:4G
942 shadow: $biblioserverdir/shadow:4G
943
944 # Temp File area for result sets
945 setTmpDir: $biblioserverdir/tmp
946
947 # Temp File area for index program
948 keyTmpDir: $biblioserverdir/key
949
950 # Approx. Memory usage during indexing
951 memMax: 40M
952 rank:rank-1
953     ";
954         print "Info: creating zebra-biblios.cfg\n";
955         $created_dir_or_file++;
956     }
957     
958     if ($created_dir_or_file) {
959         print "Info: created : $created_dir_or_file directories & files\n";
960     } else {
961         print "Info: file & directories OK\n";
962     }
963     
964 }
965 }