removing useless sub declarations
[koha-ffzg.git] / C4 / Biblio.pm
1 package C4::Biblio;
2
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
20 use strict;
21 require Exporter;
22 use C4::Context;
23 use C4::Database;
24 use MARC::Record;
25 use MARC::File::USMARC;
26 use MARC::File::XML;
27
28 use vars qw($VERSION @ISA @EXPORT);
29
30 # set the version for version checking
31 $VERSION = 0.01;
32
33 @ISA = qw(Exporter);
34
35 #
36 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
37 # as the old-style API and the NEW one are the only public functions.
38 #
39 @EXPORT = qw(
40   &itemcount &newbiblio &newbiblioitem
41   &newsubject &newsubtitle
42   &modbiblio &checkitems
43   &newitems &modbibitem
44   &modsubtitle &modsubject &modaddauthor &moditem
45   &delitem &deletebiblioitem &delbiblio
46   &getbiblio
47   &getbiblioitembybiblionumber
48   &getbiblioitem &getitemsbybiblioitem
49
50   &MARCfind_marc_from_kohafield
51   &MARCfind_frameworkcode
52   &find_biblioitemnumber
53   &MARCgettagslib
54
55   &NEWnewbiblio &NEWnewitem
56   &NEWmodbiblio &NEWmoditem
57   &NEWdelbiblio &NEWdelitem
58   &NEWmodbiblioframework
59
60   &MARCkoha2marcBiblio &MARCmarc2koha
61   &MARCkoha2marcItem &MARChtml2marc
62   &MARCgetbiblio &MARCgetitem
63   &char_decode
64   
65   &FindDuplicate
66   &DisplayISBN
67 );
68
69 =head1 NAME
70
71 C4::Biblio - acquisition, catalog  management functions
72
73 =head1 SYNOPSIS
74
75 ( lot of changes for Koha 3.0)
76
77 Koha 1.2 and previous version used a specific API to manage biblios. This API uses old-DB style parameters.
78 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, bibliosubject and bibliosubtitle where applicable)
79
80 In Koha 2.0, we introduced a MARC-DB.
81
82 In Koha 3.0 we removed this MARC-DB for search as we wanted to use Zebra as search system.
83
84 So in Koha 3.0, saving a record means :
85  - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items informations.
86  - storing the "decoded information" in biblio/biblioitems/items as previously.
87  - using zebra to manage search & indexing on the MARC datas.
88  
89  In Koha, there is a systempreference saying "MARC=ON" or "MARC=OFF"
90  
91  * MARC=ON : when MARC=ON, koha uses a MARC::Record object (in sub parameters). Saving informations in the DB means : 
92  - transform the MARC record into a hash
93  - add the raw marc record into the hash
94  - store them & update zebra
95  
96  * MARC=OFF : when MARC=OFF, koha uses a hash object (in sub parameters). Saving informations in the DB means :
97  - transform the hash into a MARC record
98  - add the raw marc record into the hash
99  - store them and update zebra
100  
101  
102 That's why we need 3 types of subs :
103
104 =head2 REALxxx subs
105
106 all I<subs beginning by REAL> does effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in zebra. REAL subs should be only for internal use (called by NEW or "something else" subs
107
108 =head2 NEWxxx related subs
109
110 =over 4
111
112 all I<subs beginning by NEW> use MARC::Record as parameters. it's the API that MUST be used in MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
113
114 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. they sometimes requires another parameter.
115
116 =back
117
118 =head2 something_elsexxx related subs
119
120 =over 4
121
122 all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and calls REAL subs.
123
124 all subs requires/use $dbh as 1st parameter and a hash as 2nd parameter.
125
126 =back
127
128 =head1 API
129
130 =cut
131
132 sub zebra_create {
133         my ($biblionumber,$record) = @_;
134         # create the iso2709 file for zebra
135         my $cgidir = C4::Context->intranetdir ."/cgi-bin";
136         unless (opendir(DIR, "$cgidir")) {
137                         $cgidir = C4::Context->intranetdir."/";
138         } 
139
140         my $filename = $cgidir."/zebra/biblios/BIBLIO".$biblionumber."iso2709";
141         open F,"> $filename";
142         print F $record->as_usmarc();
143         close F;
144         my $res = system("cd $cgidir/zebra;/usr/local/bin/zebraidx update biblios");
145         unlink($filename);
146         warn "$biblionumber : $res";
147 }
148
149 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
150
151 =over 4
152
153 2nd param is 1 for liblibrarian and 0 for libopac
154 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
155
156 returns a hash with all values for all fields and subfields for a given MARC framework :
157         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
158                     ->{tab}        = "";            # XXX
159                     ->{mandatory}  = $mandatory;
160                     ->{repeatable} = $repeatable;
161                     ->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
162                                  ->{tab}              = $tab;
163                                  ->{mandatory}        = $mandatory;
164                                  ->{repeatable}       = $repeatable;
165                                  ->{authorised_value} = $authorised_value;
166                                  ->{authtypecode}     = $authtypecode;
167                                  ->{value_builder}    = $value_builder;
168                                  ->{kohafield}        = $kohafield;
169                                  ->{seealso}          = $seealso;
170                                  ->{hidden}           = $hidden;
171                                  ->{isurl}            = $isurl;
172                                  ->{link}            = $link;
173
174 =back
175
176 =cut
177
178 sub MARCgettagslib {
179     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
180     $frameworkcode = "" unless $frameworkcode;
181     my $sth;
182     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
183
184     # check that framework exists
185     $sth =
186       $dbh->prepare(
187         "select count(*) from marc_tag_structure where frameworkcode=?");
188     $sth->execute($frameworkcode);
189     my ($total) = $sth->fetchrow;
190     $frameworkcode = "" unless ( $total > 0 );
191     $sth =
192       $dbh->prepare(
193 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
194     );
195     $sth->execute($frameworkcode);
196     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
197
198     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
199         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
200         $res->{$tab}->{tab}        = "";            # XXX
201         $res->{$tag}->{mandatory}  = $mandatory;
202         $res->{$tag}->{repeatable} = $repeatable;
203     }
204
205     $sth =
206       $dbh->prepare(
207 "select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link from marc_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
208     );
209     $sth->execute($frameworkcode);
210
211     my $subfield;
212     my $authorised_value;
213     my $authtypecode;
214     my $value_builder;
215     my $kohafield;
216     my $seealso;
217     my $hidden;
218     my $isurl;
219         my $link;
220
221     while (
222         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
223         $mandatory,     $repeatable, $authorised_value, $authtypecode,
224         $value_builder, $kohafield,  $seealso,          $hidden,
225         $isurl,                 $link )
226         = $sth->fetchrow
227       )
228     {
229         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
230         $res->{$tag}->{$subfield}->{tab}              = $tab;
231         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
232         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
233         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
234         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
235         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
236         $res->{$tag}->{$subfield}->{kohafield}        = $kohafield;
237         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
238         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
239         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
240         $res->{$tag}->{$subfield}->{link}            = $link;
241     }
242     return $res;
243 }
244
245 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
246
247 =over 4
248
249 finds MARC tag and subfield for a given kohafield
250 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
251
252 =back
253
254 =cut
255
256 sub MARCfind_marc_from_kohafield {
257     my ( $dbh, $kohafield,$frameworkcode ) = @_;
258     return 0, 0 unless $kohafield;
259         my $relations = C4::Context->marcfromkohafield;
260         return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
261 }
262
263 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
264
265 =over 4
266
267 Returns a MARC::Record for the biblio $biblionumber.
268
269 =cut
270
271 sub MARCgetbiblio {
272
273     # Returns MARC::Record of the biblio passed in parameter.
274     my ( $dbh, $biblionumber ) = @_;
275         my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
276         $sth->execute($biblionumber);
277         my ($marc) = $sth->fetchrow;
278         my $record = MARC::File::USMARC::decode($marc);
279     return $record;
280 }
281
282 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
283
284 =over 4
285
286 Returns a MARC::Record with all items of biblio # $biblionumber
287
288 =back
289
290 =cut
291
292 sub MARCgetitem {
293
294     my ( $dbh, $biblionumber, $itemnumber ) = @_;
295         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
296         # get the complete MARC record
297         my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
298         $sth->execute($biblionumber);
299         my ($rawmarc) = $sth->fetchrow;
300         my $record = MARC::File::USMARC::decode($rawmarc);
301         # now, find the relevant itemnumber
302         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
303         # prepare the new item record
304         my $itemrecord = MARC::Record->new();
305         # parse all fields fields from the complete record
306         foreach ($record->field($itemnumberfield)) {
307                 # when the item field is found, save it
308                 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
309                         $itemrecord->append_fields($_);
310                 }
311         }
312
313     return $itemrecord;
314 }
315
316 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
317
318 =over 4
319
320 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
321 This sub is useless when MARC=OFF
322
323 =back
324
325 =cut
326 sub find_biblioitemnumber {
327         my ( $dbh, $biblionumber ) = @_;
328         my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
329         $sth->execute($biblionumber);
330         my ($biblioitemnumber) = $sth->fetchrow;
331         return $biblioitemnumber;
332 }
333
334 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
335
336 =over 4
337
338 returns the framework of a given biblio
339
340 =back
341
342 =cut
343
344 sub MARCfind_frameworkcode {
345         my ( $dbh, $biblionumber ) = @_;
346         my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
347         $sth->execute($biblionumber);
348         my ($frameworkcode) = $sth->fetchrow;
349         return $frameworkcode;
350 }
351
352 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$biblionumber,biblioitemnumber);
353
354 =over 4
355
356 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
357 all entries of the hash are transformed into their matching MARC field/subfield.
358
359 =back
360
361 =cut
362
363 sub MARCkoha2marcBiblio {
364
365     # this function builds partial MARC::Record from the old koha-DB fields
366     my ( $dbh, $biblionumber, $biblioitemnumber ) = @_;
367     my $sth =
368       $dbh->prepare(
369 "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
370     );
371     my $record = MARC::Record->new();
372
373     #--- if bibid, then retrieve old-style koha data
374     if ( $biblionumber > 0 ) {
375         my $sth2 =
376           $dbh->prepare(
377 "select biblionumber,author,title,unititle,notes,abstract,serial,seriestitle,copyrightdate,timestamp
378                 from biblio where biblionumber=?"
379         );
380         $sth2->execute($biblionumber);
381         my $row = $sth2->fetchrow_hashref;
382         my $code;
383         foreach $code ( keys %$row ) {
384             if ( $row->{$code} ) {
385                 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $code,
386                     $row->{$code}, '');
387             }
388         }
389     }
390
391     #--- if biblioitem, then retrieve old-style koha data
392     if ( $biblioitemnumber > 0 ) {
393         my $sth2 =
394           $dbh->prepare(
395             " SELECT biblioitemnumber,biblionumber,volume,number,classification,
396                                                 itemtype,url,isbn,issn,dewey,subclass,publicationyear,publishercode,
397                                                 volumedate,volumeddesc,timestamp,illus,pages,notes AS bnotes,size,place
398                                         FROM biblioitems
399                                         WHERE biblioitemnumber=?
400                                         "
401         );
402         $sth2->execute($biblioitemnumber);
403         my $row = $sth2->fetchrow_hashref;
404         my $code;
405         foreach $code ( keys %$row ) {
406             if ( $row->{$code} ) {
407                 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $code,
408                     $row->{$code},'' );
409             }
410         }
411     }
412
413     # other fields => additional authors, subjects, subtitles
414     my $sth2 =
415       $dbh->prepare(
416         " SELECT author FROM additionalauthors WHERE biblionumber=?");
417     $sth2->execute($biblionumber);
418     while ( my $row = $sth2->fetchrow_hashref ) {
419         &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author",
420             $row->{'author'},'' );
421     }
422     $sth2 =
423       $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
424     $sth2->execute($biblionumber);
425     while ( my $row = $sth2->fetchrow_hashref ) {
426         &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject",
427             $row->{'subject'},'' );
428     }
429     $sth2 =
430       $dbh->prepare(
431         " SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
432     $sth2->execute($biblionumber);
433     while ( my $row = $sth2->fetchrow_hashref ) {
434         &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle",
435             $row->{'subtitle'},'' );
436     }
437     return $record;
438 }
439
440 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
441
442 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
443 all entries of the hash are transformed into their matching MARC field/subfield.
444
445 =over 4
446
447 =back
448
449 =cut
450
451 sub MARCkoha2marcItem {
452
453     # this function builds partial MARC::Record from the old koha-DB fields
454     my ( $dbh, $biblionumber, $itemnumber ) = @_;
455
456     #    my $dbh=&C4Connect;
457     my $sth =
458       $dbh->prepare(
459 "select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?"
460     );
461     my $record = MARC::Record->new();
462
463     #--- if item, then retrieve old-style koha data
464     if ( $itemnumber > 0 ) {
465
466         #       print STDERR "prepare $biblionumber,$itemnumber\n";
467         my $sth2 =
468           $dbh->prepare(
469 "SELECT itemnumber,biblionumber,multivolumepart,biblioitemnumber,barcode,dateaccessioned,
470                                                 booksellerid,homebranch,price,replacementprice,replacementpricedate,datelastborrowed,
471                                                 datelastseen,multivolume,stack,notforloan,itemlost,wthdrawn,itemcallnumber,issues,renewals,
472                                         reserves,restricted,binding,itemnotes,holdingbranch,timestamp
473                                         FROM items
474                                         WHERE itemnumber=?"
475         );
476         $sth2->execute($itemnumber);
477         my $row = $sth2->fetchrow_hashref;
478         my $code;
479         foreach $code ( keys %$row ) {
480             if ( $row->{$code} ) {
481                 &MARCkoha2marcOnefield( $sth, $record, "items." . $code,
482                     $row->{$code},'' );
483             }
484         }
485     }
486     return $record;
487 }
488
489 =head2 MARCkoha2marcOnefield
490
491 =over 4
492
493 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
494
495 =back
496
497 =cut
498
499 sub MARCkoha2marcOnefield {
500     my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
501     my $tagfield;
502     my $tagsubfield;
503     $sth->execute($frameworkcode,$kohafieldname);
504     if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
505         if ( $record->field($tagfield) ) {
506             my $tag = $record->field($tagfield);
507             if ($tag) {
508                 $tag->add_subfields( $tagsubfield, $value );
509                 $record->delete_field($tag);
510                 $record->add_fields($tag);
511             }
512         }
513         else {
514             $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
515         }
516     }
517     return $record;
518 }
519
520 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
521
522 =over 4
523
524 transforms the parameters (coming from HTML form) into a MARC::Record
525 parameters with r are references to arrays.
526
527 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
528
529 =back
530
531 =cut
532
533 sub MARChtml2marc {
534         my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
535         my $prevtag = -1;
536         my $record = MARC::Record->new();
537 #       my %subfieldlist=();
538         my $prevvalue; # if tag <10
539         my $field; # if tag >=10
540         for (my $i=0; $i< @$rtags; $i++) {
541                 next unless @$rvalues[$i];
542                 # rebuild MARC::Record
543 #                       warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
544                 if (@$rtags[$i] ne $prevtag) {
545                         if ($prevtag < 10) {
546                                 if ($prevvalue) {
547                                         if ($prevtag ne '000') {
548                                                 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
549                                         } else {
550                                                 $record->leader($prevvalue);
551                                         }
552                                 }
553                         } else {
554                                 if ($field) {
555                                         $record->add_fields($field);
556                                 }
557                         }
558                         $indicators{@$rtags[$i]}.='  ';
559                         if (@$rtags[$i] <10) {
560                                 $prevvalue= @$rvalues[$i];
561                                 undef $field;
562                         } else {
563                                 undef $prevvalue;
564                                 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
565 #                       warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
566                         }
567                         $prevtag = @$rtags[$i];
568                 } else {
569                         if (@$rtags[$i] <10) {
570                                 $prevvalue=@$rvalues[$i];
571                         } else {
572                                 if (length(@$rvalues[$i])>0) {
573                                         $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
574 #                       warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
575                                 }
576                         }
577                         $prevtag= @$rtags[$i];
578                 }
579         }
580         # the last has not been included inside the loop... do it now !
581         $record->add_fields($field) if $field;
582 #       warn "HTML2MARC=".$record->as_formatted;
583         return $record;
584 }
585
586
587 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
588
589 =over 4
590
591 builds a hash with old-db datas from a MARC::Record
592
593 =back
594
595 =cut
596
597 sub MARCmarc2koha {
598         my ($dbh,$record,$frameworkcode) = @_;
599         my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
600         my $result;
601         my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
602         $sth2->execute;
603         my $field;
604         while (($field)=$sth2->fetchrow) {
605                 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
606         }
607         $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
608         $sth2->execute;
609         while (($field)=$sth2->fetchrow) {
610                 if ($field eq 'notes') { $field = 'bnotes'; }
611                 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
612         }
613         $sth2=$dbh->prepare("SHOW COLUMNS from items");
614         $sth2->execute;
615         while (($field)=$sth2->fetchrow) {
616                 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
617         }
618         # additional authors : specific
619         $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
620         $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
621 # modify copyrightdate to keep only the 1st year found
622         my $temp = $result->{'copyrightdate'};
623         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
624         if ($1>0) {
625                 $result->{'copyrightdate'} = $1;
626         } else { # if no cYYYY, get the 1st date.
627                 $temp =~ m/(\d\d\d\d)/;
628                 $result->{'copyrightdate'} = $1;
629         }
630 # modify publicationyear to keep only the 1st year found
631         $temp = $result->{'publicationyear'};
632         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
633         if ($1>0) {
634                 $result->{'publicationyear'} = $1;
635         } else { # if no cYYYY, get the 1st date.
636                 $temp =~ m/(\d\d\d\d)/;
637                 $result->{'publicationyear'} = $1;
638         }
639         return $result;
640 }
641
642 sub MARCmarc2kohaOneField {
643
644 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
645     my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
646     #    warn "kohatable / $kohafield / $result / ";
647     my $res = "";
648     my $tagfield;
649     my $subfield;
650     ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
651     foreach my $field ( $record->field($tagfield) ) {
652                 if ($field->tag()<10) {
653                         if ($result->{$kohafield}) {
654                                 $result->{$kohafield} .= " | ".$field->data();
655                         } else {
656                                 $result->{$kohafield} = $field->data();
657                         }
658                 } else {
659                         if ( $field->subfields ) {
660                                 my @subfields = $field->subfields();
661                                 foreach my $subfieldcount ( 0 .. $#subfields ) {
662                                         if ($subfields[$subfieldcount][0] eq $subfield) {
663                                                 if ( $result->{$kohafield} ) {
664                                                         $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
665                                                 }
666                                                 else {
667                                                         $result->{$kohafield} = $subfields[$subfieldcount][1];
668                                                 }
669                                         }
670                                 }
671                         }
672                 }
673     }
674 #       warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
675     return $result;
676 }
677
678 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
679
680 =over 4
681
682 creates a biblio from a MARC::Record.
683
684 =back
685
686 =cut
687
688 sub NEWnewbiblio {
689     my ( $dbh, $record, $frameworkcode ) = @_;
690     my $biblionumber;
691     my $biblioitemnumber;
692     my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
693         $olddata->{frameworkcode} = $frameworkcode;
694     $biblionumber = REALnewbiblio( $dbh, $olddata );
695         $olddata->{biblionumber} = $biblionumber;
696         # add biblionumber into the MARC record (it's the ID for zebra)
697         my ( $tagfield, $tagsubfield ) =
698                                         MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
699         # create the field
700         my $newfield;
701         if ($tagfield<10) {
702                 $newfield = MARC::Field->new(
703                         $tagfield, $biblionumber,
704                 );
705         } else {
706                 $newfield = MARC::Field->new(
707                         $tagfield, '', '', "$tagsubfield" => $biblionumber,
708                 );
709         }
710         # drop old field (just in case it already exist and create new one...
711         my $old_field = $record->field($tagfield);
712         $record->delete_field($old_field);
713         $record->add_fields($newfield);
714
715         #create the marc entry, that stores the rax marc record in Koha 3.0
716         $olddata->{marc} = $record->as_usmarc();
717         $olddata->{marcxml} = $record->as_xml();
718         # and create biblioitem, that's all folks !
719     $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
720
721     # search subtiles, addiauthors and subjects
722     ( $tagfield, $tagsubfield ) =
723       MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
724     my @addiauthfields = $record->field($tagfield);
725     foreach my $addiauthfield (@addiauthfields) {
726         my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
727         foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
728             REALmodaddauthor( $dbh, $biblionumber,
729                 $addiauthsubfields[$subfieldcount] );
730         }
731     }
732     ( $tagfield, $tagsubfield ) =
733       MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
734     my @subtitlefields = $record->field($tagfield);
735     foreach my $subtitlefield (@subtitlefields) {
736         my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
737         foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
738             REALnewsubtitle( $dbh, $biblionumber,
739                 $subtitlesubfields[$subfieldcount] );
740         }
741     }
742     ( $tagfield, $tagsubfield ) =
743       MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
744     my @subj = $record->field($tagfield);
745     my @subjects;
746     foreach my $subject (@subj) {
747         my @subjsubfield = $subject->subfield($tagsubfield);
748         foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
749             push @subjects, $subjsubfield[$subfieldcount];
750         }
751     }
752     REALmodsubject( $dbh, $biblionumber, 1, @subjects );
753     return ( $biblionumber, $biblioitemnumber );
754 }
755
756 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
757
758 =over 4
759
760 modify the framework of a biblio
761
762 =back
763
764 =cut
765
766 sub NEWmodbiblioframework {
767         my ($dbh,$biblionumber,$frameworkcode) =@_;
768         my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
769         $sth->execute($frameworkcode,$biblionumber);
770         return 1;
771 }
772
773 =head2 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
774
775 =over 4
776
777 modify a biblio (MARC=ON)
778
779 =back
780
781 =cut
782
783 sub NEWmodbiblio {
784         my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
785         $frameworkcode="" unless $frameworkcode;
786 #       &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
787         my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
788         
789         $oldbiblio->{frameworkcode} = $frameworkcode;
790         #create the marc entry, that stores the rax marc record in Koha 3.0
791         $oldbiblio->{marc} = $record->as_usmarc();
792         $oldbiblio->{marcxml} = $record->as_xml();
793         
794         REALmodbiblio($dbh,$oldbiblio);
795         REALmodbiblioitem($dbh,$oldbiblio);
796         # now, modify addi authors, subject, addititles.
797         my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
798         my @addiauthfields = $record->field($tagfield);
799         foreach my $addiauthfield (@addiauthfields) {
800                 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
801                 foreach my $subfieldcount (0..$#addiauthsubfields) {
802                         REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
803                 }
804         }
805         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
806         my @subtitlefields = $record->field($tagfield);
807         foreach my $subtitlefield (@subtitlefields) {
808                 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
809                 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
810                 # between 2 modifs
811                 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
812                 foreach my $subfieldcount (0..$#subtitlesubfields) {
813                         foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
814                                 REALnewsubtitle($dbh,$biblionumber,$subtit);
815                         }
816                 }
817         }
818         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
819         my @subj = $record->field($tagfield);
820         my @subjects;
821         foreach my $subject (@subj) {
822                 my @subjsubfield = $subject->subfield($tagsubfield);
823                 foreach my $subfieldcount (0..$#subjsubfield) {
824                         push @subjects,$subjsubfield[$subfieldcount];
825                 }
826         }
827         REALmodsubject($dbh,$biblionumber,1,@subjects);
828         return 1;
829 }
830
831 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
832
833 =over 4
834
835 delete a biblio
836
837 =back
838
839 =cut
840
841 sub NEWdelbiblio {
842     my ( $dbh, $bibid ) = @_;
843     my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
844     &REALdelbiblio( $dbh, $biblio );
845     my $sth =
846       $dbh->prepare(
847         "select biblioitemnumber from biblioitems where biblionumber=?");
848     $sth->execute($biblio);
849     while ( my ($biblioitemnumber) = $sth->fetchrow ) {
850         REALdelbiblioitem( $dbh, $biblioitemnumber );
851     }
852     &MARCdelbiblio( $dbh, $bibid, 0 );
853 }
854
855 =head2 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
856
857 =over 4
858
859 creates an item from a MARC::Record
860
861 =back
862
863 =cut
864
865 sub NEWnewitem {
866     my ( $dbh, $record, $biblionumber, $biblioitemnumber ) = @_;
867
868     # add item in old-DB
869         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
870     my $item = &MARCmarc2koha( $dbh, $record,$frameworkcode );
871     # needs old biblionumber and biblioitemnumber
872     $item->{'biblionumber'} = $biblionumber;
873     $item->{'biblioitemnumber'}=$biblioitemnumber;
874         $item->{marc} = $record->as_usmarc();
875     my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
876         return $itemnumber;
877 }
878
879
880 =head2 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
881
882 =over 4
883
884 Modify an item
885
886 =back
887
888 =cut
889
890 sub NEWmoditem {
891     my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
892     
893         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
894     my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
895         # add MARC record
896         $olditem->{marc} = $record->as_usmarc();
897         $olditem->{biblionumber} = $biblionumber;
898         $olditem->{biblioitemnumber} = $biblioitemnumber;
899         # and modify item
900     REALmoditem( $dbh, $olditem );
901 }
902
903
904 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
905
906 =over 4
907
908 delete an item
909
910 =back
911
912 =cut
913
914 sub NEWdelitem {
915     my ( $dbh, $bibid, $itemnumber ) = @_;
916     my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
917     &REALdelitem( $dbh, $itemnumber );
918     &MARCdelitem( $dbh, $bibid, $itemnumber );
919 }
920
921
922 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
923
924 =over 4
925
926 adds a record in biblio table. Datas are in the hash $biblio.
927
928 =back
929
930 =cut
931
932 sub REALnewbiblio {
933     my ( $dbh, $biblio ) = @_;
934
935         $dbh->do('lock tables biblio WRITE');
936     my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
937     $sth->execute;
938     my $data   = $sth->fetchrow_arrayref;
939     my $bibnum = $$data[0] + 1;
940     my $series = 0;
941
942     if ( $biblio->{'seriestitle'} ) { $series = 1 }
943     $sth->finish;
944     $sth =
945       $dbh->prepare("insert into biblio set     biblionumber=?, title=?,                author=?,       copyrightdate=?,
946                                                                                         serial=?,               seriestitle=?,  notes=?,        abstract=?,
947                                                                                         unititle=?"
948     );
949     $sth->execute(
950         $bibnum,             $biblio->{'title'},
951         $biblio->{'author'}, $biblio->{'copyrightdate'},
952         $biblio->{'serial'},             $biblio->{'seriestitle'},
953         $biblio->{'notes'},  $biblio->{'abstract'},
954                 $biblio->{'unititle'}
955     );
956
957     $sth->finish;
958         $dbh->do('unlock tables');
959     return ($bibnum);
960 }
961
962 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
963
964 =over 4
965
966 modify a record in biblio table. Datas are in the hash $biblio.
967
968 =back
969
970 =cut
971
972 sub REALmodbiblio {
973     my ( $dbh, $biblio ) = @_;
974     my $sth = $dbh->prepare("Update biblio set  title=?,                author=?,       abstract=?,     copyrightdate=?,
975                                                                                                 seriestitle=?,  serial=?,       unititle=?,     notes=?,        frameworkcode=? 
976                                                                                         where biblionumber = ?"
977     );
978     $sth->execute(
979                 $biblio->{'title'},       $biblio->{'author'},
980                 $biblio->{'abstract'},    $biblio->{'copyrightdate'},
981                 $biblio->{'seriestitle'}, $biblio->{'serial'},
982                 $biblio->{'unititle'},    $biblio->{'notes'},
983                 $biblio->{frameworkcode},
984                 $biblio->{'biblionumber'}
985     );
986         $sth->finish;
987         return ( $biblio->{'biblionumber'} );
988 }    # sub modbiblio
989
990 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
991
992 =over 4
993
994 modify subtitles in bibliosubtitle table.
995
996 =back
997
998 =cut
999
1000 sub REALmodsubtitle {
1001     my ( $dbh, $bibnum, $subtitle ) = @_;
1002     my $sth =
1003       $dbh->prepare(
1004         "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1005     $sth->execute( $subtitle, $bibnum );
1006     $sth->finish;
1007 }    # sub modsubtitle
1008
1009 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1010
1011 =over 4
1012
1013 adds or modify additional authors
1014 NOTE :  Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1015
1016 =back
1017
1018 =cut
1019
1020 sub REALmodaddauthor {
1021     my ( $dbh, $bibnum, @authors ) = @_;
1022
1023     #    my $dbh   = C4Connect;
1024     my $sth =
1025       $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1026
1027     $sth->execute($bibnum);
1028     $sth->finish;
1029     foreach my $author (@authors) {
1030         if ( $author ne '' ) {
1031             $sth =
1032               $dbh->prepare(
1033                 "Insert into additionalauthors set author = ?, biblionumber = ?"
1034             );
1035
1036             $sth->execute( $author, $bibnum );
1037
1038             $sth->finish;
1039         }    # if
1040     }
1041 }    # sub modaddauthor
1042
1043 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1044
1045 =over 4
1046
1047 modify/adds subjects
1048
1049 =back
1050
1051 =cut
1052 sub REALmodsubject {
1053     my ( $dbh, $bibnum, $force, @subject ) = @_;
1054
1055     #  my $dbh   = C4Connect;
1056     my $count = @subject;
1057     my $error;
1058     for ( my $i = 0 ; $i < $count ; $i++ ) {
1059         $subject[$i] =~ s/^ //g;
1060         $subject[$i] =~ s/ $//g;
1061         my $sth =
1062           $dbh->prepare(
1063 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1064         );
1065         $sth->execute( $subject[$i] );
1066
1067         if ( my $data = $sth->fetchrow_hashref ) {
1068         }
1069         else {
1070             if ( $force eq $subject[$i] || $force == 1 ) {
1071
1072                 # subject not in aut, chosen to force anway
1073                 # so insert into cataloguentry so its in auth file
1074                 my $sth2 =
1075                   $dbh->prepare(
1076 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1077                 );
1078
1079                 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1080                 $sth2->finish;
1081             }
1082             else {
1083                 $error =
1084                   "$subject[$i]\n does not exist in the subject authority file";
1085                 my $sth2 =
1086                   $dbh->prepare(
1087 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1088                 );
1089                 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1090                     "% $subject[$i]" );
1091                 while ( my $data = $sth2->fetchrow_hashref ) {
1092                     $error .= "<br>$data->{'catalogueentry'}";
1093                 }    # while
1094                 $sth2->finish;
1095             }    # else
1096         }    # else
1097         $sth->finish;
1098     }    # else
1099     if ( $error eq '' ) {
1100         my $sth =
1101           $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1102         $sth->execute($bibnum);
1103         $sth->finish;
1104         $sth =
1105           $dbh->prepare(
1106             "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1107         my $query;
1108         foreach $query (@subject) {
1109             $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1110         }    # foreach
1111         $sth->finish;
1112     }    # if
1113
1114     #  $dbh->disconnect;
1115     return ($error);
1116 }    # sub modsubject
1117
1118 =head2 REALmodbiblioitem($dbh, $biblioitem);
1119
1120 =over 4
1121
1122 modify a biblioitem
1123
1124 =back
1125
1126 =cut
1127 sub REALmodbiblioitem {
1128     my ( $dbh, $biblioitem ) = @_;
1129     my $query;
1130
1131     my $sth = $dbh->prepare("update biblioitems set     itemtype=?,                     url=?,                          isbn=?, issn=?,
1132                                                                                 publishercode=?,        publicationyear=?,      classification=?,       dewey=?,
1133                                                                                 subclass=?,                     illus=?,                        pages=?,                        volumeddesc=?,
1134                                                                                 notes=?,                        size=?,                         place=?,                        marc=?,
1135                                                                                 marcxml=?
1136                                                         where biblioitemnumber=?");
1137         $sth->execute(  $biblioitem->{itemtype},                $biblioitem->{url},             $biblioitem->{isbn},    $biblioitem->{issn},
1138                                 $biblioitem->{publishercode},   $biblioitem->{publicationyear}, $biblioitem->{classification},  $biblioitem->{dewey},
1139                                 $biblioitem->{subclass},                $biblioitem->{illus},           $biblioitem->{pages},   $biblioitem->{volumeddesc},
1140                                 $biblioitem->{bnotes},                  $biblioitem->{size},            $biblioitem->{place},   $biblioitem->{marc},
1141                                         $biblioitem->{marcxml},                 $biblioitem->{biblioitemnumber});
1142         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1143         zebra_create($biblioitem->{biblionumber}, $record);
1144 #       warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1145 }    # sub modbibitem
1146
1147 =head2 REALnewbiblioitem($dbh,$biblioitem);
1148
1149 =over 4
1150
1151 adds a biblioitem ($biblioitem is a hash with the values)
1152
1153 =back
1154
1155 =cut
1156
1157 sub REALnewbiblioitem {
1158         my ( $dbh, $biblioitem ) = @_;
1159
1160         $dbh->do("lock tables biblioitems WRITE, biblio WRITE");
1161         my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1162         my $data;
1163         my $biblioitemnumber;
1164
1165         $sth->execute;
1166         $data       = $sth->fetchrow_arrayref;
1167         $biblioitemnumber = $$data[0] + 1;
1168         
1169         # Insert biblioitemnumber in MARC record, we need it to manage items later...
1170         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1171         my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1172         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1173         my $field=$record->field($biblioitemnumberfield);
1174         $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1175         $biblioitem->{marc} = $record->as_usmarc();
1176         $biblioitem->{marcxml} = $record->as_xml();
1177
1178         $sth = $dbh->prepare( "insert into biblioitems set
1179                                                                         biblioitemnumber = ?,           biblionumber     = ?,
1180                                                                         volume           = ?,                   number           = ?,
1181                                                                         classification  = ?,                    itemtype         = ?,
1182                                                                         url              = ?,                           isbn             = ?,
1183                                                                         issn             = ?,                           dewey            = ?,
1184                                                                         subclass         = ?,                           publicationyear  = ?,
1185                                                                         publishercode    = ?,           volumedate       = ?,
1186                                                                         volumeddesc      = ?,           illus            = ?,
1187                                                                         pages            = ?,                           notes            = ?,
1188                                                                         size             = ?,                           lccn             = ?,
1189                                                                         marc             = ?,                           place            = ?,
1190                                                                         marcxml          = ?"
1191         );
1192         $sth->execute(
1193                 $biblioitemnumber,               $biblioitem->{'biblionumber'},
1194                 $biblioitem->{'volume'},         $biblioitem->{'number'},
1195                 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1196                 $biblioitem->{'url'},            $biblioitem->{'isbn'},
1197                 $biblioitem->{'issn'},           $biblioitem->{'dewey'},
1198                 $biblioitem->{'subclass'},       $biblioitem->{'publicationyear'},
1199                 $biblioitem->{'publishercode'},  $biblioitem->{'volumedate'},
1200                 $biblioitem->{'volumeddesc'},    $biblioitem->{'illus'},
1201                 $biblioitem->{'pages'},          $biblioitem->{'bnotes'},
1202                 $biblioitem->{'size'},           $biblioitem->{'lccn'},
1203                 $biblioitem->{'marc'},           $biblioitem->{'place'},
1204                 $biblioitem->{marcxml},
1205         );
1206         $dbh->do("unlock tables");
1207         zebra_create($biblioitem->{biblionumber}, $record);
1208         return ($biblioitemnumber);
1209 }
1210
1211 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1212
1213 =over 4
1214
1215 create a new subtitle
1216
1217 =back
1218
1219 =cut
1220 sub REALnewsubtitle {
1221     my ( $dbh, $bibnum, $subtitle ) = @_;
1222     my $sth =
1223       $dbh->prepare(
1224         "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1225     $sth->execute( $bibnum, $subtitle ) if $subtitle;
1226     $sth->finish;
1227 }
1228
1229 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1230
1231 =over 4
1232
1233 create a item. $item is a hash and $barcode the barcode.
1234
1235 =back
1236
1237 =cut
1238
1239 sub REALnewitems {
1240     my ( $dbh, $item, $barcode ) = @_;
1241
1242 #       warn "OLDNEWITEMS";
1243         
1244         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1245     my $sth = $dbh->prepare("Select max(itemnumber) from items");
1246     my $data;
1247     my $itemnumber;
1248     my $error = "";
1249     $sth->execute;
1250     $data       = $sth->fetchrow_hashref;
1251     $itemnumber = $data->{'max(itemnumber)'} + 1;
1252
1253 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1254     if ( $item->{'loan'} ) {
1255         $item->{'notforloan'} = $item->{'loan'};
1256     }
1257
1258     # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1259     if ( $item->{'dateaccessioned'} ) {
1260         $sth = $dbh->prepare( "Insert into items set
1261                                                         itemnumber           = ?,                       biblionumber         = ?,
1262                                                         multivolumepart      = ?,
1263                                                         biblioitemnumber     = ?,                       barcode              = ?,
1264                                                         booksellerid         = ?,                       dateaccessioned      = ?,
1265                                                         homebranch           = ?,                       holdingbranch        = ?,
1266                                                         price                = ?,                       replacementprice     = ?,
1267                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1268                                                         multivolume                     = ?,                    stack                           = ?,
1269                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1270                                                         paidfor                         = ?,                    itemnotes            = ?,
1271                                                         itemcallnumber  =?,                                                     notforloan = ?,
1272                                                         location = ?
1273                                                         "
1274         );
1275         $sth->execute(
1276                         $itemnumber,                            $item->{'biblionumber'},
1277                         $item->{'multivolumepart'},
1278                         $item->{'biblioitemnumber'},$barcode,
1279                         $item->{'booksellerid'},        $item->{'dateaccessioned'},
1280                         $item->{'homebranch'},          $item->{'holdingbranch'},
1281                         $item->{'price'},                       $item->{'replacementprice'},
1282                         $item->{multivolume},           $item->{stack},
1283                         $item->{itemlost},                      $item->{wthdrawn},
1284                         $item->{paidfor},                       $item->{'itemnotes'},
1285                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1286                         $item->{'location'}
1287         );
1288                 if ( defined $sth->errstr ) {
1289                         $error .= $sth->errstr;
1290                 }
1291     }
1292     else {
1293         $sth = $dbh->prepare( "Insert into items set
1294                                                         itemnumber           = ?,                       biblionumber         = ?,
1295                                                         multivolumepart      = ?,
1296                                                         biblioitemnumber     = ?,                       barcode              = ?,
1297                                                         booksellerid         = ?,                       dateaccessioned      = NOW(),
1298                                                         homebranch           = ?,                       holdingbranch        = ?,
1299                                                         price                = ?,                       replacementprice     = ?,
1300                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1301                                                         multivolume                     = ?,                    stack                           = ?,
1302                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1303                                                         paidfor                         = ?,                    itemnotes            = ?,
1304                                                         itemcallnumber  =?,                                                     notforloan = ?,
1305                                                         location = ?
1306                                                         "
1307         );
1308         $sth->execute(
1309                         $itemnumber,                            $item->{'biblionumber'},
1310                         $item->{'multivolumepart'},
1311                         $item->{'biblioitemnumber'},$barcode,
1312                         $item->{'booksellerid'},
1313                         $item->{'homebranch'},          $item->{'holdingbranch'},
1314                         $item->{'price'},                       $item->{'replacementprice'},
1315                         $item->{multivolume},           $item->{stack},
1316                         $item->{itemlost},                      $item->{wthdrawn},
1317                         $item->{paidfor},                       $item->{'itemnotes'},
1318                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1319                         $item->{'location'}
1320         );
1321                 if ( defined $sth->errstr ) {
1322                         $error .= $sth->errstr;
1323                 }
1324     }
1325         # item stored, now, deal with the marc part...
1326         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1327                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1328                                                                         biblio.biblionumber=?");
1329         $sth->execute($item->{biblionumber});
1330     if ( defined $sth->errstr ) {
1331         $error .= $sth->errstr;
1332     }
1333         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1334         warn "ERROR IN OLDnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1335         my $record = MARC::File::USMARC::decode($rawmarc);
1336         # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1337         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1338         my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1339         my $itemfield = $itemrecord->field($itemnumberfield);
1340         $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1341         $record->insert_grouped_field($itemfield);
1342         # save the record into biblioitem
1343         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1344         $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1345     if ( defined $sth->errstr ) {
1346         $error .= $sth->errstr;
1347     }
1348         zebra_create($item->{biblionumber},$record);
1349         $dbh->do('unlock tables');
1350     return ( $itemnumber, $error );
1351 }
1352
1353 =head2 REALmoditem($dbh,$item);
1354
1355 =over 4
1356
1357 modify item
1358
1359 =back
1360
1361 =cut
1362
1363 sub REALmoditem {
1364     my ( $dbh, $item ) = @_;
1365         my $error;
1366         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1367     $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1368     my $query = "update items set  barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1369     my @bind = (
1370         $item->{'barcode'},                     $item->{'notes'},
1371         $item->{'itemcallnumber'},      $item->{'notforloan'},
1372         $item->{'location'},            $item->{multivolumepart},
1373                 $item->{multivolume},           $item->{stack},
1374                 $item->{wthdrawn},
1375     );
1376     if ( $item->{'lost'} ne '' ) {
1377         $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1378                                                         itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1379                                                         location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1380         @bind = (
1381             $item->{'bibitemnum'},     $item->{'barcode'},
1382             $item->{'notes'},          $item->{'homebranch'},
1383             $item->{'lost'},           $item->{'wthdrawn'},
1384             $item->{'itemcallnumber'}, $item->{'notforloan'},
1385             $item->{'location'},                $item->{multivolumepart},
1386                         $item->{multivolume},           $item->{stack},
1387                         $item->{wthdrawn},
1388         );
1389                 if ($item->{homebranch}) {
1390                         $query.=",homebranch=?";
1391                         push @bind, $item->{homebranch};
1392                 }
1393                 if ($item->{holdingbranch}) {
1394                         $query.=",holdingbranch=?";
1395                         push @bind, $item->{holdingbranch};
1396                 }
1397     }
1398         $query.=" where itemnumber=?";
1399         push @bind,$item->{'itemnum'};
1400    if ( $item->{'replacement'} ne '' ) {
1401         $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1402     }
1403     my $sth = $dbh->prepare($query);
1404     $sth->execute(@bind);
1405         
1406         # item stored, now, deal with the marc part...
1407         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1408                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1409                                                                         biblio.biblionumber=? and 
1410                                                                         biblioitems.biblioitemnumber=?");
1411         $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1412     if ( defined $sth->errstr ) {
1413         $error .= $sth->errstr;
1414     }
1415         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1416         warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1417         my $record = MARC::File::USMARC::decode($rawmarc);
1418         # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1419         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1420         # prepare the new item record
1421         my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1422         my $itemfield = $itemrecord->field($itemnumberfield);
1423         $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1424         # parse all fields fields from the complete record
1425         foreach ($record->field($itemnumberfield)) {
1426                 # when the previous field is found, replace by the new one
1427                 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1428                         $_->replace_with($itemfield);
1429                 }
1430         }
1431 #       $record->insert_grouped_field($itemfield);
1432         # save the record into biblioitem
1433         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1434         $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1435         zebra_create($item->biblionumber,$record);
1436     if ( defined $sth->errstr ) {
1437         $error .= $sth->errstr;
1438     }
1439         $dbh->do('unlock tables');
1440
1441     #  $dbh->disconnect;
1442 }
1443
1444 =head2 REALdelitem($dbh,$itemnum);
1445
1446 =over 4
1447
1448 delete item
1449
1450 =back
1451
1452 =cut
1453
1454 sub REALdelitem {
1455     my ( $dbh, $itemnum ) = @_;
1456
1457     #  my $dbh=C4Connect;
1458     my $sth = $dbh->prepare("select * from items where itemnumber=?");
1459     $sth->execute($itemnum);
1460     my $data = $sth->fetchrow_hashref;
1461     $sth->finish;
1462     my $query = "Insert into deleteditems set ";
1463     my @bind  = ();
1464     foreach my $temp ( keys %$data ) {
1465         $query .= "$temp = ?,";
1466         push ( @bind, $data->{$temp} );
1467     }
1468     $query =~ s/\,$//;
1469
1470     #  print $query;
1471     $sth = $dbh->prepare($query);
1472     $sth->execute(@bind);
1473     $sth->finish;
1474     $sth = $dbh->prepare("Delete from items where itemnumber=?");
1475     $sth->execute($itemnum);
1476     $sth->finish;
1477
1478     #  $dbh->disconnect;
1479 }
1480
1481 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1482
1483 =over 4
1484
1485 deletes a biblioitem
1486 NOTE : not standard sub name. Should be REALdelbiblioitem()
1487
1488 =back
1489
1490 =cut
1491
1492 sub REALdelbiblioitem {
1493     my ( $dbh, $biblioitemnumber ) = @_;
1494
1495     #    my $dbh   = C4Connect;
1496     my $sth = $dbh->prepare( "Select * from biblioitems
1497 where biblioitemnumber = ?"
1498     );
1499     my $results;
1500
1501     $sth->execute($biblioitemnumber);
1502
1503     if ( $results = $sth->fetchrow_hashref ) {
1504         $sth->finish;
1505         $sth =
1506           $dbh->prepare(
1507 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1508                                         isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1509                                         pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1510         );
1511
1512         $sth->execute(
1513             $results->{biblioitemnumber}, $results->{biblionumber},
1514             $results->{volume},           $results->{number},
1515             $results->{classification},   $results->{itemtype},
1516             $results->{isbn},             $results->{issn},
1517             $results->{dewey},            $results->{subclass},
1518             $results->{publicationyear},  $results->{publishercode},
1519             $results->{volumedate},       $results->{volumeddesc},
1520             $results->{timestamp},        $results->{illus},
1521             $results->{pages},            $results->{notes},
1522             $results->{size},             $results->{url},
1523             $results->{lccn}
1524         );
1525         my $sth2 =
1526           $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1527         $sth2->execute($biblioitemnumber);
1528         $sth2->finish();
1529     }    # if
1530     $sth->finish;
1531
1532     # Now delete all the items attached to the biblioitem
1533     $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1534     $sth->execute($biblioitemnumber);
1535     my @results;
1536     while ( my $data = $sth->fetchrow_hashref ) {
1537         my $query = "Insert into deleteditems set ";
1538         my @bind  = ();
1539         foreach my $temp ( keys %$data ) {
1540             $query .= "$temp = ?,";
1541             push ( @bind, $data->{$temp} );
1542         }
1543         $query =~ s/\,$//;
1544         my $sth2 = $dbh->prepare($query);
1545         $sth2->execute(@bind);
1546     }    # while
1547     $sth->finish;
1548     $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1549     $sth->execute($biblioitemnumber);
1550     $sth->finish();
1551
1552     #    $dbh->disconnect;
1553 }    # sub deletebiblioitem
1554
1555 =head2 REALdelbiblio($dbh,$biblio);
1556
1557 =over 4
1558
1559 delete a biblio
1560
1561 =back
1562
1563 =cut
1564
1565 sub REALdelbiblio {
1566     my ( $dbh, $biblio ) = @_;
1567     my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1568     $sth->execute($biblio);
1569     if ( my $data = $sth->fetchrow_hashref ) {
1570         $sth->finish;
1571         my $query = "Insert into deletedbiblio set ";
1572         my @bind  = ();
1573         foreach my $temp ( keys %$data ) {
1574             $query .= "$temp = ?,";
1575             push ( @bind, $data->{$temp} );
1576         }
1577
1578         #replacing the last , by ",?)"
1579         $query =~ s/\,$//;
1580         $sth = $dbh->prepare($query);
1581         $sth->execute(@bind);
1582         $sth->finish;
1583         $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1584         $sth->execute($biblio);
1585         $sth->finish;
1586     }
1587     $sth->finish;
1588 }
1589
1590 =head2 $number = itemcount($biblio);
1591
1592 =over 4
1593
1594 returns the number of items attached to a biblio
1595
1596 =back
1597
1598 =cut
1599
1600 sub itemcount {
1601     my ($biblio) = @_;
1602     my $dbh = C4::Context->dbh;
1603
1604     #  print $query;
1605     my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1606     $sth->execute($biblio);
1607     my $data = $sth->fetchrow_hashref;
1608     $sth->finish;
1609     return ( $data->{'count(*)'} );
1610 }
1611
1612 =head2 $biblionumber = newbiblio($biblio);
1613
1614 =over 4
1615
1616 create a biblio. The parameter is a hash
1617
1618 =back
1619
1620 =cut
1621
1622 sub newbiblio {
1623     my ($biblio) = @_;
1624     my $dbh    = C4::Context->dbh;
1625     my $bibnum = REALnewbiblio( $dbh, $biblio );
1626     # finds new (MARC bibid
1627     #   my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1628     my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1629     MARCaddbiblio( $dbh, $record, $bibnum,'' );
1630     return ($bibnum);
1631 }
1632
1633 =head2   $biblionumber = &modbiblio($biblio);
1634
1635 =over 4
1636
1637 Update a biblio record.
1638
1639 C<$biblio> is a reference-to-hash whose keys are the fields in the
1640 biblio table in the Koha database. All fields must be present, not
1641 just the ones you wish to change.
1642
1643 C<&modbiblio> updates the record defined by
1644 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1645
1646 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1647 successful or not.
1648
1649 =back
1650
1651 =cut
1652
1653 sub modbiblio {
1654         my ($biblio) = @_;
1655         my $dbh  = C4::Context->dbh;
1656         my $biblionumber=REALmodbiblio($dbh,$biblio);
1657         my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1658         # finds new (MARC bibid
1659         my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1660         MARCmodbiblio($dbh,$bibid,$record,"",0);
1661         return($biblionumber);
1662 } # sub modbiblio
1663
1664 =head2   &modsubtitle($biblionumber, $subtitle);
1665
1666 =over 4
1667
1668 Sets the subtitle of a book.
1669
1670 C<$biblionumber> is the biblionumber of the book to modify.
1671
1672 C<$subtitle> is the new subtitle.
1673
1674 =back
1675
1676 =cut
1677
1678 sub modsubtitle {
1679     my ( $bibnum, $subtitle ) = @_;
1680     my $dbh = C4::Context->dbh;
1681     &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1682 }    # sub modsubtitle
1683
1684 =head2 &modaddauthor($biblionumber, $author);
1685
1686 =over 4
1687
1688 Replaces all additional authors for the book with biblio number
1689 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1690 C<&modaddauthor> deletes all additional authors.
1691
1692 =back
1693
1694 =cut
1695
1696 sub modaddauthor {
1697     my ( $bibnum, @authors ) = @_;
1698     my $dbh = C4::Context->dbh;
1699     &REALmodaddauthor( $dbh, $bibnum, @authors );
1700 }    # sub modaddauthor
1701
1702 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1703
1704 =over 4
1705
1706 $force - a subject to force
1707 $error - Error message, or undef if successful.
1708
1709 =back
1710
1711 =cut
1712
1713 sub modsubject {
1714     my ( $bibnum, $force, @subject ) = @_;
1715     my $dbh = C4::Context->dbh;
1716     my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1717     if ($error eq ''){
1718                 # When MARC is off, ensures that the MARC biblio table gets updated with new
1719                 # subjects, of course, it deletes the biblio in marc, and then recreates.
1720                 # This check is to ensure that no MARC data exists to lose.
1721                 if (C4::Context->preference("MARC") eq '0'){
1722                         my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1723                         my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1724                         &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1725                 }
1726         }
1727         return ($error);
1728 }    # sub modsubject
1729
1730 =head2 modbibitem($biblioitem);
1731
1732 =over 4
1733
1734 modify a biblioitem. The parameter is a hash
1735
1736 =back
1737
1738 =cut
1739
1740 sub modbibitem {
1741     my ($biblioitem) = @_;
1742     my $dbh = C4::Context->dbh;
1743     &REALmodbiblioitem( $dbh, $biblioitem );
1744 }    # sub modbibitem
1745
1746 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1747
1748 =over 4
1749
1750 create a biblioitem, the parameter is a hash
1751
1752 =back
1753
1754 =cut
1755
1756 sub newbiblioitem {
1757     my ($biblioitem) = @_;
1758     my $dbh        = C4::Context->dbh;
1759     my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1760
1761     my $MARCbiblio =
1762       MARCkoha2marcBiblio( $dbh, 0, $bibitemnum )
1763       ; # the 0 means "do NOT retrieve biblio, only biblioitem, in the MARC record
1764     my $bibid =
1765       &MARCfind_MARCbibid_from_oldbiblionumber( $dbh,
1766         $biblioitem->{biblionumber} );
1767     &MARCaddbiblio( $dbh, $MARCbiblio, $biblioitem->{biblionumber}, '',$bibid );
1768     return ($bibitemnum);
1769 }
1770
1771 =head2 newsubtitle($biblionumber,$subtitle);
1772
1773 =over 4
1774
1775 insert a subtitle for $biblionumber biblio
1776
1777 =back
1778
1779 =cut
1780
1781
1782 sub newsubtitle {
1783     my ( $bibnum, $subtitle ) = @_;
1784     my $dbh = C4::Context->dbh;
1785     &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1786 }
1787
1788 =head2 $errors = newitems($item, @barcodes);
1789
1790 =over 4
1791
1792 insert items ($item is a hash)
1793
1794 =back
1795
1796 =cut
1797
1798
1799 sub newitems {
1800     my ( $item, @barcodes ) = @_;
1801     my $dbh = C4::Context->dbh;
1802     my $errors;
1803     my $itemnumber;
1804     my $error;
1805     foreach my $barcode (@barcodes) {
1806         ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, uc($barcode) );
1807         $errors .= $error;
1808         my $MARCitem =
1809           &MARCkoha2marcItem( $dbh, $item->{biblionumber}, $itemnumber );
1810         &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1811     }
1812     return ($errors);
1813 }
1814
1815 =head2 moditem($item);
1816
1817 =over 4
1818
1819 modify an item ($item is a hash with all item informations)
1820
1821 =back
1822
1823 =cut
1824
1825
1826 sub moditem {
1827     my ($item) = @_;
1828     my $dbh = C4::Context->dbh;
1829     &REALmoditem( $dbh, $item );
1830     my $MARCitem =
1831       &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1832     my $bibid =
1833       &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1834     &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1835 }
1836
1837 =head2 $error = checkitems($count,@barcodes);
1838
1839 =over 4
1840
1841 check for each @barcode entry that the barcode is not a duplicate
1842
1843 =back
1844
1845 =cut
1846
1847 sub checkitems {
1848     my ( $count, @barcodes ) = @_;
1849     my $dbh = C4::Context->dbh;
1850     my $error;
1851     my $sth = $dbh->prepare("Select * from items where barcode=?");
1852     for ( my $i = 0 ; $i < $count ; $i++ ) {
1853         $barcodes[$i] = uc $barcodes[$i];
1854         $sth->execute( $barcodes[$i] );
1855         if ( my $data = $sth->fetchrow_hashref ) {
1856             $error .= " Duplicate Barcode: $barcodes[$i]";
1857         }
1858     }
1859     $sth->finish;
1860     return ($error);
1861 }
1862
1863 =head2 $delitem($itemnum);
1864
1865 =over 4
1866
1867 delete item $itemnum being the item number to delete
1868
1869 =back
1870
1871 =cut
1872
1873 sub delitem {
1874     my ($itemnum) = @_;
1875     my $dbh = C4::Context->dbh;
1876     &REALdelitem( $dbh, $itemnum );
1877 }
1878
1879 =head2 deletebiblioitem($biblioitemnumber);
1880
1881 =over 4
1882
1883 delete the biblioitem $biblioitemnumber
1884
1885 =back
1886
1887 =cut
1888
1889 sub deletebiblioitem {
1890     my ($biblioitemnumber) = @_;
1891     my $dbh = C4::Context->dbh;
1892     &REALdelbiblioitem( $dbh, $biblioitemnumber );
1893 }    # sub deletebiblioitem
1894
1895 =head2 delbiblio($biblionumber)
1896
1897 =over 4
1898
1899 delete biblio $biblionumber
1900
1901 =back
1902
1903 =cut
1904
1905 sub delbiblio {
1906     my ($biblio) = @_;
1907     my $dbh = C4::Context->dbh;
1908     &REALdelbiblio( $dbh, $biblio );
1909     my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
1910     &MARCdelbiblio( $dbh, $bibid, 0 );
1911 }
1912
1913 =head2 ($count,@results) = getbiblio($biblionumber);
1914
1915 =over 4
1916
1917 return an array with hash of biblios.
1918
1919 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
1920
1921 =back
1922
1923 =cut
1924
1925 sub getbiblio {
1926     my ($biblionumber) = @_;
1927     my $dbh = C4::Context->dbh;
1928     my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
1929
1930     # || die "Cannot prepare $query\n" . $dbh->errstr;
1931     my $count = 0;
1932     my @results;
1933
1934     $sth->execute($biblionumber);
1935
1936     # || die "Cannot execute $query\n" . $sth->errstr;
1937     while ( my $data = $sth->fetchrow_hashref ) {
1938         $results[$count] = $data;
1939         $count++;
1940     }    # while
1941
1942     $sth->finish;
1943     return ( $count, @results );
1944 }    # sub getbiblio
1945
1946 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
1947
1948 =over 4
1949
1950 return an array with hash of biblioitemss.
1951
1952 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
1953
1954 =back
1955
1956 =cut
1957
1958 sub getbiblioitem {
1959     my ($biblioitemnum) = @_;
1960     my $dbh = C4::Context->dbh;
1961     my $sth = $dbh->prepare( "Select * from biblioitems where
1962 biblioitemnumber = ?"
1963     );
1964     my $count = 0;
1965     my @results;
1966
1967     $sth->execute($biblioitemnum);
1968
1969     while ( my $data = $sth->fetchrow_hashref ) {
1970         $results[$count] = $data;
1971         $count++;
1972     }    # while
1973
1974     $sth->finish;
1975     return ( $count, @results );
1976 }    # sub getbiblioitem
1977
1978 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
1979
1980 =over 4
1981
1982 return an array with hash of biblioitems for the given biblionumber.
1983
1984 =back
1985
1986 =cut
1987
1988 sub getbiblioitembybiblionumber {
1989     my ($biblionumber) = @_;
1990     my $dbh = C4::Context->dbh;
1991     my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
1992     my $count = 0;
1993     my @results;
1994
1995     $sth->execute($biblionumber);
1996
1997     while ( my $data = $sth->fetchrow_hashref ) {
1998         $results[$count] = $data;
1999         $count++;
2000     }    # while
2001
2002     $sth->finish;
2003     return ( $count, @results );
2004 }    # sub
2005
2006 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2007
2008 =over 4
2009
2010 returns an array with hash of items
2011
2012 =back
2013
2014 =cut
2015
2016 sub getitemsbybiblioitem {
2017     my ($biblioitemnum) = @_;
2018     my $dbh = C4::Context->dbh;
2019     my $sth = $dbh->prepare( "Select * from items, biblio where
2020 biblio.biblionumber = items.biblionumber and biblioitemnumber
2021 = ?"
2022     );
2023
2024     # || die "Cannot prepare $query\n" . $dbh->errstr;
2025     my $count = 0;
2026     my @results;
2027
2028     $sth->execute($biblioitemnum);
2029
2030     # || die "Cannot execute $query\n" . $sth->errstr;
2031     while ( my $data = $sth->fetchrow_hashref ) {
2032         $results[$count] = $data;
2033         $count++;
2034     }    # while
2035
2036     $sth->finish;
2037     return ( $count, @results );
2038 }    # sub getitemsbybiblioitem
2039
2040 sub char_decode {
2041
2042     # converts ISO 5426 coded string to ISO 8859-1
2043     # sloppy code : should be improved in next issue
2044     my ( $string, $encoding ) = @_;
2045     $_ = $string;
2046
2047     #   $encoding = C4::Context->preference("marcflavour") unless $encoding;
2048     if ( $encoding eq "UNIMARC" ) {
2049 #         s/\xe1/Æ/gm;
2050         s/\xe2/Ð/gm;
2051         s/\xe9/Ø/gm;
2052         s/\xec/þ/gm;
2053         s/\xf1/æ/gm;
2054         s/\xf3/ð/gm;
2055         s/\xf9/ø/gm;
2056         s/\xfb/ß/gm;
2057         s/\xc1\x61/à/gm;
2058         s/\xc1\x65/è/gm;
2059         s/\xc1\x69/ì/gm;
2060         s/\xc1\x6f/ò/gm;
2061         s/\xc1\x75/ù/gm;
2062         s/\xc1\x41/À/gm;
2063         s/\xc1\x45/È/gm;
2064         s/\xc1\x49/Ì/gm;
2065         s/\xc1\x4f/Ò/gm;
2066         s/\xc1\x55/Ù/gm;
2067         s/\xc2\x41/Á/gm;
2068         s/\xc2\x45/É/gm;
2069         s/\xc2\x49/Í/gm;
2070         s/\xc2\x4f/Ó/gm;
2071         s/\xc2\x55/Ú/gm;
2072         s/\xc2\x59/Ý/gm;
2073         s/\xc2\x61/á/gm;
2074         s/\xc2\x65/é/gm;
2075         s/\xc2\x69/í/gm;
2076         s/\xc2\x6f/ó/gm;
2077         s/\xc2\x75/ú/gm;
2078         s/\xc2\x79/ý/gm;
2079         s/\xc3\x41/Â/gm;
2080         s/\xc3\x45/Ê/gm;
2081         s/\xc3\x49/Î/gm;
2082         s/\xc3\x4f/Ô/gm;
2083         s/\xc3\x55/Û/gm;
2084         s/\xc3\x61/â/gm;
2085         s/\xc3\x65/ê/gm;
2086         s/\xc3\x69/î/gm;
2087         s/\xc3\x6f/ô/gm;
2088         s/\xc3\x75/û/gm;
2089         s/\xc4\x41/Ã/gm;
2090         s/\xc4\x4e/Ñ/gm;
2091         s/\xc4\x4f/Õ/gm;
2092         s/\xc4\x61/ã/gm;
2093         s/\xc4\x6e/ñ/gm;
2094         s/\xc4\x6f/õ/gm;
2095         s/\xc8\x41/Ä/gm;
2096         s/\xc8\x45/Ë/gm;
2097         s/\xc8\x49/Ï/gm;
2098         s/\xc8\x61/ä/gm;
2099         s/\xc8\x65/ë/gm;
2100         s/\xc8\x69/ï/gm;
2101         s/\xc8\x6F/ö/gm;
2102         s/\xc8\x75/ü/gm;
2103         s/\xc8\x76/ÿ/gm;
2104         s/\xc9\x41/Ä/gm;
2105         s/\xc9\x45/Ë/gm;
2106         s/\xc9\x49/Ï/gm;
2107         s/\xc9\x4f/Ö/gm;
2108         s/\xc9\x55/Ü/gm;
2109         s/\xc9\x61/ä/gm;
2110         s/\xc9\x6f/ö/gm;
2111         s/\xc9\x75/ü/gm;
2112         s/\xca\x41/Å/gm;
2113         s/\xca\x61/å/gm;
2114         s/\xd0\x43/Ç/gm;
2115         s/\xd0\x63/ç/gm;
2116
2117         # this handles non-sorting blocks (if implementation requires this)
2118         $string = nsb_clean($_);
2119     }
2120     elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
2121         if (/[\xc1-\xff]/) {
2122             s/\xe1\x61/à/gm;
2123             s/\xe1\x65/è/gm;
2124             s/\xe1\x69/ì/gm;
2125             s/\xe1\x6f/ò/gm;
2126             s/\xe1\x75/ù/gm;
2127             s/\xe1\x41/À/gm;
2128             s/\xe1\x45/È/gm;
2129             s/\xe1\x49/Ì/gm;
2130             s/\xe1\x4f/Ò/gm;
2131             s/\xe1\x55/Ù/gm;
2132             s/\xe2\x41/Á/gm;
2133             s/\xe2\x45/É/gm;
2134             s/\xe2\x49/Í/gm;
2135             s/\xe2\x4f/Ó/gm;
2136             s/\xe2\x55/Ú/gm;
2137             s/\xe2\x59/Ý/gm;
2138             s/\xe2\x61/á/gm;
2139             s/\xe2\x65/é/gm;
2140             s/\xe2\x69/í/gm;
2141             s/\xe2\x6f/ó/gm;
2142             s/\xe2\x75/ú/gm;
2143             s/\xe2\x79/ý/gm;
2144             s/\xe3\x41/Â/gm;
2145             s/\xe3\x45/Ê/gm;
2146             s/\xe3\x49/Î/gm;
2147             s/\xe3\x4f/Ô/gm;
2148             s/\xe3\x55/Û/gm;
2149             s/\xe3\x61/â/gm;
2150             s/\xe3\x65/ê/gm;
2151             s/\xe3\x69/î/gm;
2152             s/\xe3\x6f/ô/gm;
2153             s/\xe3\x75/û/gm;
2154             s/\xe4\x41/Ã/gm;
2155             s/\xe4\x4e/Ñ/gm;
2156             s/\xe4\x4f/Õ/gm;
2157             s/\xe4\x61/ã/gm;
2158             s/\xe4\x6e/ñ/gm;
2159             s/\xe4\x6f/õ/gm;
2160             s/\xe8\x45/Ë/gm;
2161             s/\xe8\x49/Ï/gm;
2162             s/\xe8\x65/ë/gm;
2163             s/\xe8\x69/ï/gm;
2164             s/\xe8\x76/ÿ/gm;
2165             s/\xe9\x41/Ä/gm;
2166             s/\xe9\x4f/Ö/gm;
2167             s/\xe9\x55/Ü/gm;
2168             s/\xe9\x61/ä/gm;
2169             s/\xe9\x6f/ö/gm;
2170             s/\xe9\x75/ü/gm;
2171             s/\xea\x41/Å/gm;
2172             s/\xea\x61/å/gm;
2173
2174             # this handles non-sorting blocks (if implementation requires this)
2175             $string = nsb_clean($_);
2176         }
2177     }
2178     return ($string);
2179 }
2180
2181 sub nsb_clean {
2182     my $NSB = '\x88';    # NSB : begin Non Sorting Block
2183     my $NSE = '\x89';    # NSE : Non Sorting Block end
2184                          # handles non sorting blocks
2185     my ($string) = @_;
2186     $_ = $string;
2187     s/$NSB/(/gm;
2188     s/[ ]{0,1}$NSE/) /gm;
2189     $string = $_;
2190     return ($string);
2191 }
2192
2193 sub FindDuplicate {
2194         my ($record)=@_;
2195         my $dbh = C4::Context->dbh;
2196         my $result = MARCmarc2koha($dbh,$record,'');
2197         my $sth;
2198         my ($biblionumber,$bibid,$title);
2199         # search duplicate on ISBN, easy and fast...
2200         if ($result->{isbn}) {
2201                 $sth = $dbh->prepare("select biblio.biblionumber,bibid,title from biblio,biblioitems,marc_biblio where biblio.biblionumber=biblioitems.biblionumber and marc_biblio.biblionumber=biblioitems.biblionumber and isbn=?");
2202                 $sth->execute($result->{'isbn'});
2203                 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2204                 return $biblionumber,$bibid,$title if ($biblionumber);
2205         }
2206         # a more complex search : build a request for SearchMarc::catalogsearch()
2207         my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2208         # search on biblio.title
2209         my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2210         if ($record->field($tag)) {
2211                 if ($record->field($tag)->subfields($subfield)) {
2212                         push @tags, "'".$tag.$subfield."'";
2213                         push @and_or, "and";
2214                         push @excluding, "";
2215                         push @operator, "contains";
2216                         push @value, $record->field($tag)->subfield($subfield);
2217 #                       warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2218                 }
2219         }
2220         # ... and on biblio.author
2221         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2222         if ($record->field($tag)) {
2223                 if ($record->field($tag)->subfields($subfield)) {
2224                         push @tags, "'".$tag.$subfield."'";
2225                         push @and_or, "and";
2226                         push @excluding, "";
2227                         push @operator, "contains";
2228                         push @value, $record->field($tag)->subfield($subfield);
2229 #                       warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2230                 }
2231         }
2232         # ... and on publicationyear.
2233         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2234         if ($record->field($tag)) {
2235                 if ($record->field($tag)->subfields($subfield)) {
2236                         push @tags, "'".$tag.$subfield."'";
2237                         push @and_or, "and";
2238                         push @excluding, "";
2239                         push @operator, "=";
2240                         push @value, $record->field($tag)->subfield($subfield);
2241 #                       warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2242                 }
2243         }
2244         # ... and on size.
2245         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2246         if ($record->field($tag)) {
2247                 if ($record->field($tag)->subfields($subfield)) {
2248                         push @tags, "'".$tag.$subfield."'";
2249                         push @and_or, "and";
2250                         push @excluding, "";
2251                         push @operator, "=";
2252                         push @value, $record->field($tag)->subfield($subfield);
2253 #                       warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2254                 }
2255         }
2256         # ... and on publisher.
2257         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2258         if ($record->field($tag)) {
2259                 if ($record->field($tag)->subfields($subfield)) {
2260                         push @tags, "'".$tag.$subfield."'";
2261                         push @and_or, "and";
2262                         push @excluding, "";
2263                         push @operator, "=";
2264                         push @value, $record->field($tag)->subfield($subfield);
2265 #                       warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2266                 }
2267         }
2268         # ... and on volume.
2269         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2270         if ($record->field($tag)) {
2271                 if ($record->field($tag)->subfields($subfield)) {
2272                         push @tags, "'".$tag.$subfield."'";
2273                         push @and_or, "and";
2274                         push @excluding, "";
2275                         push @operator, "=";
2276                         push @value, $record->field($tag)->subfield($subfield);
2277 #                       warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2278                 }
2279         }
2280
2281         my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2282         # there is at least 1 result => return the 1st one
2283         if ($nbresult) {
2284 #               warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2285                 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2286         }
2287         # no result, returns nothing
2288         return;
2289 }
2290
2291 sub DisplayISBN {
2292         my ($isbn)=@_;
2293         my $seg1;
2294         if(substr($isbn, 0, 1) <=7) {
2295                 $seg1 = substr($isbn, 0, 1);
2296         } elsif(substr($isbn, 0, 2) <= 94) {
2297                 $seg1 = substr($isbn, 0, 2);
2298         } elsif(substr($isbn, 0, 3) <= 995) {
2299                 $seg1 = substr($isbn, 0, 3);
2300         } elsif(substr($isbn, 0, 4) <= 9989) {
2301                 $seg1 = substr($isbn, 0, 4);
2302         } else {
2303                 $seg1 = substr($isbn, 0, 5);
2304         }
2305         my $x = substr($isbn, length($seg1));
2306         my $seg2;
2307         if(substr($x, 0, 2) <= 19) {
2308 #               if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2309                 $seg2 = substr($x, 0, 2);
2310         } elsif(substr($x, 0, 3) <= 699) {
2311                 $seg2 = substr($x, 0, 3);
2312         } elsif(substr($x, 0, 4) <= 8399) {
2313                 $seg2 = substr($x, 0, 4);
2314         } elsif(substr($x, 0, 5) <= 89999) {
2315                 $seg2 = substr($x, 0, 5);
2316         } elsif(substr($x, 0, 6) <= 9499999) {
2317                 $seg2 = substr($x, 0, 6);
2318         } else {
2319                 $seg2 = substr($x, 0, 7);
2320         }
2321         my $seg3=substr($x,length($seg2));
2322         $seg3=substr($seg3,0,length($seg3)-1) ;
2323         my $seg4 = substr($x, -1, 1);
2324         return "$seg1-$seg2-$seg3-$seg4";
2325 }
2326
2327
2328 END { }    # module clean-up code here (global destructor)
2329
2330 =back
2331
2332 =head1 AUTHOR
2333
2334 Koha Developement team <info@koha.org>
2335
2336 Paul POULAIN paul.poulain@free.fr
2337
2338 =cut
2339
2340 # $Id$
2341 # $Log$
2342 # Revision 1.129  2005/08/12 13:50:31  tipaul
2343 # removing useless sub declarations
2344 #
2345 # Revision 1.128  2005/08/11 16:12:47  tipaul
2346 # Playing with the zebra...
2347 #
2348 # * go to koha cvs home directory
2349 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
2350 # * put your zebra.cfg files here & create your database.
2351 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
2352 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
2353 #
2354 # NOTE :
2355 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
2356 # * deletion still not work
2357 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
2358 # in zebra.cfg :
2359 # recordId: (bib1,Local-number)
2360 # storeKeys:1
2361 #
2362 # in .abs file :
2363 # elm 090            Local-number            -
2364 # elm 090/?          Local-number            -
2365 # elm 090/?/9        Local-number            !:w
2366 #
2367 # (090$9 being the field mapped to biblio.biblionumber in Koha)
2368 #
2369 # Revision 1.127  2005/08/11 14:37:32  tipaul
2370 # * POD documenting
2371 # * removing useless subs
2372 # * removing some subs that are also elsewhere
2373 # * renaming all OLDxxx subs to REALxxx subs (should not change anything, as OLDxxx, as well as REAL, are supposed to be for Biblio.pm internal use only)
2374 #
2375 # Revision 1.126  2005/08/11 09:13:28  tipaul
2376 # just removing useless subs (a lot !!!) for code cleaning
2377 #
2378 # Revision 1.125  2005/08/11 09:00:07  tipaul
2379 # Ok guys, this time, it seems that item add and modif begin working as expected...
2380 # Still a lot of bugs to fix, of course
2381 #
2382 # Revision 1.124  2005/08/10 10:21:15  tipaul
2383 # continuing the road to zebra :
2384 # - the biblio add begins to work.
2385 # - the biblio modif begins to work.
2386 #
2387 # (still without doing anything on zebra)
2388 # (no new change in updatedatabase)
2389 #
2390 # Revision 1.123  2005/08/09 14:10:28  tipaul
2391 # 1st commit to go to zebra.
2392 # don't update your cvs if you want to have a working head...
2393 #
2394 # this commit contains :
2395 # * updater/updatedatabase : get rid with marc_* tables, but DON'T remove them. As a lot of things uses them, it would not be a good idea for instance to drop them. If you really want to play, you can rename them to test head without them but being still able to reintroduce them...
2396 # * Biblio.pm : modify MARCgetbiblio to find the raw marc record in biblioitems.marc field, not from marc_subfield_table, modify MARCfindframeworkcode to find frameworkcode in biblio.frameworkcode, modify some other subs to use biblio.biblionumber & get rid of bibid.
2397 # * other files : get rid of bibid and use biblionumber instead.
2398 #
2399 # What is broken :
2400 # * does not do anything on zebra yet.
2401 # * if you rename marc_subfield_table, you can't search anymore.
2402 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
2403 # * don't try to add a biblio, it would add data poorly... (don't try to delete either, it may work, but that would be a surprise ;-) )
2404 #
2405 # IMPORTANT NOTE : you need MARC::XML package (http://search.cpan.org/~esummers/MARC-XML-0.7/lib/MARC/File/XML.pm), that requires a recent version of MARC::Record
2406 # Updatedatabase stores the iso2709 data in biblioitems.marc field & an xml version in biblioitems.marcxml Not sure we will keep it when releasing the stable version, but I think it's a good idea to have something readable in sql, at least for development stage.
2407
2408 # tipaul cutted previous commit notes