Savannah seems out of sync. reloading.Mainly code cleaning and removing of Date:...
[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
25 use vars qw($VERSION @ISA @EXPORT);
26
27 # set the version for version checking
28 $VERSION = 2.01;
29
30 @ISA = qw(Exporter);
31
32 # &itemcount removed, now  resides in Search.pm
33 #
34 @EXPORT = qw(
35
36 &getitemtypes
37 &getkohafields
38 &getshelves
39
40 &NEWnewbiblio 
41 &NEWnewitem
42 &NEWmodbiblio 
43 &NEWmoditem
44 &NEWdelbiblio 
45 &NEWdelitem
46 &NEWmodbiblioframework
47
48
49 &MARCfind_marc_from_kohafield
50 &MARCfind_frameworkcode
51 &MARCfind_itemtype
52 &MARCgettagslib
53 &MARCitemsgettagslib
54
55 &MARCfind_attr_from_kohafield
56 &MARChtml2xml 
57
58
59 &XMLgetbiblio 
60 &XMLgetbibliohash
61 &XMLgetitem 
62 &XMLgetitemhash
63 &XMLgetallitems 
64 &XML_xml2hash 
65 &XML_xml2hash_onerecord
66 &XML_hash2xml 
67 &XMLmarc2koha
68 &XMLmarc2koha_onerecord
69 &XML_readline
70 &XML_readline_onerecord
71 &XML_readline_asarray
72 &XML_writeline
73 &XML_writeline_id
74 &XMLmoditemonefield
75 &XMLkoha2marc
76 &XML_separate
77 &XML_record_header
78 &XMLmodLCindex
79 &ZEBRAdelbiblio
80 &ZEBRAgetrecord   
81 &ZEBRAop 
82 &ZEBRAopserver 
83 &ZEBRA_readyXML 
84 &ZEBRA_readyXML_noheader
85 &ZEBRAopcommit
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;
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     }elsif ($tag>0){
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 return undef unless $xml;
352   my $hashed = XMLin( $xml ,KeyAttr =>['leader','controlfield','datafield'],ForceArray => ['leader','controlfield','datafield','subfield'],KeepRoot=>0);
353 return $hashed;
354 }
355 sub XML_hash2xml{
356 ## turn a hash back to xml
357 my ($hashed,$root)=@_;
358 $root="record" unless $root;
359 my $xml= XMLout($hashed,KeyAttr=>['leader','controlfıeld','datafield'],NoSort => 1,AttrIndent => 0,KeepRoot=>0,SuppressEmpty => 1,RootName=>$root );
360 return $xml;
361 }
362
363
364
365 sub XMLgetbiblio {
366     # Returns MARC::XML of the biblionumber passed in parameter.
367     my ( $dbh, $biblionumber ) = @_;
368     my $sth =      $dbh->prepare("select marcxml from biblio where biblionumber=? "  );
369     $sth->execute( $biblionumber);
370    my ($marcxml)=$sth->fetchrow;
371         $marcxml=Encode::decode('utf8',$marcxml);
372  return ($marcxml);
373 }
374
375 sub XMLgetbibliohash{
376 ## Utility to return s hashed MARCXML
377 my ($dbh,$biblionumber)=@_;
378 my $xml=XMLgetbiblio($dbh,$biblionumber);
379 my $xmlhash=XML_xml2hash_onerecord($xml);
380 return $xmlhash;
381 }
382
383 sub XMLgetitem {
384    # Returns MARC::XML   of the item passed in parameter uses either itemnumber or barcode
385     my ( $dbh, $itemnumber,$barcode ) = @_;
386 my $sth;
387 if ($itemnumber){
388    $sth = $dbh->prepare("select marcxml from items  where itemnumber=?"  ); 
389     $sth->execute($itemnumber);
390 }else{
391  $sth = $dbh->prepare("select marcxml from items where barcode=?"  ); 
392     $sth->execute($barcode);
393 }
394  my ($marcxml)=$sth->fetchrow;
395 $marcxml=Encode::decode('utf8',$marcxml);
396     return ($marcxml);
397 }
398 sub XMLgetitemhash{
399 ## Utility to return s hashed MARCXML
400  my ( $dbh, $itemnumber,$barcode ) = @_;
401 my $xml=XMLgetitem( $dbh, $itemnumber,$barcode);
402 my $xmlhash=XML_xml2hash_onerecord($xml);
403 return $xmlhash;
404 }
405
406
407 sub XMLgetallitems {
408 # warn "XMLgetallitems";
409     # Returns an array of MARC:XML   of the items passed in parameter as biblionumber
410     my ( $dbh, $biblionumber ) = @_;
411 my @results;
412 my   $sth = $dbh->prepare("select marcxml from items where biblionumber =?"  ); 
413     $sth->execute($biblionumber);
414
415  while(my ($marcxml)=$sth->fetchrow_array){
416 $marcxml=Encode::decode('utf8',$marcxml);
417     push @results,$marcxml;
418 }
419 return @results;
420 }
421
422 sub XMLmarc2koha {
423 # warn "XMLmarc2koha";
424 ##Returns two hashes from KOHA_XML record hashed
425 ## A biblio hash and and array of item hashes
426         my ($dbh,$xml,$related_record,@fields) = @_;
427         my ($result,@items);
428         
429 ## if @fields is given do not bother about the rest of fields just parse those
430
431 if ($related_record eq "biblios" || $related_record eq "" || !$related_record){
432         if (@fields){
433                 foreach my $field(@fields){
434                 my $val=&XML_readline($xml,$field,'biblios');
435                         $result->{$field}=$val if $val;
436                         
437                 }
438         }else{
439         my $sth2=$dbh->prepare("SELECT  kohafield from koha_attr where  recordtype like 'biblios' and tagfield is not null" );
440         $sth2->execute();
441         my $field;
442                 while ($field=$sth2->fetchrow) {
443                 $result->{$field}=&XML_readline($xml,$field,'biblios');
444                 }
445         }
446
447 ## we only need the following for biblio data
448         
449 # modify copyrightdate to keep only the 1st year found
450         my $temp = $result->{'copyrightdate'};
451         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
452         if ($1>0) {
453                 $result->{'copyrightdate'} = $1;
454         } else { # if no cYYYY, get the 1st date.
455                 $temp =~ m/(\d\d\d\d)/;
456                 $result->{'copyrightdate'} = $1;
457         }
458 # modify publicationyear to keep only the 1st year found
459         $temp = $result->{'publicationyear'};
460         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
461         if ($1>0) {
462                 $result->{'publicationyear'} = $1;
463         } else { # if no cYYYY, get the 1st date.
464                 $temp =~ m/(\d\d\d\d)/;
465                 $result->{'publicationyear'} = $1;
466         }
467 }
468 if ($related_record eq "holdings" || $related_record eq ""  || !$related_record){
469 my $holdings=$xml->{holdings}->[0]->{record};
470
471
472         if (@fields){
473             foreach my $holding (@$holdings){   
474 my $itemresult;
475                 foreach my $field(@fields){
476                 my $val=&XML_readline($holding,$field,'holdings');
477                 $itemresult->{$field}=$val if $val;     
478                 }
479             push @items, $itemresult;
480            }
481         }else{
482         my $sth2=$dbh->prepare("SELECT  kohafield from koha_attr where recordtype like 'holdings' and tagfield is not null" );
483            foreach my $holding (@$holdings){    
484            $sth2->execute();
485             my $field;
486 my $itemresult;
487                 while ($field=$sth2->fetchrow) {
488                 $itemresult->{$field}=&XML_readline($xml,$field,'holdings');
489                 }
490          push @items, $itemresult;
491            }
492         }
493
494 }
495
496         return ($result,@items);
497 }
498 sub XMLmarc2koha_onerecord {
499 # warn "XMLmarc2koha_onerecord";
500 ##Returns a koha hash from MARCXML hash
501
502         my ($dbh,$xml,$related_record,@fields) = @_;
503         my ($result);
504         
505 ## if @fields is given do not bother about the rest of fields just parse those
506
507         if (@fields){
508                 foreach my $field(@fields){
509                 my $val=&XML_readline_onerecord($xml,$field,$related_record);
510                         $result->{$field}=$val if $val;                 
511                 }
512         }else{
513         my $sth2=$dbh->prepare("SELECT  kohafield from koha_attr where  recordtype like ? and tagfield is not null" );
514         $sth2->execute($related_record);
515         my $field;
516                 while ($field=$sth2->fetchrow) {
517                 $result->{$field}=&XML_readline_onerecord($xml,$field,$related_record);
518                 }
519         }
520         return ($result);
521 }
522
523 sub XMLmodLCindex{
524 # warn "XMLmodLCindex";
525 my ($dbh,$xmlhash)=@_;
526 my ($lc)=XML_readline_onerecord($xmlhash,"classification","biblios");
527 my ($cutter)=XML_readline_onerecord($xmlhash,"subclass","biblios");
528
529         if ($lc){
530         $lc.=$cutter;
531         my ($lcsort)=calculatelc($lc);
532         $xmlhash=XML_writeline($xmlhash,"lcsort",$lcsort,"biblios");
533         }
534 return $xmlhash;
535 }
536
537 sub XMLmoditemonefield{
538 # This routine takes itemnumber and biblionumber and updates XMLmarc;
539 ### the ZEBR DB update can wait depending on $donotupdate flag
540 my ($dbh,$biblionumber,$itemnumber,$itemfield,$newvalue,$donotupdate)=@_;
541 my ($record) = XMLgetitem($dbh,$itemnumber);
542         my $recordhash=XML_xml2hash_onerecord($record);
543         XML_writeline( $recordhash, $itemfield, $newvalue,"holdings" ); 
544  if($donotupdate){
545         ## Prevent various update calls to zebra wait until all changes finish
546                 $record=XML_hash2xml($recordhash);
547                 my $sth=$dbh->prepare("update items set marcxml=? where itemnumber=?");
548                 $sth->execute($record,$itemnumber);
549                 $sth->finish;
550         }else{
551                 NEWmoditem($dbh,$recordhash,$biblionumber,$itemnumber);
552   }
553
554 }
555
556 sub XMLkoha2marc {
557 # warn "MARCkoha2marc";
558 ## This routine  is still used for acqui management
559 ##Returns a  XML recordhash from a kohahash
560         my ($dbh,$result,$recordtype) = @_;
561 ###create a basic MARCXML
562 # find today's date
563 my ($sec,$min,$hour,$mday,$mon,$year) = localtime();
564         $year += 1900;
565         $mon += 1;
566         my $timestamp = sprintf("%4d%02d%02d%02d%02d%02d.0",
567                 $year,$mon,$mday,$hour,$min,$sec);
568 $year=substr($year,2,2);
569         my $accdate=sprintf("%2d%02d%02d",$year,$mon,$mday);
570 my ($titletag,$titlesubf)=MARCfind_marc_from_kohafield("title","biblios");
571 ##create a dummy record
572 my $xml="<record><leader>     naa a22     7ar4500</leader><controlfield tag='xxx'></controlfield><datafield ind1='' ind2='' tag='$titletag'></datafield></record>";
573 ## Now build XML
574         my $record = XML_xml2hash($xml);
575         my $sth2=$dbh->prepare("SELECT  kohafield from koha_attr where tagfield is not null and recordtype=?");
576         $sth2->execute($recordtype);
577         my $field;
578         while (($field)=$sth2->fetchrow) {
579                 $record=XML_writeline($record,$field,$result->{$field},$recordtype) if $result->{$field};
580         }
581 return $record;
582 }
583
584 #
585 #
586 # MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC MARC
587 #
588 ## Script to deal with MARCXML related tables
589
590
591 ##Sub to match kohafield to Z3950 -attributes
592
593 sub MARCfind_attr_from_kohafield {
594 # warn "MARCfind_attr_from_kohafield";
595 ## returns attribute
596     my (  $kohafield ) = @_;
597     return 0, 0 unless $kohafield;
598
599         my $relations = C4::Context->attrfromkohafield;
600         return ($relations->{$kohafield});
601 }
602
603
604 sub MARCgettagslib {
605 # warn "MARCgettagslib";
606     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
607     $frameworkcode = "" unless $frameworkcode;
608     my $sth;
609     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
610
611     # check that framework exists
612     $sth =
613       $dbh->prepare(
614         "select count(*) from biblios_tag_structure where frameworkcode=?");
615     $sth->execute($frameworkcode);
616     my ($total) = $sth->fetchrow;
617     $frameworkcode = "" unless ( $total > 0 );
618     $sth =
619       $dbh->prepare(
620 "select tagfield,liblibrarian,libopac,mandatory,repeatable from biblios_tag_structure where frameworkcode=? order by tagfield"
621     );
622     $sth->execute($frameworkcode);
623     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
624
625     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
626         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
627         $res->{$tab}->{tab}        = "";            # XXX
628         $res->{$tag}->{mandatory}  = $mandatory;
629         $res->{$tag}->{repeatable} = $repeatable;
630     }
631
632     $sth =
633       $dbh->prepare(
634 "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"
635     );
636     $sth->execute($frameworkcode);
637
638     my $subfield;
639     my $authorised_value;
640     my $authtypecode;
641     my $value_builder;
642    
643     my $seealso;
644     my $hidden;
645     my $isurl;
646         my $link;
647
648     while (
649         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
650         $mandatory,     $repeatable, $authorised_value, $authtypecode,
651         $value_builder,   $seealso,          $hidden,
652         $isurl,                 $link )
653         = $sth->fetchrow
654       )
655     {
656         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
657         $res->{$tag}->{$subfield}->{tab}              = $tab;
658         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
659         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
660         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
661         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
662         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
663         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
664         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
665         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
666         $res->{$tag}->{$subfield}->{link}            = $link;
667     }
668     return $res;
669 }
670 sub MARCitemsgettagslib {
671 # warn "MARCitemsgettagslib";
672     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
673     $frameworkcode = "" unless $frameworkcode;
674     my $sth;
675     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
676
677     # check that framework exists
678     $sth =
679       $dbh->prepare(
680         "select count(*) from holdings_tag_structure where frameworkcode=?");
681     $sth->execute($frameworkcode);
682     my ($total) = $sth->fetchrow;
683     $frameworkcode = "" unless ( $total > 0 );
684     $sth =
685       $dbh->prepare(
686 "select tagfield,liblibrarian,libopac,mandatory,repeatable from holdings_tag_structure where frameworkcode=? order by tagfield"
687     );
688     $sth->execute($frameworkcode);
689     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
690
691     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
692         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
693         $res->{$tab}->{tab}        = "";            # XXX
694         $res->{$tag}->{mandatory}  = $mandatory;
695         $res->{$tag}->{repeatable} = $repeatable;
696     }
697
698     $sth =
699       $dbh->prepare(
700 "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"
701     );
702     $sth->execute($frameworkcode);
703
704     my $subfield;
705     my $authorised_value;
706     my $authtypecode;
707     my $value_builder;
708    
709     my $seealso;
710     my $hidden;
711     my $isurl;
712         my $link;
713
714     while (
715         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
716         $mandatory,     $repeatable, $authorised_value, $authtypecode,
717         $value_builder, $seealso,          $hidden,
718         $isurl,                 $link )
719         = $sth->fetchrow
720       )
721     {
722         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
723         $res->{$tag}->{$subfield}->{tab}              = $tab;
724         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
725         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
726         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
727         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
728         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
729         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
730         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
731         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
732         $res->{$tag}->{$subfield}->{link}            = $link;
733     }
734     return $res;
735 }
736 sub MARCfind_marc_from_kohafield {
737 # warn "MARCfind_marc_from_kohafield";
738     my (  $kohafield,$recordtype) = @_;
739     return 0, 0 unless $kohafield;
740 $recordtype="biblios" unless $recordtype;
741         my $relations = C4::Context->marcfromkohafield;
742         return ($relations->{$recordtype}->{$kohafield}->[0],$relations->{$recordtype}->{$kohafield}->[1]);
743 }
744
745
746
747
748 sub MARCfind_frameworkcode {
749 # warn "MARCfind_frameworkcode";
750     my ( $dbh, $biblionumber ) = @_;
751     my $sth =
752       $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
753     $sth->execute($biblionumber);
754     my ($frameworkcode) = $sth->fetchrow;
755     return $frameworkcode;
756 }
757 sub MARCfind_itemtype {
758 # warn "MARCfind_itemtype";
759     my ( $dbh, $biblionumber ) = @_;
760     my $sth =
761       $dbh->prepare("select itemtype from biblio where biblionumber=?");
762     $sth->execute($biblionumber);
763     my ($itemtype) = $sth->fetchrow;
764     return $itemtype;
765 }
766
767
768
769 sub MARChtml2xml {
770 # warn "MARChtml2xml ";
771         my ($tags,$subfields,$values,$indicator,$ind_tag,$tagindex) = @_;        
772         my $xml= "<record>";
773
774     my $prevvalue;
775     my $prevtag=-1;
776     my $first=1;
777         my $j = -1;
778     for (my $i=0;$i<=@$tags;$i++){
779                 @$values[$i] =~ s/&/&amp;/g;
780                 @$values[$i] =~ s/</&lt;/g;
781                 @$values[$i] =~ s/>/&gt;/g;
782                 @$values[$i] =~ s/"/&quot;/g;
783                 @$values[$i] =~ s/'/&apos;/g;
784
785                 if ((@$tags[$i].@$tagindex[$i] ne $prevtag)){
786                         my $tag=@$tags[$i];
787                         $j++ unless ($tag eq "");
788                         ## warn "IND:".substr(@$indicator[$j],0,1).substr(@$indicator[$j],1,1)." ".@$tags[$i];
789                         if (!$first){
790                         $xml.="</datafield>\n";
791                                 if (($tag> 10) && (@$values[$i] ne "")){
792                                                 my $ind1 = substr(@$indicator[$j],0,1);
793                         my $ind2 = substr(@$indicator[$j],1,1);
794                         $xml.="<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
795                         $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
796                         $first=0;
797                                 } else {
798                         $first=1;
799                                 }
800                                 } else {
801                         if (@$values[$i] ne "") {
802                                 # leader
803                                 if ($tag eq "000") {
804                                 ##Force the leader to UTF8
805                                 substr(@$values[$i],9,1)="a";
806                                                 $xml.="<leader>@$values[$i]</leader>\n";
807                                                 $first=1;
808                                         # rest of the fixed fields
809                                 } elsif ($tag < 10) {
810                                                 $xml.="<controlfield tag=\"$tag\">@$values[$i]</controlfield>\n";
811                                                 $first=1;
812                                 } else {
813                                                 my $ind1 = substr(@$indicator[$j],0,1);
814                                                 my $ind2 = substr(@$indicator[$j],1,1);
815                                                 $xml.="<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
816                                                 $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
817                                                 $first=0;                       
818                                 }
819                         }
820                         }
821                 } else { # @$tags[$i] eq $prevtag
822                                  unless (@$values[$i] eq "") {
823                         my $tag=@$tags[$i];
824                                         if ($first){
825                                                 my $ind1 = substr(@$indicator[$j],0,1);                        
826                                                 my $ind2 = substr(@$indicator[$j],1,1);
827                                                 $xml.="<datafield tag=\"$tag\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
828                                                 $first=0;
829                                         }
830                         $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
831                                 }
832                 }
833                 $prevtag = @$tags[$i].@$tagindex[$i];
834         }
835         $xml.="</record>";
836         # warn $xml;
837         $xml=Encode::decode('utf8',$xml);
838         return $xml;
839 }
840 sub XML_record_header {
841 ####  this one is for <record>
842     my $format = shift;
843     my $enc = shift || 'UTF-8';
844 ##
845     return( <<MARC_XML_HEADER );
846 <?xml version="1.0" encoding="$enc"?>
847 <record  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
848   xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
849   xmlns="http://www.loc.gov/MARC21/slim">
850 MARC_XML_HEADER
851 }
852
853
854 sub collection_header {
855 ####  this one is for koha collection 
856     my $format = shift;
857     my $enc = shift || 'UTF-8';
858     return( <<KOHA_XML_HEADER );
859 <?xml version="1.0" encoding="$enc"?>
860 <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">
861 KOHA_XML_HEADER
862 }
863
864
865
866
867
868
869
870
871 ##########################NEW NEW NEW#############################
872 sub NEWnewbiblio {
873     my ( $dbh, $xml, $frameworkcode) = @_;
874 $frameworkcode="" unless $frameworkcode;
875 my $biblionumber=XML_readline_onerecord($xml,"biblionumber","biblios");
876 ## In case reimporting records with biblionumbers keep them
877 if ($biblionumber){
878 $biblionumber=NEWmodbiblio( $dbh, $biblionumber,$xml,$frameworkcode );
879 }else{
880     $biblionumber = NEWaddbiblio( $dbh, $xml,$frameworkcode );
881 }
882
883    return ( $biblionumber );
884 }
885
886
887
888
889
890 sub NEWmodbiblioframework {
891         my ($dbh,$biblionumber,$frameworkcode) =@_;
892         my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=$biblionumber");
893         $sth->execute($frameworkcode);
894         return 1;
895 }
896
897
898 sub NEWdelbiblio {
899     my ( $dbh, $biblionumber ) = @_;
900 ZEBRAop($dbh,$biblionumber,"recordDelete","biblioserver");
901 }
902
903
904 sub NEWnewitem {
905     my ( $dbh, $xmlhash, $biblionumber ) = @_;
906         my $itemtype= MARCfind_itemtype($dbh,$biblionumber);
907
908 ## In case we are re-importing marc records from bulk import do not change itemnumbers
909 my $itemnumber=XML_readline_onerecord($xmlhash,"itemnumber","holdings");
910 if ($itemnumber){
911 NEWmoditem ( $dbh, $xmlhash, $biblionumber, $itemnumber);
912 }else{
913    
914 ##Add biblionumber to $record
915 $xmlhash=XML_writeline($xmlhash,"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 if (!$biblionumber){
1206 warn "Zebra received no biblionumber";
1207 }elsif (C4::Context->preference('onlineZEBRA')){
1208 my $marcxml;
1209         if ($server eq "biblioserver"){
1210         ($marcxml) =ZEBRA_readyXML($dbh,$biblionumber);
1211         }elsif($server eq "authorityserver"){
1212         $marcxml =C4::AuthoritiesMarc::XMLgetauthority($dbh,$biblionumber);
1213         } 
1214 ZEBRAopserver($marcxml,$op,$server,$biblionumber);
1215 ZEBRAopcommit($server);
1216 }else{
1217 my $sth=$dbh->prepare("insert into zebraqueue  (biblio_auth_number ,server,operation) values(?,?,?)");
1218 $sth->execute($biblionumber,$server,$op);
1219 $sth->finish;
1220
1221 }
1222 }
1223
1224 sub ZEBRAopserver{
1225
1226 ###Accepts a $server variable thus we can use it to update  biblios, authorities or other zebra dbs
1227 my ($record,$op,$server,$biblionumber)=@_;
1228
1229 my @port;
1230
1231 my $tried=0;
1232 my $recon=0;
1233 my $reconnect=0;
1234 $record=Encode::encode("UTF-8",$record);
1235 my $shadow=$server."shadow";
1236 reconnect:
1237
1238  my $Zconnbiblio=C4::Context->Zconnauth($server);
1239 if ($record){
1240 my $Zpackage = $Zconnbiblio->package();
1241 $Zpackage->option(action => $op);
1242         $Zpackage->option(record => $record);
1243         $Zpackage->option(recordIdOpaque => $biblionumber);
1244 retry:
1245                 $Zpackage->send("update");
1246
1247  my($error, $errmsg, $addinfo, $diagset) = $Zconnbiblio->error_x();
1248         if ($error==10007 && $tried<3) {## timeout --another 30 looonng seconds for this update
1249                 sleep 1;        ##  wait a sec!
1250                 $tried=$tried+1;
1251                 goto "retry";
1252         }elsif ($error==2 && $tried<2) {## timeout --temporary zebra error !whatever that means
1253                 sleep 2;        ##  wait two seconds!
1254                 $tried=$tried+1;
1255                 goto "retry";
1256         }elsif($error==10004 && $recon==0){##Lost connection -reconnect
1257                 sleep 1;        ##  wait a sec!
1258                 $recon=1;
1259                 $Zpackage->destroy();
1260                 $Zconnbiblio->destroy();
1261                 goto "reconnect";
1262         }elsif ($error){
1263         #       warn "Error-$server   $op  /errcode:, $error, /MSG:,$errmsg,$addinfo \n";       
1264                 $Zpackage->destroy();
1265                 $Zconnbiblio->destroy();
1266                 return 0;
1267         }
1268         
1269 $Zpackage->destroy();
1270 $Zconnbiblio->destroy();
1271 return 1;
1272 }
1273 return 0;
1274 }
1275
1276
1277 sub ZEBRAopcommit {
1278 my $server=shift;
1279 return unless C4::Context->config($server."shadow");
1280 my $Zconnbiblio=C4::Context->Zconnauth($server);
1281
1282 my $Zpackage = $Zconnbiblio->package();
1283  $Zpackage->send('commit');
1284                 
1285                  my($error, $errmsg, $addinfo, $diagset) = $Zconnbiblio->error_x();
1286                  if ($error) { ## This is serious ZEBRA server is not updating  
1287              $Zpackage->destroy();
1288              $Zconnbiblio->destroy();
1289              return 0;
1290             }
1291 $Zpackage->destroy();
1292 $Zconnbiblio->destroy();
1293 return 1;
1294 }
1295 sub ZEBRA_readyXML{
1296 my ($dbh,$biblionumber)=@_;
1297 my $biblioxml=XMLgetbiblio($dbh,$biblionumber);
1298 my @itemxml=XMLgetallitems($dbh,$biblionumber);
1299 my $zebraxml=collection_header();
1300 $zebraxml.="<koharecord>";
1301 $zebraxml.=$biblioxml;
1302 $zebraxml.="<holdings>";
1303       foreach my $item(@itemxml){
1304         $zebraxml.=$item if $item;
1305      }
1306 $zebraxml.="</holdings>";
1307 $zebraxml.="</koharecord>";
1308 $zebraxml.="</kohacollection>";
1309 return $zebraxml;
1310 }
1311
1312 sub ZEBRA_readyXML_noheader{
1313 my ($dbh,$biblionumber)=@_;
1314 my $biblioxml=XMLgetbiblio($dbh,$biblionumber);
1315 my @itemxml=XMLgetallitems($dbh,$biblionumber);
1316 my $zebraxml="<koharecord>";
1317 $zebraxml.=$biblioxml;
1318 $zebraxml.="<holdings>";
1319       foreach my $item(@itemxml){
1320         $zebraxml.=$item if $item;
1321      }
1322 $zebraxml.="</holdings>";
1323 $zebraxml.="</koharecord>";
1324 return $zebraxml;
1325 }
1326
1327 #
1328 #
1329 # various utility subs and those not complying to new rules
1330 #
1331 #
1332
1333 sub newbiblio {
1334 ## Used in acqui management -- creates the biblio from koha hash 
1335     my ($biblio) = @_;
1336     my $dbh    = C4::Context->dbh;
1337 my $record=XMLkoha2marc($dbh,$biblio,"biblios");
1338    my $biblionumber=NEWnewbiblio($dbh,$record);
1339     return ($biblionumber);
1340 }
1341 sub modbiblio {
1342 ## Used in acqui management -- modifies the biblio from koha hash rather than xml-hash
1343     my ($biblio) = @_;
1344     my $dbh    = C4::Context->dbh;
1345 my $record=XMLkoha2marc($dbh,$biblio,"biblios");
1346    my $biblionumber=NEWmodbiblio($dbh,$record,$biblio->{biblionumber});
1347     return ($biblionumber);
1348 }
1349
1350 sub newitems {
1351 ## Used in acqui management -- creates the item from hash rather than marc-record
1352     my ( $item, @barcodes ) = @_;
1353     my $dbh = C4::Context->dbh;
1354     my $errors;
1355     my $itemnumber;
1356     my $error;
1357     foreach my $barcode (@barcodes) {
1358         $item->{barcode}=$barcode;
1359 my $record=MARCkoha2marc($dbh,$item,"holdings");        
1360   my $itemnumber=     NEWnewitem($dbh,$record,$item->{biblionumber});
1361     
1362     }
1363     return $itemnumber ;
1364 }
1365
1366
1367
1368
1369 sub getitemtypes {
1370     my $dbh   = C4::Context->dbh;
1371     my $query = "select * from itemtypes order by description";
1372     my $sth   = $dbh->prepare($query);
1373
1374     # || die "Cannot prepare $query" . $dbh->errstr;      
1375     my $count = 0;
1376     my @results;
1377     $sth->execute;
1378     # || die "Cannot execute $query\n" . $sth->errstr;
1379     while ( my $data = $sth->fetchrow_hashref ) {
1380         $results[$count] = $data;
1381         $count++;
1382     }    # while
1383
1384     $sth->finish;
1385     return ( $count, @results );
1386 }    # sub getitemtypes
1387
1388
1389
1390 sub getkohafields{
1391 #returns MySQL like fieldnames to emulate searches on sql like fieldnames
1392 my $type=shift;
1393 ## Either opac or intranet to select appropriate fields
1394 ## Assumes intranet
1395 $type="intra" unless $type;
1396 if ($type eq "intranet"){ $type="intra";}
1397 my $dbh   = C4::Context->dbh;
1398   my $i=0;
1399 my @results;
1400 $type=$type."show";
1401 my $sth=$dbh->prepare("SELECT  * FROM koha_attr  where $type=1 order by label");
1402 $sth->execute();
1403 while (my $data=$sth->fetchrow_hashref){
1404         $results[$i]=$data;
1405         $i++;
1406         }
1407 $sth->finish;
1408 return ($i,@results);
1409 }
1410
1411
1412
1413
1414
1415 sub DisplayISBN {
1416 ## Old style ISBN handling should be modified to accept 13 digits
1417
1418         my ($isbn)=@_;
1419         my $seg1;
1420         if(substr($isbn, 0, 1) <=7) {
1421                 $seg1 = substr($isbn, 0, 1);
1422         } elsif(substr($isbn, 0, 2) <= 94) {
1423                 $seg1 = substr($isbn, 0, 2);
1424         } elsif(substr($isbn, 0, 3) <= 995) {
1425                 $seg1 = substr($isbn, 0, 3);
1426         } elsif(substr($isbn, 0, 4) <= 9989) {
1427                 $seg1 = substr($isbn, 0, 4);
1428         } else {
1429                 $seg1 = substr($isbn, 0, 5);
1430         }
1431         my $x = substr($isbn, length($seg1));
1432         my $seg2;
1433         if(substr($x, 0, 2) <= 19) {
1434 #               if(sTmp2 < 10) sTmp2 = "0" sTmp2;
1435                 $seg2 = substr($x, 0, 2);
1436         } elsif(substr($x, 0, 3) <= 699) {
1437                 $seg2 = substr($x, 0, 3);
1438         } elsif(substr($x, 0, 4) <= 8399) {
1439                 $seg2 = substr($x, 0, 4);
1440         } elsif(substr($x, 0, 5) <= 89999) {
1441                 $seg2 = substr($x, 0, 5);
1442         } elsif(substr($x, 0, 6) <= 9499999) {
1443                 $seg2 = substr($x, 0, 6);
1444         } else {
1445                 $seg2 = substr($x, 0, 7);
1446         }
1447         my $seg3=substr($x,length($seg2));
1448         $seg3=substr($seg3,0,length($seg3)-1) ;
1449         my $seg4 = substr($x, -1, 1);
1450         return "$seg1-$seg2-$seg3-$seg4";
1451 }
1452 sub calculatelc{
1453 ## Function to create padded LC call number for sorting items with their LC code. Not exported
1454 my  ($classification)=@_;
1455 $classification=~s/^\s+|\s+$//g;
1456 my $i=0;
1457 my $lc2;
1458 my $lc1;
1459 for  ($i=0; $i<length($classification);$i++){
1460 my $c=(substr($classification,$i,1));
1461         if ($c ge '0' && $c le '9'){
1462         
1463         $lc2=substr($classification,$i);
1464         last;
1465         }else{
1466         $lc1.=substr($classification,$i,1);
1467         
1468         }
1469 }#while
1470
1471 my $other=length($lc1);
1472 if(!$lc1){$other=0;}
1473 my $extras;
1474 if ($other<4){
1475         for (1..(4-$other)){
1476         $extras.="0";
1477         }
1478 }
1479  $lc1.=$extras;
1480 $lc2=~ s/^ //g;
1481
1482 $lc2=~ s/ //g;
1483 $extras="";
1484 ##Find the decimal part of $lc2
1485 my $pos=index($lc2,".");
1486 if ($pos<0){$pos=length($lc2);}
1487 if ($pos>=0 && $pos<5){
1488 ##Pad lc2 with zeros to create a 5digit decimal needed in marc record to sort as numeric
1489
1490         for (1..(5-$pos)){
1491         $extras.="0";
1492         }
1493 }
1494 $lc2=$extras.$lc2;
1495 return($lc1.$lc2);
1496 }
1497
1498 sub itemcalculator{
1499 ## Sublimentary function to obtain sorted LC for items. Not exported
1500 my ($dbh,$biblionumber,$callnumber)=@_;
1501 my $xmlhash=XMLgetbibliohash($dbh,$biblionumber);
1502 my $lc=XML_readline_onerecord($xmlhash,"classification","biblios");
1503 my $cutter=XML_readline_onerecord($xmlhash,"subclass","biblios");
1504 my $all=$lc." ".$cutter;
1505 my $total=length($all);
1506 my $cutterextra=substr($callnumber,$total);
1507 return $cutterextra;
1508
1509 }
1510
1511
1512 #### This function allows decoding of only title and author out of a MARC record
1513   sub func_title_author {
1514         my ($tagno,$tagdata) = @_;
1515   my ($titlef,$subf)=&MARCfind_marc_from_kohafield("title","biblios");
1516   my ($authf,$subf)=&MARCfind_marc_from_kohafield("author","biblios");
1517         return ($tagno == $titlef || $tagno == $authf);
1518     }
1519
1520
1521
1522 END { }    # module clean-up code here (global destructor)
1523
1524 =back
1525
1526 =head1 AUTHOR
1527
1528 Koha Developement team <info@koha.org>
1529
1530
1531