Fixes bug with MARChtml2xml in Biblio.pm
[koha.git] / C4 / Biblio.pm
1 package C4::Biblio;
2 # New XML API added by tgarip@neu.edu.tr 25/08/06
3 # Copyright 2000-2002 Katipo Communications
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19 use strict;
20 require Exporter;
21 use C4::Context;
22 use XML::Simple;
23 use Encode;
24 use utf8;
25
26 use vars qw($VERSION @ISA @EXPORT);
27
28 # set the version for version checking
29 $VERSION = 2.01;
30
31 @ISA = qw(Exporter);
32
33 # &itemcount removed, now  resides in Search.pm
34 #
35 @EXPORT = qw(
36
37 &getitemtypes
38 &getkohafields
39 &getshelves
40
41 &NEWnewbiblio 
42 &NEWnewitem
43 &NEWmodbiblio 
44 &NEWmoditem
45 &NEWdelbiblio 
46 &NEWdelitem
47 &NEWmodbiblioframework
48
49
50 &MARCfind_marc_from_kohafield
51 &MARCfind_frameworkcode
52 &MARCfind_itemtype
53 &MARCgettagslib
54 &MARCitemsgettagslib
55
56 &MARCfind_attr_from_kohafield
57 &MARChtml2xml 
58
59
60 &XMLgetbiblio 
61 &XMLgetbibliohash
62 &XMLgetitem 
63 &XMLgetitemhash
64 &XMLgetallitems 
65 &XML_xml2hash 
66 &XML_xml2hash_onerecord
67 &XML_hash2xml 
68 &XMLmarc2koha
69 &XMLmarc2koha_onerecord
70 &XML_readline
71 &XML_readline_onerecord
72 &XML_readline_asarray
73 &XML_writeline
74 &XML_writeline_id
75 &XMLmoditemonefield
76 &XMLkoha2marc
77 &XML_separate
78
79 &ZEBRAdelbiblio
80 &ZEBRAgetrecord   
81 &ZEBRAop 
82 &ZEBRAopserver 
83 &ZEBRA_readyXML 
84 &ZEBRA_readyXML_noheader
85
86 &newbiblio
87 &modbiblio
88 &DisplayISBN
89
90 );
91
92 #################### XML XML  XML  XML ###################
93 ### XML Read- Write functions
94 sub XML_readline_onerecord{
95 my ($xml,$kohafield,$recordtype,$tag,$subf)=@_;
96 #$xml represents one record of MARCXML as perlhashed 
97 ### $recordtype is needed for mapping the correct field
98  ($tag,$subf)=MARCfind_marc_from_kohafield($kohafield,$recordtype) if $kohafield;
99
100 if ($tag){
101 my $biblio=$xml->{'datafield'};
102 my $controlfields=$xml->{'controlfield'};
103 my $leader=$xml->{'leader'};
104  if ($tag>9){
105         foreach my $data (@$biblio){
106             if ($data->{'tag'} eq $tag){
107                 foreach my $subfield ( $data->{'subfield'}){
108                     foreach my $code ( @$subfield){
109                         if ($code->{'code'} eq $subf){
110                         return $code->{'content'};
111                         }
112                    }
113                 }
114            }
115         }
116   }else{
117         if ($tag eq "000" || $tag eq "LDR"){
118                 return  $leader->[0] if $leader->[0];
119         }else{
120              foreach my $control (@$controlfields){
121                 if ($control->{'tag'} eq $tag){
122                 return  $control->{'content'} if $control->{'content'};
123                 }
124             }
125         }
126    }##tag
127 }## if tag is mapped
128 return "";
129 }
130 sub XML_readline_asarray{
131 my ($xml,$kohafield,$recordtype,$tag,$subf)=@_;
132 #$xml represents one record of MARCXML as perlhashed 
133 ## returns an array of read fields--useful for readind repeated fields
134 ### $recordtype is needed for mapping the correct field if supplied
135 ### If only $tag is give reads the whole tag
136 my @value;
137  ($tag,$subf)=MARCfind_marc_from_kohafield($kohafield,$recordtype) if $kohafield;
138 if ($tag){
139 my $biblio=$xml->{'datafield'};
140 my $controlfields=$xml->{'controlfield'};
141 my $leader=$xml->{'leader'};
142  if ($tag>9){
143         foreach my $data (@$biblio){
144             if ($data->{'tag'} eq $tag){
145                 foreach my $subfield ( $data->{'subfield'}){
146                     foreach my $code ( @$subfield){
147                         if ($code->{'code'} eq $subf || !$subf){
148                         push @value, $code->{'content'};
149                         }
150                    }
151                 }
152            }
153         }
154   }else{
155         if ($tag eq "000" || $tag eq "LDR"){
156                 push @value,  $leader->[0] if $leader->[0];
157         }else{
158              foreach my $control (@$controlfields){
159                 if ($control->{'tag'} eq $tag){
160                 push @value,    $control->{'content'} if $control->{'content'};
161
162                 }
163             }
164         }
165    }##tag
166 }## if tag is mapped
167 return @value;
168 }
169
170 sub XML_readline{
171 my ($xml,$kohafield,$recordtype,$tag,$subf)=@_;
172 #$xml represents one record node hashed of holdings or a complete xml koharecord
173 ### $recordtype is needed for reading the child records( like holdings records) .Otherwise main  record is assumed ( like biblio)
174 ## holding records are parsed and sent here one by one
175 # If kohafieldname given find tag
176
177 ($tag,$subf)=MARCfind_marc_from_kohafield($kohafield,$recordtype) if $kohafield;
178 my @itemresults;
179 if ($tag){
180 if ($recordtype eq "holdings"){
181         my $item=$xml->{'datafield'};
182         my $hcontrolfield=$xml->{'controlfield'};
183      if ($tag>9){
184         foreach my $data (@$item){
185             if ($data->{'tag'} eq $tag){
186                 foreach my $subfield ( $data->{'subfield'}){
187                     foreach my $code ( @$subfield){
188                         if ($code->{'code'} eq $subf){
189                         return $code->{content};
190                         }
191                    }
192                 }
193            }
194         }
195       }else{
196         foreach my $control (@$hcontrolfield){
197                 if ($control->{'tag'} eq $tag){
198                 return  $control->{'content'};
199                 }
200         }
201       }##tag
202
203 }else{ ##Not a holding read biblio
204 my $biblio=$xml->{'record'}->[0]->{'datafield'};
205 my $controlfields=$xml->{'record'}->[0]->{'controlfield'};
206  if ($tag>9){
207         foreach my $data (@$biblio){
208             if ($data->{'tag'} eq $tag){
209                 foreach my $subfield ( $data->{'subfield'}){
210                     foreach my $code ( @$subfield){
211                         if ($code->{'code'} eq $subf){
212                         return $code->{'content'};
213                         }
214                    }
215                 }
216            }
217         }
218   }else{
219         
220         foreach my $control (@$controlfields){
221                 if ($control->{'tag'} eq $tag){
222                 return  $control->{'content'}if $control->{'content'};
223                 }
224         }
225    }##tag
226 }## Holding or not
227 }## if tag is mapped
228 return "";
229 }
230
231 sub XML_writeline{
232 ## This routine modifies one line of marcxml record hash
233 my ($xml,$kohafield,$newvalue,$recordtype,$tag,$subf)=@_;
234 $newvalue= Encode::decode('utf8',$newvalue) if $newvalue;
235 my $biblio=$xml->{'datafield'};
236 my $controlfield=$xml->{'controlfield'};
237  ($tag,$subf)=MARCfind_marc_from_kohafield($kohafield,$recordtype) if $kohafield;
238 my $updated=0;
239     if ($tag>9){
240         foreach my $data (@$biblio){
241                         if ($data->{'tag'} eq $tag){
242                         my @subfields=$data->{'subfield'};
243                         my @newsubs;
244                         foreach my $subfield ( @subfields){
245                               foreach my $code ( @$subfield){
246                                 if ($code->{'code'} eq $subf){  
247                                 $code->{'content'}=$newvalue;
248                                 $updated=1;
249                                 }
250                               push @newsubs,$code;
251                               }
252                         }
253                      if (!$updated){    
254                          push @newsubs,{code=>$subf,content=>$newvalue};
255                         $data->{subfield}= \@newsubs;
256                         $updated=1;
257                      }  
258                 }
259          }
260         ## Tag did not exist
261              if (!$updated){
262                 if ($subf){     
263                         push @$biblio,
264                                            {
265                                              'ind1' => ' ',
266                                              'ind2' => ' ',
267                                              'subfield' => [
268                                                              {
269                                                                'content' =>$newvalue,
270                                                                'code' => $subf
271                                                              }
272                                                            ],
273                                              'tag' =>$tag
274                                            } ;
275                    }else{
276                         push @$biblio,
277                                            {
278                                              'ind1' => ' ',
279                                              'ind2' => ' ',
280                                              'tag' =>$tag
281                                            } ;
282                    }                                                            
283            }## created now
284     }else{
285         foreach my $control (@$controlfield){
286                 if ($control->{'tag'} eq $tag){
287                         $control->{'content'}=$newvalue;
288                         $updated=1;
289                 }
290              }
291          if (!$updated){
292            push @$controlfield,{tag=>$tag,content=>$newvalue};     
293         }
294    }
295 return $xml;
296 }
297
298 sub XML_writeline_id {
299 ### This routine is similar to XML_writeline but replaces a given value and do not create a new field
300 ## Useful for repeating fields
301 ## Currently  usedin authorities
302 my ($xml,$oldvalue,$newvalue,$tag,$subf)=@_;
303 $newvalue= Encode::decode('utf8',$newvalue) if $newvalue;
304 my $biblio=$xml->{'datafield'};
305 my $controlfield=$xml->{'controlfield'};
306     if ($tag>9){
307         foreach my $data (@$biblio){
308                         if ($data->{'tag'} eq $tag){
309                         my @subfields=$data->{'subfield'};
310                         foreach my $subfield ( @subfields){
311                               foreach my $code ( @$subfield){
312                                 if ($code->{'code'} eq $subf && $code->{'content'} eq $oldvalue){       
313                                 $code->{'content'}=$newvalue;
314                                 }
315                               }
316                         }       
317                 }
318          }
319     }else{
320         foreach my $control(@$controlfield){
321                 if ($control->{'tag'} eq $tag  && $control->{'content'} eq $oldvalue ){
322                         $control->{'content'}=$newvalue;
323                 }
324              }
325    }
326 return $xml;
327 }
328
329 sub XML_xml2hash{
330 ##make a perl hash from xml file
331 my ($xml)=@_;
332   my $hashed = XMLin( $xml ,KeyAttr =>['leader','controlfield','datafield'],ForceArray => ['leader','controlfield','datafield','subfield','holdings','record'],KeepRoot=>0);
333 return $hashed;
334 }
335
336 sub XML_separate{
337 ##Separates items from biblio
338 my $hashed=shift;
339 my $biblio=$hashed->{record}->[0];
340 my @items;
341 my $items=$hashed->{holdings}->[0]->{record};
342 foreach my $item (@$items){
343  push @items,$item;
344 }
345 return ($biblio,@items);
346 }
347
348 sub XML_xml2hash_onerecord{
349 ##make a perl hash from xml file
350 my ($xml)=@_;
351   my $hashed = XMLin( $xml ,KeyAttr =>['leader','controlfield','datafield'],ForceArray => ['leader','controlfield','datafield','subfield'],KeepRoot=>0);
352 return $hashed;
353 }
354 sub XML_hash2xml{
355 ## turn a hash back to xml
356 my ($hashed,$root)=@_;
357 $root="record" unless $root;
358 my $xml= XMLout($hashed,KeyAttr=>['leader','controlfıeld','datafield'],NoSort => 1,AttrIndent => 0,KeepRoot=>0,SuppressEmpty => 1,RootName=>$root );
359 return $xml;
360 }
361
362
363
364 sub XMLgetbiblio {
365     # Returns MARC::XML of the biblionumber passed in parameter.
366     my ( $dbh, $biblionumber ) = @_;
367     my $sth =      $dbh->prepare("select marcxml from biblio where biblionumber=? "  );
368     $sth->execute( $biblionumber);
369    my ($marcxml)=$sth->fetchrow;
370         $marcxml=Encode::decode('utf8',$marcxml);
371  return ($marcxml);
372 }
373
374 sub XMLgetbibliohash{
375 ## Utility to return s hashed MARCXML
376 my ($dbh,$biblionumber)=@_;
377 my $xml=XMLgetbiblio($dbh,$biblionumber);
378 my $xmlhash=XML_xml2hash_onerecord($xml);
379 return $xmlhash;
380 }
381
382 sub XMLgetitem {
383    # Returns MARC::XML   of the item passed in parameter uses either itemnumber or barcode
384     my ( $dbh, $itemnumber,$barcode ) = @_;
385 my $sth;
386 if ($itemnumber){
387    $sth = $dbh->prepare("select marcxml from items  where itemnumber=?"  ); 
388     $sth->execute($itemnumber);
389 }else{
390  $sth = $dbh->prepare("select marcxml from items where barcode=?"  ); 
391     $sth->execute($barcode);
392 }
393  my ($marcxml)=$sth->fetchrow;
394 $marcxml=Encode::decode('utf8',$marcxml);
395     return ($marcxml);
396 }
397 sub XMLgetitemhash{
398 ## Utility to return s hashed MARCXML
399  my ( $dbh, $itemnumber,$barcode ) = @_;
400 my $xml=XMLgetitem( $dbh, $itemnumber,$barcode);
401 my $xmlhash=XML_xml2hash_onerecord($xml);
402 return $xmlhash;
403 }
404
405
406 sub XMLgetallitems {
407 # warn "XMLgetallitems";
408     # Returns an array of MARC:XML   of the items passed in parameter as biblionumber
409     my ( $dbh, $biblionumber ) = @_;
410 my @results;
411 my   $sth = $dbh->prepare("select marcxml from items where biblionumber =?"  ); 
412     $sth->execute($biblionumber);
413
414  while(my ($marcxml)=$sth->fetchrow_array){
415 $marcxml=Encode::decode('utf8',$marcxml);
416     push @results,$marcxml;
417 }
418 return @results;
419 }
420
421 sub XMLmarc2koha {
422 # warn "XMLmarc2koha";
423 ##Returns two hashes from KOHA_XML record hashed
424 ## A biblio hash and and array of item hashes
425         my ($dbh,$xml,$related_record,@fields) = @_;
426         my ($result,@items);
427         
428 ## if @fields is given do not bother about the rest of fields just parse those
429
430 if ($related_record eq "biblios" || $related_record eq "" || !$related_record){
431         if (@fields){
432                 foreach my $field(@fields){
433                 my $val=&XML_readline($xml,$field,'biblios');
434                         $result->{$field}=$val if $val;
435                         
436                 }
437         }else{
438         my $sth2=$dbh->prepare("SELECT  marctokoha from koha_attr where  recordtype like 'biblios' and tagfield is not null" );
439         $sth2->execute();
440         my $field;
441                 while ($field=$sth2->fetchrow) {
442                 $result->{$field}=&XML_readline($xml,$field,'biblios');
443                 }
444         }
445
446 ## we only need the following for biblio data
447         
448 # modify copyrightdate to keep only the 1st year found
449         my $temp = $result->{'copyrightdate'};
450         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
451         if ($1>0) {
452                 $result->{'copyrightdate'} = $1;
453         } else { # if no cYYYY, get the 1st date.
454                 $temp =~ m/(\d\d\d\d)/;
455                 $result->{'copyrightdate'} = $1;
456         }
457 # modify publicationyear to keep only the 1st year found
458         $temp = $result->{'publicationyear'};
459         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
460         if ($1>0) {
461                 $result->{'publicationyear'} = $1;
462         } else { # if no cYYYY, get the 1st date.
463                 $temp =~ m/(\d\d\d\d)/;
464                 $result->{'publicationyear'} = $1;
465         }
466 }
467 if ($related_record eq "holdings" || $related_record eq ""  || !$related_record){
468 my $holdings=$xml->{holdings}->[0]->{record};
469
470
471         if (@fields){
472             foreach my $holding (@$holdings){   
473 my $itemresult;
474                 foreach my $field(@fields){
475                 my $val=&XML_readline($holding,$field,'holdings');
476                 $itemresult->{$field}=$val if $val;     
477                 }
478             push @items, $itemresult;
479            }
480         }else{
481         my $sth2=$dbh->prepare("SELECT  marctokoha from koha_attr where recordtype like 'holdings' and tagfield is not null" );
482            foreach my $holding (@$holdings){    
483            $sth2->execute();
484             my $field;
485 my $itemresult;
486                 while ($field=$sth2->fetchrow) {
487                 $itemresult->{$field}=&XML_readline($xml,$field,'holdings');
488                 }
489          push @items, $itemresult;
490            }
491         }
492
493 }
494
495         return ($result,@items);
496 }
497 sub XMLmarc2koha_onerecord {
498 # warn "XMLmarc2koha_onerecord";
499 ##Returns a koha hash from MARCXML hash
500
501         my ($dbh,$xml,$related_record,@fields) = @_;
502         my ($result);
503         
504 ## if @fields is given do not bother about the rest of fields just parse those
505
506         if (@fields){
507                 foreach my $field(@fields){
508                 my $val=&XML_readline_onerecord($xml,$field,$related_record);
509                         $result->{$field}=$val if $val;                 
510                 }
511         }else{
512         my $sth2=$dbh->prepare("SELECT  marctokoha from koha_attr where  recordtype like ? and tagfield is not null" );
513         $sth2->execute($related_record);
514         my $field;
515                 while ($field=$sth2->fetchrow) {
516                 $result->{$field}=&XML_readline_onerecord($xml,$field,$related_record);
517                 }
518         }
519         return ($result);
520 }
521
522 sub XMLmodLCindex{
523 # warn "XMLmodLCindex";
524 my ($dbh,$xmlhash)=@_;
525 my ($lc)=XML_readline_onerecord($xmlhash,"classification","biblios");
526 my ($cutter)=XML_readline_onerecord($xmlhash,"subclass","biblios");
527
528         if ($lc){
529         $lc.=$cutter;
530         my ($lcsort)=calculatelc($lc);
531         $xmlhash=XML_writeline($xmlhash,"lcsort",$lcsort,"biblios");
532         }
533 return $xmlhash;
534 }
535
536 sub XMLmoditemonefield{
537 # This routine takes itemnumber and biblionumber and updates XMLmarc;
538 ### the ZEBR DB update can wait depending on $donotupdate flag
539 my ($dbh,$biblionumber,$itemnumber,$itemfield,$newvalue,$donotupdate)=@_;
540 my ($record) = XMLgetitem($dbh,$itemnumber);
541         my $recordhash=XML_xml2hash_onerecord($record);
542         XML_writeline( $recordhash, $itemfield, $newvalue,"holdings" ); 
543  if($donotupdate){
544         ## Prevent various update calls to zebra wait until all changes finish
545                 $record=XML_hash2xml($recordhash);
546                 my $sth=$dbh->prepare("update items set marcxml=? where itemnumber=?");
547                 $sth->execute($record,$itemnumber);
548                 $sth->finish;
549         }else{
550                 NEWmoditem($dbh,$recordhash,$biblionumber,$itemnumber);
551   }
552
553 }
554
555 sub XMLkoha2marc {
556 # warn "MARCkoha2marc";
557 ## This routine  is still used for acqui management
558 ##Returns a  XML recordhash from a kohahash
559         my ($dbh,$result,$recordtype) = @_;
560 ###create a basic MARCXML
561 # find today's date
562 my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
563         $year += 1900;
564         $mon += 1;
565         my $timestamp = sprintf("%4d%02d%02d%02d%02d%02d.0",
566                 $year,$mon,$mday,$hour,$min,$sec);
567 $year=substr($year,2,2);
568         my $accdate=sprintf("%2d%02d%02d",$year,$mon,$mday);
569 my ($titletag,$titlesubf)=MARCfind_marc_from_kohafield("title","biblios");
570 my $xml="<record><leader>     naa a22     7ar4500</leader><controlfield tag='005'>$timestamp</controlfield><controlfield tag='008'>$accdate</controlfield><datafield ind1='' ind2='' tag='$titletag'></datafield></record>";
571 ## Now build XML
572         my $record = XML_xml2hash($xml);
573         my $sth2=$dbh->prepare("SELECT  marctokoha from koha_attr where tagfield is not null and recordtype=?");
574         $sth2->execute($recordtype);
575         my $field;
576         while (($field)=$sth2->fetchrow) {
577 warn $field;
578                 $record=XML_writeline($record,$field,$result->{$field},$recordtype) if $result->{$field};
579         }
580 return $record;
581 }
582
583 #
584 #
585 # MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC
586 #
587 ## Script to deal with MARCXML related tables
588
589
590 ##Sub to match kohafield to Z3950 -attributes
591
592 sub MARCfind_attr_from_kohafield {
593 # warn "MARCfind_attr_from_kohafield";
594 ## returns attribute
595     my (  $kohafield ) = @_;
596     return 0, 0 unless $kohafield;
597
598         my $relations = C4::Context->attrfromkohafield;
599         return ($relations->{$kohafield});
600 }
601
602
603 sub MARCgettagslib {
604 # warn "MARCgettagslib";
605     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
606     $frameworkcode = "" unless $frameworkcode;
607     my $sth;
608     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
609
610     # check that framework exists
611     $sth =
612       $dbh->prepare(
613         "select count(*) from biblios_tag_structure where frameworkcode=?");
614     $sth->execute($frameworkcode);
615     my ($total) = $sth->fetchrow;
616     $frameworkcode = "" unless ( $total > 0 );
617     $sth =
618       $dbh->prepare(
619 "select tagfield,liblibrarian,libopac,mandatory,repeatable from biblios_tag_structure where frameworkcode=? order by tagfield"
620     );
621     $sth->execute($frameworkcode);
622     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
623
624     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
625         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
626         $res->{$tab}->{tab}        = "";            # XXX
627         $res->{$tag}->{mandatory}  = $mandatory;
628         $res->{$tag}->{repeatable} = $repeatable;
629     }
630
631     $sth =
632       $dbh->prepare(
633 "select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,seealso,hidden,isurl,link from biblios_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
634     );
635     $sth->execute($frameworkcode);
636
637     my $subfield;
638     my $authorised_value;
639     my $authtypecode;
640     my $value_builder;
641    
642     my $seealso;
643     my $hidden;
644     my $isurl;
645         my $link;
646
647     while (
648         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
649         $mandatory,     $repeatable, $authorised_value, $authtypecode,
650         $value_builder,   $seealso,          $hidden,
651         $isurl,                 $link )
652         = $sth->fetchrow
653       )
654     {
655         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
656         $res->{$tag}->{$subfield}->{tab}              = $tab;
657         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
658         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
659         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
660         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
661         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
662         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
663         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
664         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
665         $res->{$tag}->{$subfield}->{link}            = $link;
666     }
667     return $res;
668 }
669 sub MARCitemsgettagslib {
670 # warn "MARCitemsgettagslib";
671     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
672     $frameworkcode = "" unless $frameworkcode;
673     my $sth;
674     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
675
676     # check that framework exists
677     $sth =
678       $dbh->prepare(
679         "select count(*) from holdings_tag_structure where frameworkcode=?");
680     $sth->execute($frameworkcode);
681     my ($total) = $sth->fetchrow;
682     $frameworkcode = "" unless ( $total > 0 );
683     $sth =
684       $dbh->prepare(
685 "select tagfield,liblibrarian,libopac,mandatory,repeatable from holdings_tag_structure where frameworkcode=? order by tagfield"
686     );
687     $sth->execute($frameworkcode);
688     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
689
690     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
691         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
692         $res->{$tab}->{tab}        = "";            # XXX
693         $res->{$tag}->{mandatory}  = $mandatory;
694         $res->{$tag}->{repeatable} = $repeatable;
695     }
696
697     $sth =
698       $dbh->prepare(
699 "select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,seealso,hidden,isurl,link from holdings_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
700     );
701     $sth->execute($frameworkcode);
702
703     my $subfield;
704     my $authorised_value;
705     my $authtypecode;
706     my $value_builder;
707    
708     my $seealso;
709     my $hidden;
710     my $isurl;
711         my $link;
712
713     while (
714         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
715         $mandatory,     $repeatable, $authorised_value, $authtypecode,
716         $value_builder, $seealso,          $hidden,
717         $isurl,                 $link )
718         = $sth->fetchrow
719       )
720     {
721         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
722         $res->{$tag}->{$subfield}->{tab}              = $tab;
723         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
724         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
725         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
726         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
727         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
728         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
729         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
730         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
731         $res->{$tag}->{$subfield}->{link}            = $link;
732     }
733     return $res;
734 }
735 sub MARCfind_marc_from_kohafield {
736 # warn "MARCfind_marc_from_kohafield";
737     my (  $kohafield,$recordtype) = @_;
738     return 0, 0 unless $kohafield;
739 $recordtype="biblios" unless $recordtype;
740         my $relations = C4::Context->marcfromkohafield;
741         return ($relations->{$recordtype}->{$kohafield}->[0],$relations->{$recordtype}->{$kohafield}->[1]);
742 }
743
744
745
746
747 sub MARCfind_frameworkcode {
748 # warn "MARCfind_frameworkcode";
749     my ( $dbh, $biblionumber ) = @_;
750     my $sth =
751       $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
752     $sth->execute($biblionumber);
753     my ($frameworkcode) = $sth->fetchrow;
754     return $frameworkcode;
755 }
756 sub MARCfind_itemtype {
757 # warn "MARCfind_itemtype";
758     my ( $dbh, $biblionumber ) = @_;
759     my $sth =
760       $dbh->prepare("select itemtype from biblio where biblionumber=?");
761     $sth->execute($biblionumber);
762     my ($itemtype) = $sth->fetchrow;
763     return $itemtype;
764 }
765
766
767
768 sub MARChtml2xml {
769 # warn "MARChtml2xml ";
770         my ($tags,$subfields,$values,$indicator,$ind_tag,$tagindex) = @_;        
771         my $xml= "<record>";
772
773     my $prevvalue;
774     my $prevtag=-1;
775     my $first=1;
776         my $j = -1;
777     for (my $i=0;$i<=@$tags;$i++){
778                 @$values[$i] =~ s/&/&amp;/g;
779                 @$values[$i] =~ s/</&lt;/g;
780                 @$values[$i] =~ s/>/&gt;/g;
781                 @$values[$i] =~ s/"/&quot;/g;
782                 @$values[$i] =~ s/'/&apos;/g;
783
784                 if ((@$tags[$i].@$tagindex[$i] ne $prevtag)){
785                         my $tag=@$tags[$i];
786                         $j++ unless ($tag eq "");
787                         ## warn "IND:".substr(@$indicator[$j],0,1).substr(@$indicator[$j],1,1)." ".@$tags[$i];
788                         if (!$first){
789                         $xml.="</datafield>\n";
790                                 if (($tag> 10) && (@$values[$i] ne "")){
791                                                 my $ind1 = substr(@$indicator[$j],0,1);
792                         my $ind2 = substr(@$indicator[$j],1,1);
793                         $xml.="<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
794                         $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
795                         $first=0;
796                                 } else {
797                         $first=1;
798                                 }
799                                 } else {
800                         if (@$values[$i] ne "") {
801                                 # leader
802                                 if ($tag eq "000") {
803                                 ##Force the leader to UTF8
804                                 substr(@$values[$i],9,1)="a";
805                                                 $xml.="<leader>@$values[$i]</leader>\n";
806                                                 $first=1;
807                                         # rest of the fixed fields
808                                 } elsif ($tag < 10) {
809                                                 $xml.="<controlfield tag=\"$tag\">@$values[$i]</controlfield>\n";
810                                                 $first=1;
811                                 } else {
812                                                 my $ind1 = substr(@$indicator[$j],0,1);
813                                                 my $ind2 = substr(@$indicator[$j],1,1);
814                                                 $xml.="<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
815                                                 $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
816                                                 $first=0;                       
817                                 }
818                         }
819                         }
820                 } else { # @$tags[$i] eq $prevtag
821                                  unless (@$values[$i] eq "") {
822                         my $tag=@$tags[$i];
823                                         if ($first){
824                                                 my $ind1 = substr(@$indicator[$j],0,1);                        
825                                                 my $ind2 = substr(@$indicator[$j],1,1);
826                                                 $xml.="<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
827                                                 $first=0;
828                                         }
829                         $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
830                                 }
831                 }
832                 $prevtag = @$tags[$i].@$tagindex[$i];
833         }
834         $xml.="</record>";
835         # warn $xml;
836         $xml=Encode::decode('utf8',$xml);
837         return $xml;
838 }
839 sub marc_record_header {
840 ####  this one is for <record>
841     my $format = shift;
842     my $enc = shift || 'UTF-8';
843 ##
844     return( <<MARC_XML_HEADER );
845 <?xml version="1.0" encoding="$enc"?>
846 <record  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
847   xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
848   xmlns="http://www.loc.gov/MARC21/slim">
849 MARC_XML_HEADER
850 }
851
852
853 sub collection_header {
854 ####  this one is for koha collection 
855     my $format = shift;
856     my $enc = shift || 'UTF-8';
857     return( <<KOHA_XML_HEADER );
858 <?xml version="1.0" encoding="$enc"?>
859 <kohacollection xmlns:marc="http://loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://library.neu.edu.tr/kohanamespace/koharecord.xsd">
860 KOHA_XML_HEADER
861 }
862
863
864
865
866
867
868
869
870 ##########################NEW NEW NEW#############################
871 sub NEWnewbiblio {
872     my ( $dbh, $xml, $frameworkcode) = @_;
873 $frameworkcode="" unless $frameworkcode;
874 my $biblionumber=XML_readline_onerecord($xml,"biblionumber","biblios");
875 ## In case reimporting records with biblionumbers keep them
876 if ($biblionumber){
877 $biblionumber=NEWmodbiblio( $dbh, $biblionumber,$xml,$frameworkcode );
878 }else{
879     $biblionumber = NEWaddbiblio( $dbh, $xml,$frameworkcode );
880 }
881
882    return ( $biblionumber );
883 }
884
885
886
887
888
889 sub NEWmodbiblioframework {
890         my ($dbh,$biblionumber,$frameworkcode) =@_;
891         my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=$biblionumber");
892         $sth->execute($frameworkcode);
893         return 1;
894 }
895
896
897 sub NEWdelbiblio {
898     my ( $dbh, $biblionumber ) = @_;
899 ZEBRAop($dbh,$biblionumber,"recordDelete","biblioserver");
900 }
901
902
903 sub NEWnewitem {
904     my ( $dbh, $xmlhash, $biblionumber ) = @_;
905         my $itemtype= MARCfind_itemtype($dbh,$biblionumber);
906
907 ## In case we are re-importing marc records from bulk import do not change itemnumbers
908 my $itemnumber=XML_readline_onerecord($xmlhash,"itemnumber","holdings");
909 if ($itemnumber){
910 NEWmoditem ( $dbh, $xmlhash, $biblionumber, $itemnumber);
911 }else{
912    
913 ##Add biblionumber to $record
914 $xmlhash=XML_writeline($xmlhash,"biblionumber",$biblionumber,"holdings");
915 #    MARCkoha2marcOnefield($record,"biblionumber",$biblionumber,"holdings");
916  my $sth=$dbh->prepare("select notforloan from itemtypes where itemtype='$itemtype'");
917 $sth->execute();
918 my $notforloan=$sth->fetchrow;
919 ##Change the notforloan field if $notforloan found
920         if ($notforloan >0){
921         $xmlhash=XML_writeline($xmlhash,"notforloan",$notforloan,"holdings");
922         }
923 my $dateaccessioned=XML_readline_onerecord($xmlhash,"dateaccessioned","holdings");
924 unless($dateaccessioned){
925 # find today's date
926 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =                                                           
927 localtime(time); $year +=1900; $mon +=1;
928 my $date = "$year-".sprintf ("%0.2d", $mon)."-".sprintf("%0.2d",$mday);
929
930 $xmlhash=XML_writeline($xmlhash,"dateaccessioned",$date,"holdings");
931 }
932   
933 ## Now calculate itempart of cutter-- This is NEU specific
934 my $itemcallnumber=XML_readline_onerecord($xmlhash,"itemcallnumber","holdings");
935 if ($itemcallnumber){
936 my ($cutterextra)=itemcalculator($dbh,$biblionumber,$itemcallnumber);
937 $xmlhash=XML_writeline($xmlhash,"cutterextra",$cutterextra,"holdings");
938 }
939
940 ##NEU specific add cataloguers cardnumber as well
941 my $me= C4::Context->userenv;
942 my $cataloger=$me->{'cardnumber'} if ($me);
943 $xmlhash=XML_writeline($xmlhash,"circid",$cataloger,"holdings") if $cataloger;
944
945 ##Add item to SQL
946 my  $itemnumber = &OLDnewitems( $dbh, $xmlhash );
947
948 # add the item to zebra it will add the biblio as well!!!
949     ZEBRAop( $dbh, $biblionumber,"specialUpdate","biblioserver" );
950 return $itemnumber;
951 }## added new item
952
953 }
954
955
956
957 sub NEWmoditem{
958     my ( $dbh, $xmlhash, $biblionumber, $itemnumber ) = @_;
959
960 ##Add itemnumber incase lost (old bug 090c was lost sometimes) --just incase
961 $xmlhash=XML_writeline($xmlhash,"itemnumber",$itemnumber,"holdings");
962 ##Add biblionumber incase lost on html
963 $xmlhash=XML_writeline($xmlhash,"biblionumber",$biblionumber,"holdings");
964 ##Read barcode
965 my $barcode=XML_readline_onerecord($xmlhash,"barcode","holdings");              
966 ## Now calculate itempart of cutter-- This is NEU specific
967 my $itemcallnumber=XML_readline_onerecord($xmlhash,"itemcallnumber","holdings");
968 if ($itemcallnumber){
969 my ($cutterextra)=itemcalculator($dbh,$biblionumber,$itemcallnumber);
970 $xmlhash=XML_writeline($xmlhash,"cutterextra",$cutterextra,"holdings");
971 }
972
973 ##NEU specific add cataloguers cardnumber as well
974 my $me= C4::Context->userenv;
975 my $cataloger=$me->{'cardnumber'} if ($me);
976 $xmlhash=XML_writeline($xmlhash,"circid",$cataloger,"holdings") if $cataloger;
977 my $xml=XML_hash2xml($xmlhash);
978     OLDmoditem( $dbh, $xml,$biblionumber,$itemnumber,$barcode );
979     ZEBRAop($dbh,$biblionumber,"specialUpdate","biblioserver");
980 }
981
982 sub NEWdelitem {
983     my ( $dbh, $itemnumber ) = @_;      
984 my $sth=$dbh->prepare("SELECT biblionumber from items where itemnumber=?");
985 $sth->execute($itemnumber);
986 my $biblionumber=$sth->fetchrow;
987 OLDdelitem( $dbh, $itemnumber ) ;
988 ZEBRAop($dbh,$biblionumber,"specialUpdate","biblioserver");
989
990 }
991
992
993
994
995 sub NEWaddbiblio {
996     my ( $dbh, $xmlhash,$frameworkcode ) = @_;
997      my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
998     $sth->execute;
999     my $data   = $sth->fetchrow;
1000     my $biblionumber = $data + 1;
1001     $sth->finish;
1002     # we must add biblionumber 
1003 my $record;
1004 $xmlhash=XML_writeline($xmlhash,"biblionumber",$biblionumber,"biblios");
1005
1006 ###NEU specific add cataloguers cardnumber as well
1007
1008 my $me= C4::Context->userenv;
1009 my $cataloger=$me->{'cardnumber'} if ($me);
1010 $xmlhash=XML_writeline($xmlhash,"indexedby",$cataloger,"biblios") if $cataloger;
1011
1012 ## We must add the indexing fields for LC in MARC record--TG
1013 &XMLmodLCindex($dbh,$xmlhash);
1014
1015 ##Find itemtype
1016 my $itemtype=XML_readline_onerecord($xmlhash,"itemtype","biblios");
1017 ##Find ISBN
1018 my $isbn=XML_readline_onerecord($xmlhash,"isbn","biblios");
1019 ##Find ISSN
1020 my $issn=XML_readline_onerecord($xmlhash,"issn","biblios");
1021 ##Find Title
1022 my $title=XML_readline_onerecord($xmlhash,"title","biblios");
1023 ##Find Author
1024 my $author=XML_readline_onerecord($xmlhash,"title","biblios");
1025 my $xml=XML_hash2xml($xmlhash);
1026
1027     $sth = $dbh->prepare("insert into biblio set biblionumber  = ?,frameworkcode=?, itemtype=?,marcxml=?,title=?,author=?,isbn=?,issn=?" );
1028     $sth->execute( $biblionumber,$frameworkcode, $itemtype,$xml ,$title,$author,$isbn,$issn  );
1029
1030     $sth->finish;
1031 ### Do not add biblio to ZEBRA unless there is an item with it -- depends on system preference defaults to NO
1032 if (C4::Context->preference('AddaloneBiblios')){
1033  ZEBRAop($dbh,$biblionumber,"specialUpdate","biblioserver");
1034 }
1035     return ($biblionumber);
1036 }
1037
1038 sub NEWmodbiblio {
1039     my ( $dbh, $biblionumber,$xmlhash,$frameworkcode ) = @_;
1040 ##Add biblionumber incase lost on html
1041
1042 $xmlhash=XML_writeline($xmlhash,"biblionumber",$biblionumber,"biblios");
1043
1044 ###NEU specific add cataloguers cardnumber as well
1045 my $me= C4::Context->userenv;
1046 my $cataloger=$me->{'cardnumber'} if ($me);
1047
1048 $xmlhash=XML_writeline($xmlhash,"indexedby",$cataloger,"biblios") if $cataloger;
1049
1050 ## We must add the indexing fields for LC in MARC record--TG
1051
1052   XMLmodLCindex($dbh,$xmlhash);
1053     OLDmodbiblio ($dbh,$xmlhash,$biblionumber,$frameworkcode);
1054     my $ok=ZEBRAop($dbh,$biblionumber,"specialUpdate","biblioserver");
1055     return ($biblionumber);
1056 }
1057
1058 #
1059 #
1060 # OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD OLD
1061 #
1062 #
1063
1064 sub OLDnewitems {
1065
1066     my ( $dbh, $xmlhash) = @_;
1067     my $sth = $dbh->prepare("SELECT max(itemnumber) from items");
1068     my $data;
1069     my $itemnumber;
1070     $sth->execute;
1071     $data       = $sth->fetchrow_hashref;
1072     $itemnumber = $data->{'max(itemnumber)'} + 1;
1073     $sth->finish;
1074       $xmlhash=XML_writeline(  $xmlhash, "itemnumber", $itemnumber,"holdings" );
1075 my $biblionumber=XML_readline_onerecord($xmlhash,"biblionumber","holdings");
1076  my $barcode=XML_readline_onerecord($xmlhash,"barcode","holdings");
1077 my $xml=XML_hash2xml($xmlhash);
1078         $sth = $dbh->prepare( "Insert into items set itemnumber = ?,    biblionumber  = ?,barcode = ?,marcxml=?"   );
1079         $sth->execute($itemnumber,$biblionumber,$barcode,$xml);
1080     return $itemnumber;
1081 }
1082
1083 sub OLDmoditem {
1084     my ( $dbh, $xml,$biblionumber,$itemnumber,$barcode  ) = @_;
1085     my $sth =$dbh->prepare("replace items set  biblionumber=?,marcxml=?,barcode=? , itemnumber=?");
1086     $sth->execute($biblionumber,$xml,$barcode,$itemnumber);
1087     $sth->finish;
1088 }
1089
1090 sub OLDdelitem {
1091     my ( $dbh, $itemnumber ) = @_;
1092 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1093     $sth->execute($itemnumber);
1094     if ( my $data = $sth->fetchrow_hashref ) {
1095         $sth->finish;
1096         my $query = "replace deleteditems set ";
1097         my @bind  = ();
1098         foreach my $temp ( keys %$data ) {
1099             $query .= "$temp = ?,";
1100             push ( @bind, $data->{$temp} );
1101         }
1102
1103         #replacing the last , by ",?)"
1104         $query =~ s/\,$//;
1105         $sth = $dbh->prepare($query);
1106         $sth->execute(@bind);
1107         $sth->finish;
1108    $sth = $dbh->prepare("Delete from items where itemnumber=?");
1109     $sth->execute($itemnumber);
1110     $sth->finish;
1111   }
1112  $sth->finish;
1113 }
1114
1115 sub OLDmodbiblio {
1116 # modifies the biblio table
1117 my ($dbh,$xmlhash,$biblionumber,$frameworkcode) = @_;
1118         if (!$frameworkcode){
1119         $frameworkcode="";
1120         }
1121 ##Find itemtype
1122 my $itemtype=XML_readline_onerecord($xmlhash,"itemtype","biblios");
1123 ##Find ISBN
1124 my $isbn=XML_readline_onerecord($xmlhash,"isbn","biblios");
1125 ##Find ISSN
1126 my $issn=XML_readline_onerecord($xmlhash,"issn","biblios");
1127 ##Find Title
1128 my $title=XML_readline_onerecord($xmlhash,"title","biblios");
1129 ##Find Author
1130 my $author=XML_readline_onerecord($xmlhash,"author","biblios");
1131 my $xml=XML_hash2xml($xmlhash);
1132
1133 $isbn=~ s/(\.|\?|\;|\=|\-|\/|\\|\||\:|\*|\!|\,|\(|\)|\[|\]|\{|\}|\/)//g;
1134 $issn=~ s/(\.|\?|\;|\=|\-|\/|\\|\||\:|\*|\!|\,|\(|\)|\[|\]|\{|\}|\/)//g;
1135 $isbn=~s/^\s+|\s+$//g;
1136 $isbn=substr($isbn,0,13);
1137         my $sth = $dbh->prepare("REPLACE  biblio set biblionumber=?,marcxml=?,frameworkcode=? ,itemtype=? , title=?,author=?,isbn=?,issn=?" );
1138         $sth->execute( $biblionumber ,$xml, $frameworkcode,$itemtype, $title,$author,$isbn,$issn);  
1139         $sth->finish;
1140     return $biblionumber;
1141 }
1142
1143 sub OLDdelbiblio {
1144     my ( $dbh, $biblionumber ) = @_;
1145     my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1146     $sth->execute($biblionumber);
1147     if ( my $data = $sth->fetchrow_hashref ) {
1148         $sth->finish;
1149         my $query = "replace deletedbiblio set ";
1150         my @bind  = ();
1151            foreach my $temp ( keys %$data ) {
1152             $query .= "$temp = ?,";
1153             push ( @bind, $data->{$temp} );
1154            }
1155
1156         #replacing the last , by ",?)"
1157         $query =~ s/\,$//;
1158         $sth = $dbh->prepare($query);
1159         $sth->execute(@bind);
1160         $sth->finish;
1161         $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1162         $sth->execute($biblionumber);
1163         $sth->finish;
1164     }
1165     $sth->finish;
1166 }
1167
1168
1169 #
1170 #
1171 #
1172 #ZEBRA ZEBRA ZEBRA
1173 #
1174 #
1175
1176 sub ZEBRAdelbiblio {
1177 ## Zebra calls this routine to delete after it deletes biblio from ZEBRAddb
1178  my ( $dbh, $biblionumber ) = @_;
1179 my $sth=$dbh->prepare("SELECT itemnumber FROM items where biblionumber=?");
1180
1181 $sth->execute($biblionumber);
1182         while (my $itemnumber =$sth->fetchrow){
1183         OLDdelitem($dbh,$itemnumber) ;
1184         }       
1185 OLDdelbiblio($dbh,$biblionumber) ;
1186 }
1187
1188 sub ZEBRAgetrecord{
1189 my $biblionumber=shift;
1190 my @kohafield="biblionumber";
1191 my @value=$biblionumber;
1192 my ($count,@result)=C4::Search::ZEBRAsearch_kohafields(\@kohafield,\@value);
1193
1194    if ($count>0){
1195    my ( $xmlrecord, @itemsrecord) = XML_separate($result[0]);
1196    return ($xmlrecord, @itemsrecord);
1197    }else{
1198    return (undef,undef);
1199    }
1200 }
1201
1202 sub ZEBRAop {
1203 ### Puts the zebra update in queue writes in zebraserver table
1204 my ($dbh,$biblionumber,$op,$server)=@_;
1205 my ($record);
1206 my $sth=$dbh->prepare("insert into zebraqueue  (biblio_auth_number ,server,operation) values(?,?,?)");
1207 $sth->execute($biblionumber,$server,$op);
1208 }
1209
1210
1211 sub ZEBRAopserver{
1212
1213 ###Accepts a $server variable thus we can use it to update  biblios, authorities or other zebra dbs
1214 my ($record,$op,$server,$biblionumber)=@_;
1215 my @Zconnbiblio;
1216 my @port;
1217 my $Zpackage;
1218 my $tried=0;
1219 my $recon=0;
1220 my $reconnect=0;
1221 $record=Encode::encode("UTF-8",$record);
1222 my $shadow=$server."shadow";
1223 reconnect:
1224
1225 $Zconnbiblio[0]=C4::Context->Zconnauth($server);
1226 if ($record){
1227 my $Zpackage = $Zconnbiblio[0]->package();
1228 $Zpackage->option(action => $op);
1229         $Zpackage->option(record => $record);
1230         $Zpackage->option(recordIdOpaque => $biblionumber);
1231 retry:
1232                 $Zpackage->send("update");
1233 my $i;
1234 my $event;
1235
1236 while (($i = ZOOM::event(\@Zconnbiblio)) != 0) {
1237     $event = $Zconnbiblio[0]->last_event();
1238     last if $event == ZOOM::Event::ZEND;
1239 }
1240  my($error, $errmsg, $addinfo, $diagset) = $Zconnbiblio[0]->error_x();
1241         if ($error==10007 && $tried<3) {## timeout --another 30 looonng seconds for this update
1242                 sleep 1;        ##  wait a sec!
1243                 $tried=$tried+1;
1244                 goto "retry";
1245         }elsif ($error==2 && $tried<2) {## timeout --temporary zebra error !whatever that means
1246                 sleep 2;        ##  wait two seconds!
1247                 $tried=$tried+1;
1248                 goto "retry";
1249         }elsif($error==10004 && $recon==0){##Lost connection -reconnect
1250                 sleep 1;        ##  wait a sec!
1251                 $recon=1;
1252                 $Zpackage->destroy();
1253                 $Zconnbiblio[0]->destroy();
1254                 goto "reconnect";
1255         }elsif ($error){
1256         #       warn "Error-$server   $op  /errcode:, $error, /MSG:,$errmsg,$addinfo \n";       
1257                 $Zpackage->destroy();
1258                 $Zconnbiblio[0]->destroy();
1259         #       ZEBRAopfiles($dbh,$biblionumber,$record,$op,$server);
1260                 return 0;
1261         }
1262         ## System preference batchMode=1 means wea are bulk importing
1263         ## DO NOT COMMIT while in batchMode for faster operation
1264         my $batchmode=C4::Context->preference('batchMode');
1265          if (C4::Context->$shadow >0 && !$batchmode){
1266          $Zpackage->send('commit');
1267                 while (($i = ZOOM::event(\@Zconnbiblio)) != 0) {
1268                  $event = $Zconnbiblio[0]->last_event();
1269                 last if $event == ZOOM::Event::ZEND;
1270                 }
1271              my($error, $errmsg, $addinfo, $diagset) = $Zconnbiblio[0]->error_x();
1272              if ($error) { ## This is serious ZEBRA server is not updating      
1273              $Zpackage->destroy();
1274              $Zconnbiblio[0]->destroy();
1275              return 0;
1276             }
1277          }##commit
1278 #
1279 $Zpackage->destroy();
1280 $Zconnbiblio[0]->destroy();
1281 return 1;
1282 }
1283 return 0;
1284 }
1285
1286 sub ZEBRA_readyXML{
1287 my ($dbh,$biblionumber)=@_;
1288 my $biblioxml=XMLgetbiblio($dbh,$biblionumber);
1289 my @itemxml=XMLgetallitems($dbh,$biblionumber);
1290 my $zebraxml=collection_header();
1291 $zebraxml.="<koharecord>";
1292 $zebraxml.=$biblioxml;
1293 $zebraxml.="<holdings>";
1294       foreach my $item(@itemxml){
1295         $zebraxml.=$item if $item;
1296      }
1297 $zebraxml.="</holdings>";
1298 $zebraxml.="</koharecord>";
1299 $zebraxml.="</kohacollection>";
1300 return $zebraxml;
1301 }
1302
1303 sub ZEBRA_readyXML_noheader{
1304 my ($dbh,$biblionumber)=@_;
1305 my $biblioxml=XMLgetbiblio($dbh,$biblionumber);
1306 my @itemxml=XMLgetallitems($dbh,$biblionumber);
1307 my $zebraxml="<koharecord>";
1308 $zebraxml.=$biblioxml;
1309 $zebraxml.="<holdings>";
1310       foreach my $item(@itemxml){
1311         $zebraxml.=$item if $item;
1312      }
1313 $zebraxml.="</holdings>";
1314 $zebraxml.="</koharecord>";
1315 return $zebraxml;
1316 }
1317
1318 #
1319 #
1320 # various utility subs and those not complying to new rules
1321 #
1322 #
1323
1324 sub newbiblio {
1325 ## Used in acqui management -- creates the biblio from koha hash 
1326     my ($biblio) = @_;
1327     my $dbh    = C4::Context->dbh;
1328 my $record=XMLkoha2marc($dbh,$biblio,"biblios");
1329    my $biblionumber=NEWnewbiblio($dbh,$record);
1330     return ($biblionumber);
1331 }
1332 sub modbiblio {
1333 ## Used in acqui management -- modifies the biblio from koha hash rather than xml-hash
1334     my ($biblio) = @_;
1335     my $dbh    = C4::Context->dbh;
1336 my $record=XMLkoha2marc($dbh,$biblio,"biblios");
1337    my $biblionumber=NEWmodbiblio($dbh,$record,$biblio->{biblionumber});
1338     return ($biblionumber);
1339 }
1340
1341 sub newitems {
1342 ## Used in acqui management -- creates the item from hash rather than marc-record
1343     my ( $item, @barcodes ) = @_;
1344     my $dbh = C4::Context->dbh;
1345     my $errors;
1346     my $itemnumber;
1347     my $error;
1348     foreach my $barcode (@barcodes) {
1349         $item->{barcode}=$barcode;
1350 my $record=MARCkoha2marc($dbh,$item,"holdings");        
1351   my $itemnumber=     NEWnewitem($dbh,$record,$item->{biblionumber});
1352     
1353     }
1354     return $itemnumber ;
1355 }
1356
1357
1358
1359
1360 sub getitemtypes {
1361     my $dbh   = C4::Context->dbh;
1362     my $query = "select * from itemtypes order by description";
1363     my $sth   = $dbh->prepare($query);
1364
1365     # || die "Cannot prepare $query" . $dbh->errstr;      
1366     my $count = 0;
1367     my @results;
1368     $sth->execute;
1369     # || die "Cannot execute $query\n" . $sth->errstr;
1370     while ( my $data = $sth->fetchrow_hashref ) {
1371         $results[$count] = $data;
1372         $count++;
1373     }    # while
1374
1375     $sth->finish;
1376     return ( $count, @results );
1377 }    # sub getitemtypes
1378
1379
1380
1381 sub getkohafields{
1382 #returns MySQL like fieldnames to emulate searches on sql like fieldnames
1383 my $type=@_;
1384 ## Either opac or intranet to select appropriate fields
1385 ## Assumes intranet
1386 $type="intra" unless $type;
1387 if ($type eq "intranet"){ $type="intra";}
1388 my $dbh   = C4::Context->dbh;
1389   my $i=0;
1390 my @results;
1391 $type=$type."show";
1392 my $sth=$dbh->prepare("SELECT  * FROM koha_attr  where $type=1 order by liblibrarian");
1393 $sth->execute();
1394 while (my $data=$sth->fetchrow_hashref){
1395         $results[$i]=$data;
1396         $i++;
1397         }
1398 $sth->finish;
1399 return ($i,@results);
1400 }
1401
1402
1403
1404
1405
1406 sub DisplayISBN {
1407 ## Old style ISBN handling should be modified to accept 13 digits
1408
1409         my ($isbn)=@_;
1410         my $seg1;
1411         if(substr($isbn, 0, 1) <=7) {
1412                 $seg1 = substr($isbn, 0, 1);
1413         } elsif(substr($isbn, 0, 2) <= 94) {
1414                 $seg1 = substr($isbn, 0, 2);
1415         } elsif(substr($isbn, 0, 3) <= 995) {
1416                 $seg1 = substr($isbn, 0, 3);
1417         } elsif(substr($isbn, 0, 4) <= 9989) {
1418                 $seg1 = substr($isbn, 0, 4);
1419         } else {
1420                 $seg1 = substr($isbn, 0, 5);
1421         }
1422         my $x = substr($isbn, length($seg1));
1423         my $seg2;
1424         if(substr($x, 0, 2) <= 19) {
1425 #               if(sTmp2 < 10) sTmp2 = "0" sTmp2;
1426                 $seg2 = substr($x, 0, 2);
1427         } elsif(substr($x, 0, 3) <= 699) {
1428                 $seg2 = substr($x, 0, 3);
1429         } elsif(substr($x, 0, 4) <= 8399) {
1430                 $seg2 = substr($x, 0, 4);
1431         } elsif(substr($x, 0, 5) <= 89999) {
1432                 $seg2 = substr($x, 0, 5);
1433         } elsif(substr($x, 0, 6) <= 9499999) {
1434                 $seg2 = substr($x, 0, 6);
1435         } else {
1436                 $seg2 = substr($x, 0, 7);
1437         }
1438         my $seg3=substr($x,length($seg2));
1439         $seg3=substr($seg3,0,length($seg3)-1) ;
1440         my $seg4 = substr($x, -1, 1);
1441         return "$seg1-$seg2-$seg3-$seg4";
1442 }
1443 sub calculatelc{
1444 ## Function to create padded LC call number for sorting items with their LC code. Not exported
1445 my  ($classification)=@_;
1446 $classification=~s/^\s+|\s+$//g;
1447 my $i=0;
1448 my $lc2;
1449 my $lc1;
1450 for  ($i=0; $i<length($classification);$i++){
1451 my $c=(substr($classification,$i,1));
1452         if ($c ge '0' && $c le '9'){
1453         
1454         $lc2=substr($classification,$i);
1455         last;
1456         }else{
1457         $lc1.=substr($classification,$i,1);
1458         
1459         }
1460 }#while
1461
1462 my $other=length($lc1);
1463 if(!$lc1){$other=0;}
1464 my $extras;
1465 if ($other<4){
1466         for (1..(4-$other)){
1467         $extras.="0";
1468         }
1469 }
1470  $lc1.=$extras;
1471 $lc2=~ s/^ //g;
1472
1473 $lc2=~ s/ //g;
1474 $extras="";
1475 ##Find the decimal part of $lc2
1476 my $pos=index($lc2,".");
1477 if ($pos<0){$pos=length($lc2);}
1478 if ($pos>=0 && $pos<5){
1479 ##Pad lc2 with zeros to create a 5digit decimal needed in marc record to sort as numeric
1480
1481         for (1..(5-$pos)){
1482         $extras.="0";
1483         }
1484 }
1485 $lc2=$extras.$lc2;
1486 return($lc1.$lc2);
1487 }
1488
1489 sub itemcalculator{
1490 ## Sublimentary function to obtain sorted LC for items. Not exported
1491 my ($dbh,$biblionumber,$callnumber)=@_;
1492 my $xmlhash=XMLgetbibliohash($dbh,$biblionumber);
1493 my $lc=XML_readline_onerecord($xmlhash,"classification","biblios");
1494 my $cutter=XML_readline_onerecord($xmlhash,"subclass","biblios");
1495 my $all=$lc." ".$cutter;
1496 my $total=length($all);
1497 my $cutterextra=substr($callnumber,$total);
1498 return $cutterextra;
1499
1500 }
1501
1502
1503 #### This function allows decoding of only title and author out of a MARC record
1504   sub func_title_author {
1505         my ($tagno,$tagdata) = @_;
1506   my ($titlef,$subf)=&MARCfind_marc_from_kohafield("title","biblios");
1507   my ($authf,$subf)=&MARCfind_marc_from_kohafield("author","biblios");
1508         return ($tagno == $titlef || $tagno == $authf);
1509     }
1510
1511
1512
1513 END { }    # module clean-up code here (global destructor)
1514
1515 =back
1516
1517 =head1 AUTHOR
1518
1519 Koha Developement team <info@koha.org>
1520
1521
1522