rollback ... by accident I committed a rel_2_2 Biblio.pm
[koha.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 C4::Date;
25 use MARC::Record;
26 use MARC::File::USMARC;
27 use MARC::File::XML;
28 use ZOOM;
29 use vars qw($VERSION @ISA @EXPORT);
30
31 # set the version for version checking
32 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
33                 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
34
35 @ISA = qw(Exporter);
36
37 #
38 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
39 # as the old-style API and the NEW one are the only public functions.
40 #
41 @EXPORT = qw(
42   &newbiblio &newbiblioitem
43   &newsubject &newsubtitle &newitems 
44   
45   &modbiblio &checkitems &modbibitem
46   &modsubtitle &modsubject &modaddauthor &moditem
47   
48   &delitem &deletebiblioitem &delbiblio
49   
50   &getbiblio &bibdata &bibitems &bibitemdata 
51   &barcodes &ItemInfo &itemdata &itemissues &itemcount 
52   &getsubject &getaddauthor &getsubtitle
53   &getwebbiblioitems &getwebsites
54   &getbiblioitembybiblionumber
55   &getbiblioitem &getitemsbybiblioitem
56
57   &MARCfind_marc_from_kohafield
58   &MARCfind_frameworkcode
59   &find_biblioitemnumber
60   &MARCgettagslib
61
62   &NEWnewbiblio &NEWnewitem
63   &NEWmodbiblio &NEWmoditem
64   &NEWdelbiblio &NEWdelitem
65   &NEWmodbiblioframework
66
67   &MARCkoha2marcBiblio &MARCmarc2koha
68   &MARCkoha2marcItem &MARChtml2marc
69   &MARCgetbiblio &MARCgetitem
70   &XMLgetbiblio
71   
72   &FindDuplicate
73   &DisplayISBN
74
75   &z3950_extended_services
76   &set_service_options
77   
78   &get_item_from_barcode
79   &MARCfind_MARCbibid_from_oldbiblionumber
80
81 );
82
83 =head1 NAME
84
85 C4::Biblio - Acquisitions, Catalog Management Functions
86
87 =head1 SYNOPSIS
88
89 ( lot of changes for Koha 3.X)
90
91 Koha 1.2 and previous versions used a specific API to manage biblios. This API uses old-DB style parameters.
92 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, 
93 bibliosubject and bibliosubtitle where applicable).
94
95 In Koha 2.X, we introduced a MARC-DB.
96
97 In Koha 3.X, we removed this MARC-DB for search as we wanted to use Zebra as search system.
98
99 So in Koha 3.X, saving a record means :
100
101  - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items information.
102  - storing the "decoded information" in biblio/biblioitems/items as previously.
103  - using zebra to manage search & indexing on the MARC data.
104  
105  In Koha, there is a systempreference for "MARC=ON" or "MARC=OFF" :
106  
107  * MARC=ON : when MARC=ON, Koha uses a MARC::Record object (in sub parameters). Saving information in the DB means : 
108
109  - transform the MARC record into a hash
110  - add the raw MARC record into the hash
111  - store them & update Zebra
112  
113  * MARC=OFF : when MARC=OFF, Koha uses a hash object (in sub parameters). Saving information in the DB means :
114
115  - transform the hash into a MARC record
116  - add the raw marc record into the hash
117  - store them & update zebra
118  
119 That's why we need 3 types of subs :
120
121 =head2 REALxxx subs
122
123 all I<subs beginning by REAL> do the 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).
124
125 =head2 NEWxxx related subs
126
127 =over 4
128
129 all I<subs beginning by NEW> use MARC::Record as parameters. It's the API that MUST be used in the MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
130
131 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. They sometimes require another parameter.
132
133 =back
134
135 =head2 something_elsexxx related subs
136
137 =over 4
138
139 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 call REAL subs.
140
141 all subs require/use $dbh as 1st parameter and a hash as 2nd parameter.
142
143 =back
144
145 =head1 FUNCTIONS
146
147 =head2 z3950_extended_services
148
149 z3950_extended_services($serviceType,$serviceOptions,$record);
150
151         z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
152
153 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
154
155 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
156
157         action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
158
159 and maybe
160
161         recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
162         syntax => the record syntax (transfer syntax)
163         databaseName = Database from connection object
164
165         To set serviceOptions, call set_service_options($serviceType)
166
167 C<$record> the record, if one is needed for the service type
168
169         A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
170
171 =cut
172 sub z3950_extended_services {
173         my ($serviceType,$serviceOptions,$record) = @_;
174
175     my $Zconn = C4::Context->Zconn; 
176         # create a new package object
177         my $Zpackage = $Zconn->package();
178
179         # set our options
180         $Zpackage->option(action => $serviceOptions->{'action'});
181
182         if ($serviceOptions->{'databaseName'}) {
183                 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
184         }
185         if ($serviceOptions->{'recordIdNumber'}) {
186                 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
187         }
188         if ($serviceOptions->{'recordIdOpaque'}) {
189                 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
190         }
191
192         # this is an ILL request (Zebra doesn't support it)
193         #if ($serviceType eq 'itemorder') {
194         #   $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
195         #   $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
196         #   $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
197         #   $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
198         #}
199
200         if ($record) {
201                 my $xmlrecord = marc2xml($record);
202                 $Zpackage->option(record => $xmlrecord);
203                 if ($serviceOptions->{'syntax'}) {
204                         $Zpackage->option(syntax => $serviceOptions->{'syntax'});
205                 }
206         }
207
208         # send the request, handle any exception encountered
209         eval { $Zpackage->send($serviceType) };
210                 if ($@ && $@->isa("ZOOM::Exception")) {
211                         print "Oops!  ", $@->message(), "\n";
212                         return $@->code();
213                 }
214         # free up package resources
215         $Zpackage->destroy();
216 }
217
218 =head2 set_service_options
219
220 my $serviceOptions = set_service_options($serviceType);
221
222 C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
223
224 Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
225
226 =cut
227
228 sub set_service_options {
229         my ($serviceType) = @_;
230         my $serviceOptions;
231
232         if ($serviceType eq 'update') {
233                 $serviceOptions->{ 'action' } = 'specialUpdate';
234
235         # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
236         #       $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
237         }
238
239         if ($serviceType eq 'commit') {
240         # nothing to do
241
242         }
243         if ($serviceType eq 'create') {
244         # nothing to do
245         }
246         if ($serviceType eq 'drop') {
247                 die "ERROR: 'drop' not currently supported (by Zebra)";
248         }
249         return $serviceOptions;
250 }
251
252 =head2 marc2xml
253
254 my $xmlrecord = marc2xml($record);
255
256 Convert from MARC to XML. Note that MARC::File::XML will automatically encode from MARC-8 to UTF-8 as of version .8
257
258 C<$record> a MARC record
259
260 =cut
261
262 sub marc2xml {
263         my ($record) = @_;
264         my $xmlrecord;
265         eval { $xmlrecord=$record->as_xml() };
266         #TODO: better error handling here
267         if ($@){
268                 warn "ERROR: I suspect a badly formatted MARC record";
269         }
270         return $xmlrecord;
271 }
272
273 =head2 MARCgettagslib
274
275 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
276
277 =over 4
278
279 2nd param is 1 for liblibrarian and 0 for libopac
280 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
281
282 returns a hash with all values for all fields and subfields for a given MARC framework :
283         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
284                     ->{tab}        = "";            # XXX
285                     ->{mandatory}  = $mandatory;
286                     ->{repeatable} = $repeatable;
287                     ->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
288                                  ->{tab}              = $tab;
289                                  ->{mandatory}        = $mandatory;
290                                  ->{repeatable}       = $repeatable;
291                                  ->{authorised_value} = $authorised_value;
292                                  ->{authtypecode}     = $authtypecode;
293                                  ->{value_builder}    = $value_builder;
294                                  ->{kohafield}        = $kohafield;
295                                  ->{seealso}          = $seealso;
296                                  ->{hidden}           = $hidden;
297                                  ->{isurl}            = $isurl;
298                                  ->{link}            = $link;
299
300 =back
301
302 =cut
303
304 sub MARCgettagslib {
305     my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
306     $frameworkcode = "" unless $frameworkcode;
307     $forlibrarian = 1 unless $forlibrarian;
308     my $sth;
309     my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
310
311     # check that framework exists
312     $sth =
313       $dbh->prepare(
314         "select count(*) from marc_tag_structure where frameworkcode=?");
315     $sth->execute($frameworkcode);
316     my ($total) = $sth->fetchrow;
317     $frameworkcode = "" unless ( $total > 0 );
318     $sth =
319       $dbh->prepare(
320 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
321     );
322     $sth->execute($frameworkcode);
323     my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
324
325     while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
326         $res->{$tag}->{lib}        = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
327         $res->{$tag}->{tab}        = "";            # XXX
328         $res->{$tag}->{mandatory}  = $mandatory;
329         $res->{$tag}->{repeatable} = $repeatable;
330     }
331
332     $sth =
333       $dbh->prepare(
334 "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"
335     );
336     $sth->execute($frameworkcode);
337
338     my $subfield;
339     my $authorised_value;
340     my $authtypecode;
341     my $value_builder;
342     my $kohafield;
343     my $seealso;
344     my $hidden;
345     my $isurl;
346         my $link;
347
348     while (
349         ( $tag,         $subfield,   $liblibrarian,   , $libopac,      $tab,
350         $mandatory,     $repeatable, $authorised_value, $authtypecode,
351         $value_builder, $kohafield,  $seealso,          $hidden,
352         $isurl,                 $link )
353         = $sth->fetchrow
354       )
355     {
356         $res->{$tag}->{$subfield}->{lib}              = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
357         $res->{$tag}->{$subfield}->{tab}              = $tab;
358         $res->{$tag}->{$subfield}->{mandatory}        = $mandatory;
359         $res->{$tag}->{$subfield}->{repeatable}       = $repeatable;
360         $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
361         $res->{$tag}->{$subfield}->{authtypecode}     = $authtypecode;
362         $res->{$tag}->{$subfield}->{value_builder}    = $value_builder;
363         $res->{$tag}->{$subfield}->{kohafield}        = $kohafield;
364         $res->{$tag}->{$subfield}->{seealso}          = $seealso;
365         $res->{$tag}->{$subfield}->{hidden}           = $hidden;
366         $res->{$tag}->{$subfield}->{isurl}            = $isurl;
367         $res->{$tag}->{$subfield}->{link}            = $link;
368     }
369     return $res;
370 }
371
372 =head2 MARCfind_marc_from_kohafield
373
374 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
375
376 =over 4
377
378 finds MARC tag and subfield for a given kohafield
379 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
380
381 =back
382
383 =cut
384
385 sub MARCfind_marc_from_kohafield {
386     my ( $dbh, $kohafield,$frameworkcode ) = @_;
387     return 0, 0 unless $kohafield;
388     $frameworkcode='' unless $frameworkcode;
389         my $relations = C4::Context->marcfromkohafield;
390         return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
391 }
392
393 =head2 MARCgetbiblio
394
395 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
396
397 =over 4
398
399 Returns a MARC::Record for the biblio $biblionumber.
400
401 =cut
402
403 sub MARCgetbiblio {
404
405     # Returns MARC::Record of the biblio passed in parameter.
406     my ( $dbh, $biblionumber ) = @_;
407         my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
408         $sth->execute($biblionumber);
409         my ($marc) = $sth->fetchrow;
410         my $record = MARC::Record::new_from_usmarc($marc);
411     return $record;
412 }
413
414 =head2 XMLgetbiblio
415
416 $XML = &XMLgetbiblio($dbh,$biblionumber);
417
418 =over 4
419
420 Returns a raw XML for the biblio $biblionumber.
421
422 =cut
423
424 sub XMLgetbiblio {
425
426     # Returns MARC::Record of the biblio passed in parameter.
427     my ( $dbh, $biblionumber ) = @_;
428         my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
429         $sth->execute($biblionumber);
430         my ($XML,$marc) = $sth->fetchrow;
431 #       my $record =MARC::Record::new_from_usmarc($marc);
432 #       warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
433     return $XML;
434 }
435
436 =head2 MARCgetitem
437
438 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
439
440 =over 4
441
442 Returns a MARC::Record with all items of biblio # $biblionumber
443
444 =back
445
446 =cut
447
448 sub MARCgetitem {
449
450     my ( $dbh, $biblionumber, $itemnumber ) = @_;
451         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
452         # get the complete MARC record
453         my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
454         $sth->execute($biblionumber);
455         my ($rawmarc) = $sth->fetchrow;
456         my $record = MARC::File::USMARC::decode($rawmarc);
457         # now, find the relevant itemnumber
458         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
459         # prepare the new item record
460         my $itemrecord = MARC::Record->new();
461         # parse all fields fields from the complete record
462         foreach ($record->field($itemnumberfield)) {
463                 # when the item field is found, save it
464                 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
465                         $itemrecord->append_fields($_);
466                 }
467         }
468
469     return $itemrecord;
470 }
471
472 =head2 find_biblioitemnumber
473
474 my $biblioitemnumber = find_biblioitemnumber($dbh,$biblionumber);
475
476 =over 4
477
478 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
479 This sub is useless when MARC=OFF
480
481 =back
482
483 =cut
484 sub find_biblioitemnumber {
485         my ( $dbh, $biblionumber ) = @_;
486         my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
487         $sth->execute($biblionumber);
488         my ($biblioitemnumber) = $sth->fetchrow;
489         return $biblioitemnumber;
490 }
491
492 =head2 MARCfind_frameworkcode
493
494 my $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
495
496 =over 4
497
498 returns the framework of a given biblio
499
500 =back
501
502 =cut
503
504 sub MARCfind_frameworkcode {
505         my ( $dbh, $biblionumber ) = @_;
506         my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
507         $sth->execute($biblionumber);
508         my ($frameworkcode) = $sth->fetchrow;
509         return $frameworkcode;
510 }
511
512 =head2 MARCkoha2marcBiblio
513
514 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
515
516 =over 4
517
518 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
519 all entries of the hash are transformed into their matching MARC field/subfield.
520
521 =back
522
523 =cut
524
525 sub MARCkoha2marcBiblio {
526
527         # this function builds partial MARC::Record from the old koha-DB fields
528         my ( $dbh, $bibliohash ) = @_;
529         # we don't have biblio entries in the hash, so we add them first
530         my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
531         $sth->execute($bibliohash->{biblionumber});
532         my $biblio = $sth->fetchrow_hashref;
533         foreach (keys %$biblio) {
534                 $bibliohash->{$_}=$biblio->{$_};
535         }
536         $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
537         my $record = MARC::Record->new();
538         foreach ( keys %$bibliohash ) {
539                 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
540                 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
541         }
542
543         # other fields => additional authors, subjects, subtitles
544         my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
545         $sth2->execute($bibliohash->{biblionumber});
546         while ( my $row = $sth2->fetchrow_hashref ) {
547                 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
548         }
549         $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
550         $sth2->execute($bibliohash->{biblionumber});
551         while ( my $row = $sth2->fetchrow_hashref ) {
552                 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
553         }
554         $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
555         $sth2->execute($bibliohash->{biblionumber});
556         while ( my $row = $sth2->fetchrow_hashref ) {
557                 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
558         }
559         
560         return $record;
561 }
562
563 =head2 MARCkoha2marcItem
564
565 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
566
567 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
568 all entries of the hash are transformed into their matching MARC field/subfield.
569
570 =over 4
571
572 =back
573
574 =cut
575
576 sub MARCkoha2marcItem {
577
578     # this function builds partial MARC::Record from the old koha-DB fields
579     my ( $dbh, $item ) = @_;
580
581     #    my $dbh=&C4Connect;
582     my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
583     my $record = MARC::Record->new();
584
585         foreach( keys %$item ) {
586                 if ( $item->{$_} ) {
587                         &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
588                                 $item->{$_},'' );
589                 }
590         }
591     return $record;
592 }
593
594 =head2 MARCkoha2marcOnefield
595
596 =over 4
597
598 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
599
600 =back
601
602 =cut
603
604 sub MARCkoha2marcOnefield {
605     my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
606     my $tagfield;
607     my $tagsubfield;
608     $sth->execute($frameworkcode,$kohafieldname);
609     if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
610         if ( $record->field($tagfield) ) {
611             my $tag = $record->field($tagfield);
612             if ($tag) {
613                 $tag->add_subfields( $tagsubfield, $value );
614                 $record->delete_field($tag);
615                 $record->add_fields($tag);
616             }
617         }
618         else {
619             $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
620         }
621     }
622     return $record;
623 }
624
625 =head2 MARChtml2marc
626
627 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
628
629 =over 4
630
631 transforms the parameters (coming from HTML form) into a MARC::Record
632 parameters with r are references to arrays.
633
634 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
635
636 =back
637
638 =cut
639
640 sub MARChtml2marc {
641         my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
642         my $prevtag = -1;
643         my $record = MARC::Record->new();
644 #       my %subfieldlist=();
645         my $prevvalue; # if tag <10
646         my $field; # if tag >=10
647         for (my $i=0; $i< @$rtags; $i++) {
648                 next unless @$rvalues[$i];
649                 # rebuild MARC::Record
650 #                       warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
651                 if (@$rtags[$i] ne $prevtag) {
652                         if ($prevtag < 10) {
653                                 if ($prevvalue) {
654                                         if ($prevtag ne '000') {
655                                                 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
656                                         } else {
657                                                 $record->leader($prevvalue);
658                                         }
659                                 }
660                         } else {
661                                 if ($field) {
662                                         $record->add_fields($field);
663                                 }
664                         }
665                         $indicators{@$rtags[$i]}.='  ';
666                         if (@$rtags[$i] <10) {
667                                 $prevvalue= @$rvalues[$i];
668                                 undef $field;
669                         } else {
670                                 undef $prevvalue;
671                                 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
672 #                       warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
673                         }
674                         $prevtag = @$rtags[$i];
675                 } else {
676                         if (@$rtags[$i] <10) {
677                                 $prevvalue=@$rvalues[$i];
678                         } else {
679                                 if (length(@$rvalues[$i])>0) {
680                                         $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
681 #                       warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
682                                 }
683                         }
684                         $prevtag= @$rtags[$i];
685                 }
686         }
687         # the last has not been included inside the loop... do it now !
688         $record->add_fields($field) if $field;
689 #       warn "HTML2MARC=".$record->as_formatted;
690         return $record;
691 }
692
693
694 =head2 MARCmarc2koha
695
696 $hash = &MARCmarc2koha($dbh,$MARCRecord);
697
698 =over 4
699
700 builds a hash with old-db datas from a MARC::Record
701
702 =back
703
704 =cut
705
706 sub MARCmarc2koha {
707         my ($dbh,$record,$frameworkcode) = @_;
708         my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
709         my $result;  
710         my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
711         $sth2->execute;
712         my $field;
713         while (($field)=$sth2->fetchrow) {
714 #               warn "biblio.".$field;
715                 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
716         }
717         $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
718         $sth2->execute;
719         while (($field)=$sth2->fetchrow) {
720                 if ($field eq 'notes') { $field = 'bnotes'; }
721 #               warn "biblioitems".$field;
722                 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
723         }
724         $sth2=$dbh->prepare("SHOW COLUMNS from items");
725         $sth2->execute;
726         while (($field)=$sth2->fetchrow) {
727 #               warn "items".$field;
728                 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
729         }
730         # additional authors : specific
731         $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
732         $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
733 # modify copyrightdate to keep only the 1st year found
734         my $temp = $result->{'copyrightdate'};
735         if ($temp){
736                 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
737                 if ($1>0) {
738                         $result->{'copyrightdate'} = $1;
739                 } else { # if no cYYYY, get the 1st date.
740                         $temp =~ m/(\d\d\d\d)/;
741                         $result->{'copyrightdate'} = $1;
742                 }
743         }
744 # modify publicationyear to keep only the 1st year found
745         $temp = $result->{'publicationyear'};
746         $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
747         if ($1>0) {
748                 $result->{'publicationyear'} = $1;
749         } else { # if no cYYYY, get the 1st date.
750                 $temp =~ m/(\d\d\d\d)/;
751                 $result->{'publicationyear'} = $1;
752         }
753         return $result;
754 }
755
756 sub MARCmarc2kohaOneField {
757
758 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
759     my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
760     #    warn "kohatable / $kohafield / $result / ";
761     my $res = "";
762     my $tagfield;
763     my $subfield;
764     ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
765     foreach my $field ( $record->field($tagfield) ) {
766                 if ($field->tag()<10) {
767                         if ($result->{$kohafield}) {
768                                 # Reverse array filled with elements from repeated subfields 
769                                 # from first to last to avoid last to first concatenation of 
770                                 # elements in Koha DB.  -- thd.
771                                 $result->{$kohafield} .= " | ".reverse($field->data());
772                         } else {
773                                 $result->{$kohafield} = $field->data();
774                         }
775                 } else {
776                         if ( $field->subfields ) {
777                                 my @subfields = $field->subfields();
778                                 foreach my $subfieldcount ( 0 .. $#subfields ) {
779                                         if ($subfields[$subfieldcount][0] eq $subfield) {
780                                                 if ( $result->{$kohafield} ) {
781                                                         $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
782                                                 }
783                                                 else {
784                                                         $result->{$kohafield} = $subfields[$subfieldcount][1];
785                                                 }
786                                         }
787                                 }
788                         }
789                 }
790     }
791 #       warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
792     return $result;
793 }
794
795 =head2 NEWnewbibilio
796
797 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
798
799 =over 4
800
801 creates a biblio from a MARC::Record.
802
803 =back
804
805 =cut
806
807 sub NEWnewbiblio {
808     my ( $dbh,$record,$frameworkcode ) = @_;
809     my $biblionumber;
810     my $biblioitemnumber;
811     my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
812         $olddata->{frameworkcode} = $frameworkcode;
813     $biblionumber = REALnewbiblio( $dbh, $olddata );
814         $olddata->{biblionumber} = $biblionumber;
815         # add biblionumber into the MARC record (it's the ID for zebra)
816         my ( $tagfield, $tagsubfield ) =
817                                         MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
818         # create the field
819         my $newfield;
820         if ($tagfield<10) {
821                 $newfield = MARC::Field->new(
822                         $tagfield, $biblionumber,
823                 );
824         } else {
825                 $newfield = MARC::Field->new(
826                         $tagfield, '', '', "$tagsubfield" => $biblionumber,
827                 );
828         }
829         # drop old field (just in case it already exist and create new one...
830         my $old_field = $record->field($tagfield);
831         $record->delete_field($old_field);
832         $record->add_fields($newfield);
833
834         #create the marc entry, that stores the rax marc record in Koha 3.0
835         $olddata->{marc} = $record->as_usmarc();
836         $olddata->{marcxml} = $record->as_xml();
837         # and create biblioitem, that's all folks !
838     $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
839
840     # search subtiles, addiauthors and subjects
841     ( $tagfield, $tagsubfield ) =
842       MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
843     my @addiauthfields = $record->field($tagfield);
844     foreach my $addiauthfield (@addiauthfields) {
845         my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
846         foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
847             REALmodaddauthor( $dbh, $biblionumber,
848                 $addiauthsubfields[$subfieldcount] );
849         }
850     }
851     ( $tagfield, $tagsubfield ) =
852       MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
853     my @subtitlefields = $record->field($tagfield);
854     foreach my $subtitlefield (@subtitlefields) {
855         my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
856         foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
857             REALnewsubtitle( $dbh, $biblionumber,
858                 $subtitlesubfields[$subfieldcount] );
859         }
860     }
861     ( $tagfield, $tagsubfield ) =
862       MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
863     my @subj = $record->field($tagfield);
864     my @subjects;
865     foreach my $subject (@subj) {
866         my @subjsubfield = $subject->subfield($tagsubfield);
867         foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
868             push @subjects, $subjsubfield[$subfieldcount];
869         }
870     }
871     REALmodsubject( $dbh, $biblionumber, 1, @subjects );
872     return ( $biblionumber, $biblioitemnumber );
873 }
874
875 =head2 NEWmodbilbioframework
876
877 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
878
879 =over 4
880
881 modify the framework of a biblio
882
883 =back
884
885 =cut
886
887 sub NEWmodbiblioframework {
888         my ($dbh,$biblionumber,$frameworkcode) =@_;
889         my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
890         $sth->execute($frameworkcode,$biblionumber);
891         return 1;
892 }
893
894 =head2 NEWmodbiblio
895
896 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
897
898 =over 4
899
900 modify a biblio (MARC=ON)
901
902 =back
903
904 =cut
905
906 sub NEWmodbiblio {
907         my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
908         $frameworkcode="" unless $frameworkcode;
909 #       &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
910         my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
911         
912         $oldbiblio->{frameworkcode} = $frameworkcode;
913         #create the marc entry, that stores the rax marc record in Koha 3.0
914         $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
915         $oldbiblio->{marc} = $record->as_usmarc();
916         $oldbiblio->{marcxml} = $record->as_xml();
917         warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
918         REALmodbiblio($dbh,$oldbiblio);
919         REALmodbiblioitem($dbh,$oldbiblio);
920         # now, modify addi authors, subject, addititles.
921         my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
922         my @addiauthfields = $record->field($tagfield);
923         foreach my $addiauthfield (@addiauthfields) {
924                 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
925                 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
926                 foreach my $subfieldcount (0..$#addiauthsubfields) {
927                         REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
928                 }
929         }
930         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
931         my @subtitlefields = $record->field($tagfield);
932         foreach my $subtitlefield (@subtitlefields) {
933                 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
934                 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
935                 # between 2 modifs
936                 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
937                 foreach my $subfieldcount (0..$#subtitlesubfields) {
938                         foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
939                                 REALnewsubtitle($dbh,$biblionumber,$subtit);
940                         }
941                 }
942         }
943         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
944         my @subj = $record->field($tagfield);
945         my @subjects;
946         foreach my $subject (@subj) {
947                 my @subjsubfield = $subject->subfield($tagsubfield);
948                 foreach my $subfieldcount (0..$#subjsubfield) {
949                         push @subjects,$subjsubfield[$subfieldcount];
950                 }
951         }
952         REALmodsubject($dbh,$biblionumber,1,@subjects);
953         return 1;
954 }
955
956 =head2 NEWmodbilbioframework
957
958 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
959
960 =over 4
961
962 delete a biblio
963
964 =back
965
966 =cut
967
968 sub NEWdelbiblio {
969     my ( $dbh, $bibid ) = @_;
970     my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
971     &REALdelbiblio( $dbh, $biblio );
972     my $sth =
973       $dbh->prepare(
974         "select biblioitemnumber from biblioitems where biblionumber=?");
975     $sth->execute($biblio);
976     while ( my ($biblioitemnumber) = $sth->fetchrow ) {
977         REALdelbiblioitem( $dbh, $biblioitemnumber );
978     }
979     &MARCdelbiblio( $dbh, $bibid, 0 );
980 }
981
982 =head2 NEWnewitem
983
984 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
985
986 =over 4
987
988 creates an item from a MARC::Record
989
990 =back
991
992 =cut
993
994 sub NEWnewitem {
995     my ( $dbh,$record,$biblionumber,$biblioitemnumber ) = @_;
996
997     # add item in old-DB
998         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
999     my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
1000     # needs old biblionumber and biblioitemnumber
1001     $item->{'biblionumber'} = $biblionumber;
1002     $item->{'biblioitemnumber'}=$biblioitemnumber;
1003     $item->{marc} = $record->as_usmarc();
1004     #warn $item->{marc};
1005     my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
1006         return $itemnumber;
1007 }
1008
1009
1010 =head2 NEWmoditem
1011
1012 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1013
1014 =over 4
1015
1016 Modify an item
1017
1018 =back
1019
1020 =cut
1021
1022 sub NEWmoditem {
1023     my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1024     
1025         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1026     my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1027         # add MARC record
1028         $olditem->{marc} = $record->as_usmarc();
1029         $olditem->{biblionumber} = $biblionumber;
1030         $olditem->{biblioitemnumber} = $biblioitemnumber;
1031         # and modify item
1032     REALmoditem( $dbh, $olditem );
1033 }
1034
1035
1036 =head2 NEWdelitem
1037
1038 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1039
1040 =over 4
1041
1042 delete an item
1043
1044 =back
1045
1046 =cut
1047
1048 sub NEWdelitem {
1049     my ( $dbh, $bibid, $itemnumber ) = @_;
1050     my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1051     &REALdelitem( $dbh, $itemnumber );
1052     &MARCdelitem( $dbh, $bibid, $itemnumber );
1053 }
1054
1055
1056 =head2 REALnewbiblio
1057
1058 $biblionumber = REALnewbiblio($dbh,$biblio);
1059
1060 =over 4
1061
1062 adds a record in biblio table. Datas are in the hash $biblio.
1063
1064 =back
1065
1066 =cut
1067
1068 sub REALnewbiblio {
1069     my ( $dbh, $biblio ) = @_;
1070
1071         $dbh->do('lock tables biblio WRITE');
1072     my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1073     $sth->execute;
1074     my $data   = $sth->fetchrow_arrayref;
1075     my $bibnum = $$data[0] + 1;
1076     my $series = 0;
1077
1078     if ( $biblio->{'seriestitle'} ) { $series = 1 }
1079     $sth->finish;
1080     $sth =
1081       $dbh->prepare("insert into biblio set     biblionumber=?, title=?,                author=?,       copyrightdate=?,
1082                                                                                         serial=?,               seriestitle=?,  notes=?,        abstract=?,
1083                                                                                         unititle=?"
1084     );
1085     $sth->execute(
1086         $bibnum,             $biblio->{'title'},
1087         $biblio->{'author'}, $biblio->{'copyrightdate'},
1088         $biblio->{'serial'},             $biblio->{'seriestitle'},
1089         $biblio->{'notes'},  $biblio->{'abstract'},
1090                 $biblio->{'unititle'}
1091     );
1092
1093     $sth->finish;
1094         $dbh->do('unlock tables');
1095     return ($bibnum);
1096 }
1097
1098 =head2 REALmodbiblio
1099
1100 $biblionumber = REALmodbiblio($dbh,$biblio);
1101
1102 =over 4
1103
1104 modify a record in biblio table. Datas are in the hash $biblio.
1105
1106 =back
1107
1108 =cut
1109
1110 sub REALmodbiblio {
1111     my ( $dbh, $biblio ) = @_;
1112     my $sth = $dbh->prepare("Update biblio set  title=?,                author=?,       abstract=?,     copyrightdate=?,
1113                                                                                                 seriestitle=?,  serial=?,       unititle=?,     notes=?,        frameworkcode=? 
1114                                                                                         where biblionumber = ?"
1115     );
1116     $sth->execute(
1117                 $biblio->{'title'},       $biblio->{'author'},
1118                 $biblio->{'abstract'},    $biblio->{'copyrightdate'},
1119                 $biblio->{'seriestitle'}, $biblio->{'serial'},
1120                 $biblio->{'unititle'},    $biblio->{'notes'},
1121                 $biblio->{frameworkcode},
1122                 $biblio->{'biblionumber'}
1123     );
1124         $sth->finish;
1125         return ( $biblio->{'biblionumber'} );
1126 }    # sub modbiblio
1127
1128 =head2 REALmodsubtitle
1129
1130 REALmodsubtitle($dbh,$bibnum,$subtitle);
1131
1132 =over 4
1133
1134 modify subtitles in bibliosubtitle table.
1135
1136 =back
1137
1138 =cut
1139
1140 sub REALmodsubtitle {
1141     my ( $dbh, $bibnum, $subtitle ) = @_;
1142     my $sth =
1143       $dbh->prepare(
1144         "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1145     $sth->execute( $subtitle, $bibnum );
1146     $sth->finish;
1147 }    # sub modsubtitle
1148
1149 =head2 REALmodaddauthor
1150
1151 REALmodaddauthor($dbh,$bibnum,$author);
1152
1153 =over 4
1154
1155 adds or modify additional authors
1156 NOTE :  Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1157
1158 =back
1159
1160 =cut
1161
1162 sub REALmodaddauthor {
1163     my ( $dbh, $bibnum, @authors ) = @_;
1164
1165     #    my $dbh   = C4Connect;
1166     my $sth =
1167       $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1168
1169     $sth->execute($bibnum);
1170     $sth->finish;
1171     foreach my $author (@authors) {
1172         if ( $author ne '' ) {
1173             $sth =
1174               $dbh->prepare(
1175                 "Insert into additionalauthors set author = ?, biblionumber = ?"
1176             );
1177
1178             $sth->execute( $author, $bibnum );
1179
1180             $sth->finish;
1181         }    # if
1182     }
1183 }    # sub modaddauthor
1184
1185 =head2 REALmodsubject
1186
1187 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1188
1189 =over 4
1190
1191 modify/adds subjects
1192
1193 =back
1194
1195 =cut
1196 sub REALmodsubject {
1197     my ( $dbh, $bibnum, $force, @subject ) = @_;
1198
1199     #  my $dbh   = C4Connect;
1200     my $count = @subject;
1201     my $error="";
1202     for ( my $i = 0 ; $i < $count ; $i++ ) {
1203         $subject[$i] =~ s/^ //g;
1204         $subject[$i] =~ s/ $//g;
1205         my $sth =
1206           $dbh->prepare(
1207 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1208         );
1209         $sth->execute( $subject[$i] );
1210
1211         if ( my $data = $sth->fetchrow_hashref ) {
1212         }
1213         else {
1214             if ( $force eq $subject[$i] || $force == 1 ) {
1215
1216                 # subject not in aut, chosen to force anway
1217                 # so insert into cataloguentry so its in auth file
1218                 my $sth2 =
1219                   $dbh->prepare(
1220 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1221                 );
1222
1223                 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1224                 $sth2->finish;
1225             }
1226             else {
1227                 $error =
1228                   "$subject[$i]\n does not exist in the subject authority file";
1229                 my $sth2 =
1230                   $dbh->prepare(
1231 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1232                 );
1233                 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1234                     "% $subject[$i]" );
1235                 while ( my $data = $sth2->fetchrow_hashref ) {
1236                     $error .= "<br>$data->{'catalogueentry'}";
1237                 }    # while
1238                 $sth2->finish;
1239             }    # else
1240         }    # else
1241         $sth->finish;
1242     }    # else
1243     if ($error eq '') {
1244         my $sth =
1245           $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1246         $sth->execute($bibnum);
1247         $sth->finish;
1248         $sth =
1249           $dbh->prepare(
1250             "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1251         my $query;
1252         foreach $query (@subject) {
1253             $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1254         }    # foreach
1255         $sth->finish;
1256     }    # if
1257
1258     #  $dbh->disconnect;
1259     return ($error);
1260 }    # sub modsubject
1261
1262 =head2 REALmodbiblioitem
1263
1264 REALmodbiblioitem($dbh, $biblioitem);
1265
1266 =over 4
1267
1268 modify a biblioitem
1269
1270 =back
1271
1272 =cut
1273 sub REALmodbiblioitem {
1274     my ( $dbh, $biblioitem ) = @_;
1275     my $query;
1276
1277     my $sth = $dbh->prepare("update biblioitems set number=?,volume=?,                  volumedate=?,           lccn=?,
1278                                                                                 itemtype=?,                     url=?,                          isbn=?,                         issn=?,
1279                                                                                 publishercode=?,        publicationyear=?,      classification=?,       dewey=?,
1280                                                                                 subclass=?,                     illus=?,                        pages=?,                        volumeddesc=?,
1281                                                                                 notes=?,                        size=?,                         place=?,                        marc=?,
1282                                                                                 marcxml=?
1283                                                         where biblioitemnumber=?");
1284         $sth->execute(  $biblioitem->{number},                  $biblioitem->{volume},  $biblioitem->{volumedate},      $biblioitem->{lccn},
1285                                         $biblioitem->{itemtype},                $biblioitem->{url},             $biblioitem->{isbn},    $biblioitem->{issn},
1286                                 $biblioitem->{publishercode},   $biblioitem->{publicationyear}, $biblioitem->{classification},  $biblioitem->{dewey},
1287                                 $biblioitem->{subclass},                $biblioitem->{illus},           $biblioitem->{pages},   $biblioitem->{volumeddesc},
1288                                 $biblioitem->{bnotes},                  $biblioitem->{size},            $biblioitem->{place},   $biblioitem->{marc},
1289                                         $biblioitem->{marcxml},                 $biblioitem->{biblioitemnumber});
1290
1291         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1292
1293         z3950_extended_services('update',set_service_options('update'),$record);
1294
1295
1296 #       warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1297 }    # sub modbibitem
1298
1299 =head2 REALnewbiblioitem
1300
1301 REALnewbiblioitem($dbh,$biblioitem);
1302
1303 =over 4
1304
1305 adds a biblioitem ($biblioitem is a hash with the values)
1306
1307 =back
1308
1309 =cut
1310
1311 sub REALnewbiblioitem {
1312         my ( $dbh, $biblioitem ) = @_;
1313
1314         $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1315         my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1316         my $data;
1317         my $biblioitemnumber;
1318
1319         $sth->execute;
1320         $data       = $sth->fetchrow_arrayref;
1321         $biblioitemnumber = $$data[0] + 1;
1322         
1323         # Insert biblioitemnumber in MARC record, we need it to manage items later...
1324         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1325         my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1326         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1327         my $field=$record->field($biblioitemnumberfield);
1328         $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1329         $biblioitem->{marc} = $record->as_usmarc();
1330         $biblioitem->{marcxml} = $record->as_xml();
1331
1332         $sth = $dbh->prepare( "insert into biblioitems set
1333                                                                         biblioitemnumber = ?,           biblionumber     = ?,
1334                                                                         volume           = ?,                   number           = ?,
1335                                                                         classification  = ?,                    itemtype         = ?,
1336                                                                         url              = ?,                           isbn             = ?,
1337                                                                         issn             = ?,                           dewey            = ?,
1338                                                                         subclass         = ?,                           publicationyear  = ?,
1339                                                                         publishercode    = ?,           volumedate       = ?,
1340                                                                         volumeddesc      = ?,           illus            = ?,
1341                                                                         pages            = ?,                           notes            = ?,
1342                                                                         size             = ?,                           lccn             = ?,
1343                                                                         marc             = ?,                           place            = ?,
1344                                                                         marcxml          = ?"
1345         );
1346         $sth->execute(
1347                 $biblioitemnumber,               $biblioitem->{'biblionumber'},
1348                 $biblioitem->{'volume'},         $biblioitem->{'number'},
1349                 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1350                 $biblioitem->{'url'},            $biblioitem->{'isbn'},
1351                 $biblioitem->{'issn'},           $biblioitem->{'dewey'},
1352                 $biblioitem->{'subclass'},       $biblioitem->{'publicationyear'},
1353                 $biblioitem->{'publishercode'},  $biblioitem->{'volumedate'},
1354                 $biblioitem->{'volumeddesc'},    $biblioitem->{'illus'},
1355                 $biblioitem->{'pages'},          $biblioitem->{'bnotes'},
1356                 $biblioitem->{'size'},           $biblioitem->{'lccn'},
1357                 $biblioitem->{'marc'},           $biblioitem->{'place'},
1358                 $biblioitem->{marcxml},
1359         );
1360         $dbh->do("unlock tables");
1361         z3950_extended_services('update',set_service_options('update'),$record);
1362         return ($biblioitemnumber);
1363 }
1364
1365 =head2 REALnewsubtitle
1366
1367 REALnewsubtitle($dbh,$bibnum,$subtitle);
1368
1369 =over 4
1370
1371 create a new subtitle
1372
1373 =back
1374
1375 =cut
1376 sub REALnewsubtitle {
1377     my ( $dbh, $bibnum, $subtitle ) = @_;
1378     my $sth =
1379       $dbh->prepare(
1380         "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1381     $sth->execute( $bibnum, $subtitle ) if $subtitle;
1382     $sth->finish;
1383 }
1384
1385 =head2 REALnewitems
1386
1387 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1388
1389 =over 4
1390
1391 create a item. $item is a hash and $barcode the barcode.
1392
1393 =back
1394
1395 =cut
1396
1397 sub REALnewitems {
1398     my ( $dbh, $item, $barcode ) = @_;
1399
1400 #       warn "OLDNEWITEMS";
1401         
1402         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1403     my $sth = $dbh->prepare("Select max(itemnumber) from items");
1404     my $data;
1405     my $itemnumber;
1406     my $error = "";
1407     $sth->execute;
1408     $data       = $sth->fetchrow_hashref;
1409     $itemnumber = $data->{'max(itemnumber)'} + 1;
1410
1411 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1412     if ( $item->{'loan'} ) {
1413         $item->{'notforloan'} = $item->{'loan'};
1414     }
1415         $item->{'biblioitemnumber'} = 1;
1416     # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1417     if ( $item->{'dateaccessioned'} ) {
1418         $sth = $dbh->prepare( "Insert into items set
1419                                                         itemnumber           = ?,                       biblionumber         = ?,
1420                                                         multivolumepart      = ?,
1421                                                         biblioitemnumber     = ?,                       barcode              = ?,
1422                                                         booksellerid         = ?,                       dateaccessioned      = ?,
1423                                                         homebranch           = ?,                       holdingbranch        = ?,
1424                                                         price                = ?,                       replacementprice     = ?,
1425                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1426                                                         multivolume                     = ?,                    stack                           = ?,
1427                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1428                                                         paidfor                         = ?,                    itemnotes            = ?,
1429                                                         itemcallnumber  =?,                                                     notforloan = ?,
1430                                                         location = ?
1431                                                         "
1432         );
1433         $sth->execute(
1434                         $itemnumber,                            $item->{'biblionumber'},
1435                         $item->{'multivolumepart'},
1436                         $item->{'biblioitemnumber'},$item->{barcode},
1437                         $item->{'booksellerid'},        $item->{'dateaccessioned'},
1438                         $item->{'homebranch'},          $item->{'holdingbranch'},
1439                         $item->{'price'},                       $item->{'replacementprice'},
1440                         $item->{multivolume},           $item->{stack},
1441                         $item->{itemlost},                      $item->{wthdrawn},
1442                         $item->{paidfor},                       $item->{'itemnotes'},
1443                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1444                         $item->{'location'}
1445         );
1446                 if ( defined $sth->errstr ) {
1447                         $error .= $sth->errstr;
1448                 }
1449     }
1450     else {
1451         $sth = $dbh->prepare( "Insert into items set
1452                                                         itemnumber           = ?,                       biblionumber         = ?,
1453                                                         multivolumepart      = ?,
1454                                                         biblioitemnumber     = ?,                       barcode              = ?,
1455                                                         booksellerid         = ?,                       dateaccessioned      = NOW(),
1456                                                         homebranch           = ?,                       holdingbranch        = ?,
1457                                                         price                = ?,                       replacementprice     = ?,
1458                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1459                                                         multivolume                     = ?,                    stack                           = ?,
1460                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1461                                                         paidfor                         = ?,                    itemnotes            = ?,
1462                                                         itemcallnumber  =?,                                                     notforloan = ?,
1463                                                         location = ?
1464                                                         "
1465         );
1466         $sth->execute(
1467                         $itemnumber,                            $item->{'biblionumber'},
1468                         $item->{'multivolumepart'},
1469                         $item->{'biblioitemnumber'},$item->{barcode},
1470                         $item->{'booksellerid'},
1471                         $item->{'homebranch'},          $item->{'holdingbranch'},
1472                         $item->{'price'},                       $item->{'replacementprice'},
1473                         $item->{multivolume},           $item->{stack},
1474                         $item->{itemlost},                      $item->{wthdrawn},
1475                         $item->{paidfor},                       $item->{'itemnotes'},
1476                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1477                         $item->{'location'}
1478         );
1479                 if ( defined $sth->errstr ) {
1480                         $error .= $sth->errstr;
1481                 }
1482     }
1483         # item stored, now, deal with the marc part...
1484         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1485                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1486                                                                         biblio.biblionumber=?");
1487         $sth->execute($item->{biblionumber});
1488     if ( defined $sth->errstr ) {
1489         $error .= $sth->errstr;
1490     }
1491         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1492         warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1493         my $record = MARC::File::USMARC::decode($rawmarc);
1494         # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1495         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1496         my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1497         #warn $itemrecord;
1498         #warn $itemnumberfield;
1499         #warn $itemrecord->field($itemnumberfield);
1500         my $itemfield = $itemrecord->field($itemnumberfield);
1501         $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1502         $record->insert_grouped_field($itemfield);
1503         # save the record into biblioitem
1504         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1505         $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1506     if ( defined $sth->errstr ) {
1507         $error .= $sth->errstr;
1508     }
1509         z3950_extended_services('update',set_service_options('update'),$record);
1510         $dbh->do('unlock tables');
1511     return ( $itemnumber, $error );
1512 }
1513
1514 =head2 REALmoditem($dbh,$item);
1515
1516 =over 4
1517
1518 modify item
1519
1520 =back
1521
1522 =cut
1523
1524 sub REALmoditem {
1525     my ( $dbh, $item ) = @_;
1526     $item->{'bibitemnum'} = 1;
1527         my $error;
1528         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1529     $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1530     my $query = "update items set  barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1531     my @bind = (
1532         $item->{'barcode'},                     $item->{'itemnotes'},
1533         $item->{'itemcallnumber'},      $item->{'notforloan'},
1534         $item->{'location'},            $item->{multivolumepart},
1535                 $item->{multivolume},           $item->{stack},
1536                 $item->{wthdrawn},
1537     );
1538     if ( $item->{'lost'} ne '' ) {
1539         $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1540                                                         itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1541                                                         location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1542         @bind = (
1543             $item->{'bibitemnum'},     $item->{'barcode'},
1544             $item->{'itemnotes'},          $item->{'homebranch'},
1545             $item->{'lost'},           $item->{'wthdrawn'},
1546             $item->{'itemcallnumber'}, $item->{'notforloan'},
1547             $item->{'location'},                $item->{multivolumepart},
1548                         $item->{multivolume},           $item->{stack},
1549                         $item->{wthdrawn},
1550         );
1551                 if ($item->{homebranch}) {
1552                         $query.=",homebranch=?";
1553                         push @bind, $item->{homebranch};
1554                 }
1555                 if ($item->{holdingbranch}) {
1556                         $query.=",holdingbranch=?";
1557                         push @bind, $item->{holdingbranch};
1558                 }
1559     }
1560         $query.=" where itemnumber=?";
1561         push @bind,$item->{'itemnum'};
1562    if ( $item->{'replacement'} ne '' ) {
1563         $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1564     }
1565     my $sth = $dbh->prepare($query);
1566     $sth->execute(@bind);
1567         
1568         # item stored, now, deal with the marc part...
1569         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1570                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1571                                                                         biblio.biblionumber=? and 
1572                                                                         biblioitems.biblioitemnumber=?");
1573         $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1574     if ( defined $sth->errstr ) {
1575         $error .= $sth->errstr;
1576     }
1577         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1578         warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1579         my $record = MARC::File::USMARC::decode($rawmarc);
1580         # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1581         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1582         # prepare the new item record
1583         my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1584         my $itemfield = $itemrecord->field($itemnumberfield);
1585         $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1586         # parse all fields fields from the complete record
1587         foreach ($record->field($itemnumberfield)) {
1588                 # when the previous field is found, replace by the new one
1589                 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1590                         $_->replace_with($itemfield);
1591                 }
1592         }
1593 #       $record->insert_grouped_field($itemfield);
1594         # save the record into biblioitem
1595         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1596         $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1597         z3950_extended_services('update',set_service_options('update'),$record);
1598     if ( defined $sth->errstr ) {
1599         $error .= $sth->errstr;
1600     }
1601         $dbh->do('unlock tables');
1602
1603 }
1604
1605 =head2 REALdelitem($dbh,$itemnum);
1606
1607 =over 4
1608
1609 delete item
1610
1611 =back
1612
1613 =cut
1614
1615 sub REALdelitem {
1616     my ( $dbh, $itemnum ) = @_;
1617
1618     #  my $dbh=C4Connect;
1619     my $sth = $dbh->prepare("select * from items where itemnumber=?");
1620     $sth->execute($itemnum);
1621     my $data = $sth->fetchrow_hashref;
1622     $sth->finish;
1623     my $query = "Insert into deleteditems set ";
1624     my @bind  = ();
1625     foreach my $temp ( keys %$data ) {
1626         $query .= "$temp = ?,";
1627         push ( @bind, $data->{$temp} );
1628     }
1629     $query =~ s/\,$//;
1630
1631     #  print $query;
1632     $sth = $dbh->prepare($query);
1633     $sth->execute(@bind);
1634     $sth->finish;
1635     $sth = $dbh->prepare("Delete from items where itemnumber=?");
1636     $sth->execute($itemnum);
1637     $sth->finish;
1638
1639     #  $dbh->disconnect;
1640 }
1641
1642 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1643
1644 =over 4
1645
1646 deletes a biblioitem
1647 NOTE : not standard sub name. Should be REALdelbiblioitem()
1648
1649 =back
1650
1651 =cut
1652
1653 sub REALdelbiblioitem {
1654     my ( $dbh, $biblioitemnumber ) = @_;
1655
1656     #    my $dbh   = C4Connect;
1657     my $sth = $dbh->prepare( "Select * from biblioitems
1658 where biblioitemnumber = ?"
1659     );
1660     my $results;
1661
1662     $sth->execute($biblioitemnumber);
1663
1664     if ( $results = $sth->fetchrow_hashref ) {
1665         $sth->finish;
1666         $sth =
1667           $dbh->prepare(
1668 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1669                                         isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1670                                         pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1671         );
1672
1673         $sth->execute(
1674             $results->{biblioitemnumber}, $results->{biblionumber},
1675             $results->{volume},           $results->{number},
1676             $results->{classification},   $results->{itemtype},
1677             $results->{isbn},             $results->{issn},
1678             $results->{dewey},            $results->{subclass},
1679             $results->{publicationyear},  $results->{publishercode},
1680             $results->{volumedate},       $results->{volumeddesc},
1681             $results->{timestamp},        $results->{illus},
1682             $results->{pages},            $results->{notes},
1683             $results->{size},             $results->{url},
1684             $results->{lccn}
1685         );
1686         my $sth2 =
1687           $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1688         $sth2->execute($biblioitemnumber);
1689         $sth2->finish();
1690     }    # if
1691     $sth->finish;
1692
1693     # Now delete all the items attached to the biblioitem
1694     $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1695     $sth->execute($biblioitemnumber);
1696     my @results;
1697     while ( my $data = $sth->fetchrow_hashref ) {
1698         my $query = "Insert into deleteditems set ";
1699         my @bind  = ();
1700         foreach my $temp ( keys %$data ) {
1701             $query .= "$temp = ?,";
1702             push ( @bind, $data->{$temp} );
1703         }
1704         $query =~ s/\,$//;
1705         my $sth2 = $dbh->prepare($query);
1706         $sth2->execute(@bind);
1707     }    # while
1708     $sth->finish;
1709     $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1710     $sth->execute($biblioitemnumber);
1711     $sth->finish();
1712
1713     #    $dbh->disconnect;
1714 }    # sub deletebiblioitem
1715
1716 =head2 REALdelbiblio($dbh,$biblio);
1717
1718 =over 4
1719
1720 delete a biblio
1721
1722 =back
1723
1724 =cut
1725
1726 sub REALdelbiblio {
1727     my ( $dbh, $biblio ) = @_;
1728     my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1729     $sth->execute($biblio);
1730     if ( my $data = $sth->fetchrow_hashref ) {
1731         $sth->finish;
1732         my $query = "Insert into deletedbiblio set ";
1733         my @bind  = ();
1734         foreach my $temp ( keys %$data ) {
1735             $query .= "$temp = ?,";
1736             push ( @bind, $data->{$temp} );
1737         }
1738
1739         #replacing the last , by ",?)"
1740         $query =~ s/\,$//;
1741         $sth = $dbh->prepare($query);
1742         $sth->execute(@bind);
1743         $sth->finish;
1744         $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1745         $sth->execute($biblio);
1746         $sth->finish;
1747     }
1748     $sth->finish;
1749 }
1750
1751 =head2 itemcount
1752
1753 $number = itemcount($biblio);
1754
1755 =over 4
1756
1757 returns the number of items attached to a biblio
1758
1759 =back
1760
1761 =cut
1762
1763 sub itemcount {
1764     my ($biblio) = @_;
1765     my $dbh = C4::Context->dbh;
1766
1767     #  print $query;
1768     my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1769     $sth->execute($biblio);
1770     my $data = $sth->fetchrow_hashref;
1771     $sth->finish;
1772     return ( $data->{'count(*)'} );
1773 }
1774
1775 =head2 newbiblio
1776
1777 $biblionumber = newbiblio($biblio);
1778
1779 =over 4
1780
1781 create a biblio. The parameter is a hash
1782
1783 =back
1784
1785 =cut
1786
1787 sub newbiblio {
1788     my ($biblio) = @_;
1789     my $dbh    = C4::Context->dbh;
1790     my $bibnum = REALnewbiblio( $dbh, $biblio );
1791     # finds new (MARC bibid
1792     #   my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1793 #     my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1794 #     MARCaddbiblio( $dbh, $record, $bibnum,'' );
1795     return ($bibnum);
1796 }
1797
1798 =head2  modbiblio
1799
1800 $biblionumber = &modbiblio($biblio);
1801
1802 =over 4
1803
1804 Update a biblio record.
1805
1806 C<$biblio> is a reference-to-hash whose keys are the fields in the
1807 biblio table in the Koha database. All fields must be present, not
1808 just the ones you wish to change.
1809
1810 C<&modbiblio> updates the record defined by
1811 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1812
1813 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1814 successful or not.
1815
1816 =back
1817
1818 =cut
1819
1820 sub modbiblio {
1821         my ($biblio) = @_;
1822         my $dbh  = C4::Context->dbh;
1823         my $biblionumber=REALmodbiblio($dbh,$biblio);
1824         my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1825         # finds new (MARC bibid
1826         my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1827         MARCmodbiblio($dbh,$bibid,$record,"",0);
1828         return($biblionumber);
1829 } # sub modbiblio
1830
1831 =head2 &modsubtitle($biblionumber, $subtitle);
1832
1833 =over 4
1834
1835 Sets the subtitle of a book.
1836
1837 C<$biblionumber> is the biblionumber of the book to modify.
1838
1839 C<$subtitle> is the new subtitle.
1840
1841 =back
1842
1843 =cut
1844
1845 sub modsubtitle {
1846     my ( $bibnum, $subtitle ) = @_;
1847     my $dbh = C4::Context->dbh;
1848     &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1849 }    # sub modsubtitle
1850
1851 =head2 &modaddauthor($biblionumber, $author);
1852
1853 =over 4
1854
1855 Replaces all additional authors for the book with biblio number
1856 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1857 C<&modaddauthor> deletes all additional authors.
1858
1859 =back
1860
1861 =cut
1862
1863 sub modaddauthor {
1864     my ( $bibnum, @authors ) = @_;
1865     my $dbh = C4::Context->dbh;
1866     &REALmodaddauthor( $dbh, $bibnum, @authors );
1867 }    # sub modaddauthor
1868
1869 =head2 modsubject
1870
1871 $error = &modsubject($biblionumber, $force, @subjects);
1872
1873 =over 4
1874
1875 $force - a subject to force
1876 $error - Error message, or undef if successful.
1877
1878 =back
1879
1880 =cut
1881
1882 sub modsubject {
1883     my ( $bibnum, $force, @subject ) = @_;
1884     my $dbh = C4::Context->dbh;
1885     my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1886     if ($error eq ''){
1887                 # When MARC is off, ensures that the MARC biblio table gets updated with new
1888                 # subjects, of course, it deletes the biblio in marc, and then recreates.
1889                 # This check is to ensure that no MARC data exists to lose.
1890 #               if (C4::Context->preference("MARC") eq '0'){
1891 #               warn "in modSUBJECT";
1892 #                       my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1893 #                       my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1894 #                       &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1895 #               }
1896         }
1897         return ($error);
1898 }    # sub modsubject
1899
1900 =head2 modbibitem($dbh, $biblioitem);
1901
1902 =over 4
1903
1904 modify a biblioitem. The parameter is a hash
1905
1906 =back
1907
1908 =cut
1909
1910 sub modbibitem {
1911     my ($dbh, $biblioitem) = @_;
1912     #my $dbh = C4::Context->dbh;
1913     &REALmodbiblioitem( $dbh, $biblioitem );
1914 }    # sub modbibitem
1915
1916 =head2 newbiblioitem
1917
1918 $biblioitemnumber = newbiblioitem($biblioitem)
1919
1920 =over 4
1921
1922 create a biblioitem, the parameter is a hash
1923
1924 =back
1925
1926 =cut
1927
1928 sub newbiblioitem {
1929     my ($dbh, $biblioitem) = @_;
1930     #my $dbh        = C4::Context->dbh;
1931         # add biblio information to the hash
1932     my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1933         $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1934     my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1935     return ($bibitemnum);
1936 }
1937
1938 =head2 newsubtitle($biblionumber,$subtitle);
1939
1940 =over 4
1941
1942 insert a subtitle for $biblionumber biblio
1943
1944 =back
1945
1946 =cut
1947
1948
1949 sub newsubtitle {
1950     my ( $bibnum, $subtitle ) = @_;
1951     my $dbh = C4::Context->dbh;
1952     &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1953 }
1954
1955 =head2 newitems
1956
1957 $errors = newitems($dbh, $item, @barcodes);
1958
1959 =over 4
1960
1961 insert items ($item is a hash)
1962
1963 =back
1964
1965 =cut
1966
1967
1968 sub newitems {
1969     my ( $dbh, $item, @barcodes ) = @_;
1970     #my $dbh = C4::Context->dbh;
1971     my $errors;
1972     my $itemnumber;
1973     my $error;
1974     foreach my $barcode (@barcodes) {
1975                 # add items, one by one for each barcode.
1976                 my $oneitem=$item;
1977                 $oneitem->{barcode}= $barcode;
1978         my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1979                 $oneitem->{marc} = $MARCitem->as_usmarc;
1980         ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
1981 #         $errors .= $error;
1982 #         &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1983     }
1984     return ($errors);
1985 }
1986
1987 =head2 moditem($dbh,$item);
1988
1989 =over 4
1990
1991 modify an item ($item is a hash with all item informations)
1992
1993 =back
1994
1995 =cut
1996
1997
1998 sub moditem {
1999     my ($dbh, $item) = @_;
2000     #my $dbh = C4::Context->dbh;
2001     &REALmoditem( $dbh, $item );
2002     my $MARCitem =
2003       &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
2004     my $bibid =
2005       &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
2006     &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
2007 }
2008
2009 =head2 checkitems
2010
2011 $error = checkitems($count,@barcodes);
2012
2013 =over 4
2014
2015 check for each @barcode entry that the barcode is not a duplicate
2016
2017 =back
2018
2019 =cut
2020
2021 sub checkitems {
2022     my ( $count, @barcodes ) = @_;
2023     my $dbh = C4::Context->dbh;
2024     my $error;
2025     my $sth = $dbh->prepare("Select * from items where barcode=?");
2026     for ( my $i = 0 ; $i < $count ; $i++ ) {
2027         $barcodes[$i] = uc $barcodes[$i];
2028         $sth->execute( $barcodes[$i] );
2029         if ( my $data = $sth->fetchrow_hashref ) {
2030             $error .= " Duplicate Barcode: $barcodes[$i]";
2031         }
2032     }
2033     $sth->finish;
2034     return ($error);
2035 }
2036
2037 =head2 delitem($itemnum);
2038
2039 =over 4
2040
2041 delete item $itemnum being the item number to delete
2042
2043 =back
2044
2045 =cut
2046
2047 sub delitem {
2048     my ($itemnum) = @_;
2049     my $dbh = C4::Context->dbh;
2050     &REALdelitem( $dbh, $itemnum );
2051 }
2052
2053 =head2 deletebiblioitem($biblioitemnumber);
2054
2055 =over 4
2056
2057 delete the biblioitem $biblioitemnumber
2058
2059 =back
2060
2061 =cut
2062
2063 sub deletebiblioitem {
2064     my ($biblioitemnumber) = @_;
2065     my $dbh = C4::Context->dbh;
2066     &REALdelbiblioitem( $dbh, $biblioitemnumber );
2067 }    # sub deletebiblioitem
2068
2069 =head2 delbiblio($biblionumber)
2070
2071 =over 4
2072
2073 delete biblio $biblionumber
2074
2075 =back
2076
2077 =cut
2078
2079 sub delbiblio {
2080     my ($biblio) = @_;
2081     my $dbh = C4::Context->dbh;
2082     &REALdelbiblio( $dbh, $biblio );
2083     my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2084     &MARCdelbiblio( $dbh, $bibid, 0 );
2085 }
2086
2087 =head2 getbiblio
2088
2089 ($count,@results) = getbiblio($biblionumber);
2090
2091 =over 4
2092
2093 return an array with hash of biblios.
2094
2095 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2096
2097 =back
2098
2099 =cut
2100
2101 sub getbiblio {
2102     my ($biblionumber) = @_;
2103     my $dbh = C4::Context->dbh;
2104     my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2105
2106     # || die "Cannot prepare $query\n" . $dbh->errstr;
2107     my $count = 0;
2108     my @results;
2109
2110     $sth->execute($biblionumber);
2111
2112     # || die "Cannot execute $query\n" . $sth->errstr;
2113     while ( my $data = $sth->fetchrow_hashref ) {
2114         $results[$count] = $data;
2115         $count++;
2116     }    # while
2117
2118     $sth->finish;
2119     return ( $count, @results );
2120 }    # sub getbiblio
2121
2122 =head2 bibdata
2123
2124   $data = &bibdata($biblionumber, $type);
2125
2126 Returns information about the book with the given biblionumber.
2127
2128 C<$type> is ignored.
2129
2130 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2131 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2132 Koha database.
2133
2134 In addition, C<$data-E<gt>{subject}> is the list of the book's
2135 subjects, separated by C<" , "> (space, comma, space).
2136
2137 If there are multiple biblioitems with the given biblionumber, only
2138 the first one is considered.
2139
2140 =cut
2141 #'
2142 sub bibdata {
2143         my ($bibnum, $type) = @_;
2144         my $dbh   = C4::Context->dbh;
2145         my $sth   = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2146                                                                 from biblio 
2147                                                                 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2148                                                                 left join bibliosubtitle on
2149                                                                 biblio.biblionumber = bibliosubtitle.biblionumber
2150                                                                 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2151                                                                 where biblio.biblionumber = ?
2152                                                                 ");
2153         $sth->execute($bibnum);
2154         my $data;
2155         $data  = $sth->fetchrow_hashref;
2156         $sth->finish;
2157         # handle management of repeated subtitle
2158         $sth   = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2159         $sth->execute($bibnum);
2160         my @subtitles;
2161         while (my $dat = $sth->fetchrow_hashref){
2162                 my %line;
2163                 $line{subtitle} = $dat->{subtitle};
2164                 push @subtitles, \%line;
2165         } # while
2166         $data->{subtitles} = \@subtitles;
2167         $sth->finish;
2168         $sth   = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2169         $sth->execute($bibnum);
2170         my @subjects;
2171         while (my $dat = $sth->fetchrow_hashref){
2172                 my %line;
2173                 $line{subject} = $dat->{'subject'};
2174                 push @subjects, \%line;
2175         } # while
2176         $data->{subjects} = \@subjects;
2177         $sth->finish;
2178         $sth   = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2179         $sth->execute($bibnum);
2180         while (my $dat = $sth->fetchrow_hashref){
2181                 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2182         } # while
2183         chop $data->{'additionalauthors'};
2184         chop $data->{'additionalauthors'};
2185         chop $data->{'additionalauthors'};
2186         $sth->finish;
2187         return($data);
2188 } # sub bibdata
2189
2190 =head2 getbiblioitem
2191
2192 ($count,@results) = getbiblioitem($biblioitemnumber);
2193
2194 =over 4
2195
2196 return an array with hash of biblioitemss.
2197
2198 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2199
2200 =back
2201
2202 =cut
2203
2204 sub getbiblioitem {
2205     my ($biblioitemnum) = @_;
2206     my $dbh = C4::Context->dbh;
2207     my $sth = $dbh->prepare( "Select * from biblioitems where
2208 biblioitemnumber = ?"
2209     );
2210     my $count = 0;
2211     my @results;
2212
2213     $sth->execute($biblioitemnum);
2214
2215     while ( my $data = $sth->fetchrow_hashref ) {
2216         $results[$count] = $data;
2217         $count++;
2218     }    # while
2219
2220     $sth->finish;
2221     return ( $count, @results );
2222 }    # sub getbiblioitem
2223
2224 =head2 getbiblioitembybiblionumber
2225
2226 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2227
2228 =over 4
2229
2230 return an array with hash of biblioitems for the given biblionumber.
2231
2232 =back
2233
2234 =cut
2235
2236 sub getbiblioitembybiblionumber {
2237     my ($biblionumber) = @_;
2238     my $dbh = C4::Context->dbh;
2239     my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2240     my $count = 0;
2241     my @results;
2242
2243     $sth->execute($biblionumber);
2244
2245     while ( my $data = $sth->fetchrow_hashref ) {
2246         $results[$count] = $data;
2247         $count++;
2248     }    # while
2249
2250     $sth->finish;
2251     return ( $count, @results );
2252 }    # sub
2253
2254 =head2 getitemsbybiblioitem
2255
2256 ($count,@results) = getitemsbybiblioitem($biblionumber);
2257
2258 =over 4
2259
2260 returns an array with hash of items
2261
2262 =back
2263
2264 =cut
2265
2266 sub getitemsbybiblioitem {
2267     my ($biblioitemnum) = @_;
2268     my $dbh = C4::Context->dbh;
2269     my $sth = $dbh->prepare( "Select * from items, biblio where
2270 biblio.biblionumber = items.biblionumber and biblioitemnumber
2271 = ?"
2272     );
2273
2274     # || die "Cannot prepare $query\n" . $dbh->errstr;
2275     my $count = 0;
2276     my @results;
2277
2278     $sth->execute($biblioitemnum);
2279
2280     # || die "Cannot execute $query\n" . $sth->errstr;
2281     while ( my $data = $sth->fetchrow_hashref ) {
2282         $results[$count] = $data;
2283         $count++;
2284     }    # while
2285
2286     $sth->finish;
2287     return ( $count, @results );
2288 }    # sub getitemsbybiblioitem
2289
2290 =head2 ItemInfo
2291
2292   @results = &ItemInfo($env, $biblionumber, $type);
2293
2294 Returns information about books with the given biblionumber.
2295
2296 C<$type> may be either C<intra> or anything else. If it is not set to
2297 C<intra>, then the search will exclude lost, very overdue, and
2298 withdrawn items.
2299
2300 C<$env> is ignored.
2301
2302 C<&ItemInfo> returns a list of references-to-hash. Each element
2303 contains a number of keys. Most of them are table items from the
2304 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2305 Koha database. Other keys include:
2306
2307 =over 4
2308
2309 =item C<$data-E<gt>{branchname}>
2310
2311 The name (not the code) of the branch to which the book belongs.
2312
2313 =item C<$data-E<gt>{datelastseen}>
2314
2315 This is simply C<items.datelastseen>, except that while the date is
2316 stored in YYYY-MM-DD format in the database, here it is converted to
2317 DD/MM/YYYY format. A NULL date is returned as C<//>.
2318
2319 =item C<$data-E<gt>{datedue}>
2320
2321 =item C<$data-E<gt>{class}>
2322
2323 This is the concatenation of C<biblioitems.classification>, the book's
2324 Dewey code, and C<biblioitems.subclass>.
2325
2326 =item C<$data-E<gt>{ocount}>
2327
2328 I think this is the number of copies of the book available.
2329
2330 =item C<$data-E<gt>{order}>
2331
2332 If this is set, it is set to C<One Order>.
2333
2334 =back
2335
2336 =cut
2337 #'
2338 sub ItemInfo {
2339         my ($env,$biblionumber,$type) = @_;
2340         my $dbh   = C4::Context->dbh;
2341         my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems 
2342                                         left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2343                                         WHERE items.biblionumber = ?
2344                                         AND biblioitems.biblioitemnumber = items.biblioitemnumber
2345                                         AND biblio.biblionumber = items.biblionumber";
2346         $query .= " order by items.dateaccessioned desc";
2347         my $sth=$dbh->prepare($query);
2348         $sth->execute($biblionumber);
2349         my $i=0;
2350         my @results;
2351         while (my $data=$sth->fetchrow_hashref){
2352                 my $datedue = '';
2353                 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2354                 $isth->execute($data->{'itemnumber'});
2355                 if (my $idata=$isth->fetchrow_hashref){
2356                 $data->{borrowernumber} = $idata->{borrowernumber};
2357                 $data->{cardnumber} = $idata->{cardnumber};
2358                 $datedue = format_date($idata->{'date_due'});
2359                 }
2360                 if ($datedue eq ''){
2361                         my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2362                         if ($restype) {
2363                                 $datedue=$restype;
2364                         }
2365                 }
2366                 $isth->finish;
2367         #get branch information.....
2368                 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2369                 $bsth->execute($data->{'holdingbranch'});
2370                 if (my $bdata=$bsth->fetchrow_hashref){
2371                         $data->{'branchname'} = $bdata->{'branchname'};
2372                 }
2373                 my $date=format_date($data->{'datelastseen'});
2374                 $data->{'datelastseen'}=$date;
2375                 $data->{'datedue'}=$datedue;
2376         # get notforloan complete status if applicable
2377                 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2378                 $sthnflstatus->execute;
2379                 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2380                 if ($authorised_valuecode) {
2381                         $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2382                         $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2383                         my ($lib) = $sthnflstatus->fetchrow;
2384                         $data->{notforloan} = $lib;
2385                 }
2386                 $results[$i]=$data;
2387                 $i++;
2388         }
2389         $sth->finish;
2390         return(@results);
2391 }
2392
2393 =head2 bibitems
2394
2395   ($count, @results) = &bibitems($biblionumber);
2396
2397 Given the biblionumber for a book, C<&bibitems> looks up that book's
2398 biblioitems (different publications of the same book, the audio book
2399 and film versions, etc.).
2400
2401 C<$count> is the number of elements in C<@results>.
2402
2403 C<@results> is an array of references-to-hash; the keys are the fields
2404 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2405 addition, C<itemlost> indicates the availability of the item: if it is
2406 "2", then all copies of the item are long overdue; if it is "1", then
2407 all copies are lost; otherwise, there is at least one copy available.
2408
2409 =cut
2410 #'
2411 sub bibitems {
2412     my ($bibnum) = @_;
2413     my $dbh   = C4::Context->dbh;
2414     my $sth   = $dbh->prepare("SELECT biblioitems.*,
2415                         itemtypes.*,
2416                         MIN(items.itemlost)        as itemlost,
2417                         MIN(items.dateaccessioned) as dateaccessioned
2418                           FROM biblioitems, itemtypes, items
2419                          WHERE biblioitems.biblionumber     = ?
2420                            AND biblioitems.itemtype         = itemtypes.itemtype
2421                            AND biblioitems.biblioitemnumber = items.biblioitemnumber
2422                       GROUP BY items.biblioitemnumber");
2423     my $count = 0;
2424     my @results;
2425     $sth->execute($bibnum);
2426     while (my $data = $sth->fetchrow_hashref) {
2427         $results[$count] = $data;
2428         $count++;
2429     } # while
2430     $sth->finish;
2431     return($count, @results);
2432 } # sub bibitems
2433
2434
2435 =head2 bibitemdata
2436
2437   $itemdata = &bibitemdata($biblioitemnumber);
2438
2439 Looks up the biblioitem with the given biblioitemnumber. Returns a
2440 reference-to-hash. The keys are the fields from the C<biblio>,
2441 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2442 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2443
2444 =cut
2445 #'
2446 sub bibitemdata {
2447     my ($bibitem) = @_;
2448     my $dbh   = C4::Context->dbh;
2449     my $sth   = $dbh->prepare("Select *,biblioitems.notes as bnotes from biblio, biblioitems,itemtypes where biblio.biblionumber = biblioitems.biblionumber and biblioitemnumber = ? and biblioitems.itemtype = itemtypes.itemtype");
2450     my $data;
2451
2452     $sth->execute($bibitem);
2453
2454     $data = $sth->fetchrow_hashref;
2455
2456     $sth->finish;
2457     return($data);
2458 } # sub bibitemdata
2459
2460
2461 =head2 getbibliofromitemnumber
2462
2463   $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2464
2465 Looks up the item with the given itemnumber.
2466
2467 C<$env> and C<$dbh> are ignored.
2468
2469 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2470 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2471 database.
2472
2473 =cut
2474 #'
2475 sub getbibliofromitemnumber {
2476   my ($env,$dbh,$itemnumber) = @_;
2477   $dbh = C4::Context->dbh;
2478   my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2479     where items.itemnumber = ?
2480     and biblio.biblionumber = items.biblionumber
2481     and biblioitems.biblioitemnumber = items.biblioitemnumber");
2482 #  print $query;
2483   $sth->execute($itemnumber);
2484   my $data=$sth->fetchrow_hashref;
2485   $sth->finish;
2486   return($data);
2487 }
2488
2489 =head2 barcodes
2490
2491   @barcodes = &barcodes($biblioitemnumber);
2492
2493 Given a biblioitemnumber, looks up the corresponding items.
2494
2495 Returns an array of references-to-hash; the keys are C<barcode> and
2496 C<itemlost>.
2497
2498 The returned items include very overdue items, but not lost ones.
2499
2500 =cut
2501 #'
2502 sub barcodes{
2503     #called from request.pl
2504     my ($biblioitemnumber)=@_;
2505     my $dbh = C4::Context->dbh;
2506     my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2507                            WHERE biblioitemnumber = ?
2508                              AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2509     $sth->execute($biblioitemnumber);
2510     my @barcodes;
2511     my $i=0;
2512     while (my $data=$sth->fetchrow_hashref){
2513         $barcodes[$i]=$data;
2514         $i++;
2515     }
2516     $sth->finish;
2517     return(@barcodes);
2518 }
2519
2520
2521 =head2 itemdata
2522
2523   $item = &itemdata($barcode);
2524
2525 Looks up the item with the given barcode, and returns a
2526 reference-to-hash containing information about that item. The keys of
2527 the hash are the fields from the C<items> and C<biblioitems> tables in
2528 the Koha database.
2529
2530 =cut
2531 #'
2532 sub get_item_from_barcode {
2533   my ($barcode)=@_;
2534   my $dbh = C4::Context->dbh;
2535   my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2536   and items.biblioitemnumber=biblioitems.biblioitemnumber");
2537   $sth->execute($barcode);
2538   my $data=$sth->fetchrow_hashref;
2539   $sth->finish;
2540   return($data);
2541 }
2542
2543
2544 =head2 itemissues
2545
2546   @issues = &itemissues($biblioitemnumber, $biblio);
2547
2548 Looks up information about who has borrowed the bookZ<>(s) with the
2549 given biblioitemnumber.
2550
2551 C<$biblio> is ignored.
2552
2553 C<&itemissues> returns an array of references-to-hash. The keys
2554 include the fields from the C<items> table in the Koha database.
2555 Additional keys include:
2556
2557 =over 4
2558
2559 =item C<date_due>
2560
2561 If the item is currently on loan, this gives the due date.
2562
2563 If the item is not on loan, then this is either "Available" or
2564 "Cancelled", if the item has been withdrawn.
2565
2566 =item C<card>
2567
2568 If the item is currently on loan, this gives the card number of the
2569 patron who currently has the item.
2570
2571 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2572
2573 These give the timestamp for the last three times the item was
2574 borrowed.
2575
2576 =item C<card0>, C<card1>, C<card2>
2577
2578 The card number of the last three patrons who borrowed this item.
2579
2580 =item C<borrower0>, C<borrower1>, C<borrower2>
2581
2582 The borrower number of the last three patrons who borrowed this item.
2583
2584 =back
2585
2586 =cut
2587 #'
2588 sub itemissues {
2589     my ($bibitem, $biblio)=@_;
2590     my $dbh   = C4::Context->dbh;
2591     # FIXME - If this function die()s, the script will abort, and the
2592     # user won't get anything; depending on how far the script has
2593     # gotten, the user might get a blank page. It would be much better
2594     # to at least print an error message. The easiest way to do this
2595     # is to set $SIG{__DIE__}.
2596     my $sth   = $dbh->prepare("Select * from items where
2597 items.biblioitemnumber = ?")
2598       || die $dbh->errstr;
2599     my $i     = 0;
2600     my @results;
2601
2602     $sth->execute($bibitem)
2603       || die $sth->errstr;
2604
2605     while (my $data = $sth->fetchrow_hashref) {
2606         # Find out who currently has this item.
2607         # FIXME - Wouldn't it be better to do this as a left join of
2608         # some sort? Currently, this code assumes that if
2609         # fetchrow_hashref() fails, then the book is on the shelf.
2610         # fetchrow_hashref() can fail for any number of reasons (e.g.,
2611         # database server crash), not just because no items match the
2612         # search criteria.
2613         my $sth2   = $dbh->prepare("select * from issues,borrowers
2614 where itemnumber = ?
2615 and returndate is NULL
2616 and issues.borrowernumber = borrowers.borrowernumber");
2617
2618         $sth2->execute($data->{'itemnumber'});
2619         if (my $data2 = $sth2->fetchrow_hashref) {
2620             $data->{'date_due'} = $data2->{'date_due'};
2621             $data->{'card'}     = $data2->{'cardnumber'};
2622             $data->{'borrower'}     = $data2->{'borrowernumber'};
2623         } else {
2624             if ($data->{'wthdrawn'} eq '1') {
2625                 $data->{'date_due'} = 'Cancelled';
2626             } else {
2627                 $data->{'date_due'} = 'Available';
2628             } # else
2629         } # else
2630
2631         $sth2->finish;
2632
2633         # Find the last 3 people who borrowed this item.
2634         $sth2 = $dbh->prepare("select * from issues, borrowers
2635                                                 where itemnumber = ?
2636                                                                         and issues.borrowernumber = borrowers.borrowernumber
2637                                                                         and returndate is not NULL
2638                                                                         order by returndate desc,timestamp desc") || die $dbh->errstr;
2639         $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2640         for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2641             if (my $data2 = $sth2->fetchrow_hashref) {
2642                 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2643                 $data->{"card$i2"}      = $data2->{'cardnumber'};
2644                 $data->{"borrower$i2"}  = $data2->{'borrowernumber'};
2645             } # if
2646         } # for
2647
2648         $sth2->finish;
2649         $results[$i] = $data;
2650         $i++;
2651     }
2652
2653     $sth->finish;
2654     return(@results);
2655 }
2656
2657 =head2 getsubject
2658
2659   ($count, $subjects) = &getsubject($biblionumber);
2660
2661 Looks up the subjects of the book with the given biblionumber. Returns
2662 a two-element list. C<$subjects> is a reference-to-array, where each
2663 element is a subject of the book, and C<$count> is the number of
2664 elements in C<$subjects>.
2665
2666 =cut
2667 #'
2668 sub getsubject {
2669   my ($bibnum)=@_;
2670   my $dbh = C4::Context->dbh;
2671   my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2672   $sth->execute($bibnum);
2673   my @results;
2674   my $i=0;
2675   while (my $data=$sth->fetchrow_hashref){
2676     $results[$i]=$data;
2677     $i++;
2678   }
2679   $sth->finish;
2680   return($i,\@results);
2681 }
2682
2683 =head2 getaddauthor
2684
2685   ($count, $authors) = &getaddauthor($biblionumber);
2686
2687 Looks up the additional authors for the book with the given
2688 biblionumber.
2689
2690 Returns a two-element list. C<$authors> is a reference-to-array, where
2691 each element is an additional author, and C<$count> is the number of
2692 elements in C<$authors>.
2693
2694 =cut
2695 #'
2696 sub getaddauthor {
2697   my ($bibnum)=@_;
2698   my $dbh = C4::Context->dbh;
2699   my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2700   $sth->execute($bibnum);
2701   my @results;
2702   my $i=0;
2703   while (my $data=$sth->fetchrow_hashref){
2704     $results[$i]=$data;
2705     $i++;
2706   }
2707   $sth->finish;
2708   return($i,\@results);
2709 }
2710
2711
2712 =head2 getsubtitle
2713
2714   ($count, $subtitles) = &getsubtitle($biblionumber);
2715
2716 Looks up the subtitles for the book with the given biblionumber.
2717
2718 Returns a two-element list. C<$subtitles> is a reference-to-array,
2719 where each element is a subtitle, and C<$count> is the number of
2720 elements in C<$subtitles>.
2721
2722 =cut
2723 #'
2724 sub getsubtitle {
2725   my ($bibnum)=@_;
2726   my $dbh = C4::Context->dbh;
2727   my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2728   $sth->execute($bibnum);
2729   my @results;
2730   my $i=0;
2731   while (my $data=$sth->fetchrow_hashref){
2732     $results[$i]=$data;
2733     $i++;
2734   }
2735   $sth->finish;
2736   return($i,\@results);
2737 }
2738
2739
2740 =head2 getwebsites
2741
2742   ($count, @websites) = &getwebsites($biblionumber);
2743
2744 Looks up the web sites pertaining to the book with the given
2745 biblionumber.
2746
2747 C<$count> is the number of elements in C<@websites>.
2748
2749 C<@websites> is an array of references-to-hash; the keys are the
2750 fields from the C<websites> table in the Koha database.
2751
2752 =cut
2753 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2754 #(with add / modify / delete subs)
2755
2756 sub getwebsites {
2757     my ($biblionumber) = @_;
2758     my $dbh   = C4::Context->dbh;
2759     my $sth   = $dbh->prepare("Select * from websites where biblionumber = ?");
2760     my $count = 0;
2761     my @results;
2762
2763     $sth->execute($biblionumber);
2764     while (my $data = $sth->fetchrow_hashref) {
2765         # FIXME - The URL scheme shouldn't be stripped off, at least
2766         # not here, since it's part of the URL, and will be useful in
2767         # constructing a link to the site. If you don't want the user
2768         # to see the "http://" part, strip that off when building the
2769         # HTML code.
2770         $data->{'url'} =~ s/^http:\/\///;       # FIXME - Leaning toothpick
2771                                                 # syndrome
2772         $results[$count] = $data;
2773         $count++;
2774     } # while
2775
2776     $sth->finish;
2777     return($count, @results);
2778 } # sub getwebsites
2779
2780 =head2 getwebbiblioitems
2781
2782   ($count, @results) = &getwebbiblioitems($biblionumber);
2783
2784 Given a book's biblionumber, looks up the web versions of the book
2785 (biblioitems with itemtype C<WEB>).
2786
2787 C<$count> is the number of items in C<@results>. C<@results> is an
2788 array of references-to-hash; the keys are the items from the
2789 C<biblioitems> table of the Koha database.
2790
2791 =cut
2792 #'
2793 sub getwebbiblioitems {
2794     my ($biblionumber) = @_;
2795     my $dbh   = C4::Context->dbh;
2796     my $sth   = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2797 and itemtype = 'WEB'");
2798     my $count = 0;
2799     my @results;
2800
2801     $sth->execute($biblionumber);
2802     while (my $data = $sth->fetchrow_hashref) {
2803         $data->{'url'} =~ s/^http:\/\///;
2804         $results[$count] = $data;
2805         $count++;
2806     } # while
2807
2808     $sth->finish;
2809     return($count, @results);
2810 } # sub getwebbiblioitems
2811
2812 sub nsb_clean {
2813     my $NSB = '\x88';    # NSB : begin Non Sorting Block
2814     my $NSE = '\x89';    # NSE : Non Sorting Block end
2815                          # handles non sorting blocks
2816     my ($string) = @_;
2817     $_ = $string;
2818     s/$NSB/(/gm;
2819     s/[ ]{0,1}$NSE/) /gm;
2820     $string = $_;
2821     return ($string);
2822 }
2823
2824 sub FindDuplicate {
2825         my ($record)=@_;
2826         my $dbh = C4::Context->dbh;
2827         my $result = MARCmarc2koha($dbh,$record,'');
2828         my $sth;
2829         my ($biblionumber,$bibid,$title);
2830         # search duplicate on ISBN, easy and fast...
2831         if ($result->{isbn}) {
2832                 $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=?");
2833                 $sth->execute($result->{'isbn'});
2834                 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2835                 return $biblionumber,$bibid,$title if ($biblionumber);
2836         }
2837         # a more complex search : build a request for SearchMarc::catalogsearch()
2838         my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2839         # search on biblio.title
2840         my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2841         if ($record->field($tag)) {
2842                 if ($record->field($tag)->subfields($subfield)) {
2843                         push @tags, "'".$tag.$subfield."'";
2844                         push @and_or, "and";
2845                         push @excluding, "";
2846                         push @operator, "contains";
2847                         push @value, $record->field($tag)->subfield($subfield);
2848 #                       warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2849                 }
2850         }
2851         # ... and on biblio.author
2852         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2853         if ($record->field($tag)) {
2854                 if ($record->field($tag)->subfields($subfield)) {
2855                         push @tags, "'".$tag.$subfield."'";
2856                         push @and_or, "and";
2857                         push @excluding, "";
2858                         push @operator, "contains";
2859                         push @value, $record->field($tag)->subfield($subfield);
2860 #                       warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2861                 }
2862         }
2863         # ... and on publicationyear.
2864         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2865         if ($record->field($tag)) {
2866                 if ($record->field($tag)->subfields($subfield)) {
2867                         push @tags, "'".$tag.$subfield."'";
2868                         push @and_or, "and";
2869                         push @excluding, "";
2870                         push @operator, "=";
2871                         push @value, $record->field($tag)->subfield($subfield);
2872 #                       warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2873                 }
2874         }
2875         # ... and on size.
2876         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2877         if ($record->field($tag)) {
2878                 if ($record->field($tag)->subfields($subfield)) {
2879                         push @tags, "'".$tag.$subfield."'";
2880                         push @and_or, "and";
2881                         push @excluding, "";
2882                         push @operator, "=";
2883                         push @value, $record->field($tag)->subfield($subfield);
2884 #                       warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2885                 }
2886         }
2887         # ... and on publisher.
2888         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2889         if ($record->field($tag)) {
2890                 if ($record->field($tag)->subfields($subfield)) {
2891                         push @tags, "'".$tag.$subfield."'";
2892                         push @and_or, "and";
2893                         push @excluding, "";
2894                         push @operator, "=";
2895                         push @value, $record->field($tag)->subfield($subfield);
2896 #                       warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2897                 }
2898         }
2899         # ... and on volume.
2900         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2901         if ($record->field($tag)) {
2902                 if ($record->field($tag)->subfields($subfield)) {
2903                         push @tags, "'".$tag.$subfield."'";
2904                         push @and_or, "and";
2905                         push @excluding, "";
2906                         push @operator, "=";
2907                         push @value, $record->field($tag)->subfield($subfield);
2908 #                       warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2909                 }
2910         }
2911
2912         my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2913         # there is at least 1 result => return the 1st one
2914         if ($nbresult) {
2915 #               warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2916                 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2917         }
2918         # no result, returns nothing
2919         return;
2920 }
2921
2922 sub DisplayISBN {
2923         my ($isbn)=@_;
2924         my $seg1;
2925         if(substr($isbn, 0, 1) <=7) {
2926                 $seg1 = substr($isbn, 0, 1);
2927         } elsif(substr($isbn, 0, 2) <= 94) {
2928                 $seg1 = substr($isbn, 0, 2);
2929         } elsif(substr($isbn, 0, 3) <= 995) {
2930                 $seg1 = substr($isbn, 0, 3);
2931         } elsif(substr($isbn, 0, 4) <= 9989) {
2932                 $seg1 = substr($isbn, 0, 4);
2933         } else {
2934                 $seg1 = substr($isbn, 0, 5);
2935         }
2936         my $x = substr($isbn, length($seg1));
2937         my $seg2;
2938         if(substr($x, 0, 2) <= 19) {
2939 #               if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2940                 $seg2 = substr($x, 0, 2);
2941         } elsif(substr($x, 0, 3) <= 699) {
2942                 $seg2 = substr($x, 0, 3);
2943         } elsif(substr($x, 0, 4) <= 8399) {
2944                 $seg2 = substr($x, 0, 4);
2945         } elsif(substr($x, 0, 5) <= 89999) {
2946                 $seg2 = substr($x, 0, 5);
2947         } elsif(substr($x, 0, 6) <= 9499999) {
2948                 $seg2 = substr($x, 0, 6);
2949         } else {
2950                 $seg2 = substr($x, 0, 7);
2951         }
2952         my $seg3=substr($x,length($seg2));
2953         $seg3=substr($seg3,0,length($seg3)-1) ;
2954         my $seg4 = substr($x, -1, 1);
2955         return "$seg1-$seg2-$seg3-$seg4";
2956 }
2957
2958
2959 END { }    # module clean-up code here (global destructor)
2960
2961 =back
2962
2963 =head1 AUTHOR
2964
2965 Koha Developement team <info@koha.org>
2966
2967 Paul POULAIN paul.poulain@free.fr
2968
2969 =cut
2970
2971 # $Id$
2972 # $Log$
2973 # Revision 1.157  2006/03/01 03:07:54  kados
2974 # rollback ... by accident I committed a rel_2_2 Biblio.pm
2975 #
2976 # Revision 1.155  2006/02/27 01:08:31  kados
2977 # Removing 'our Zconn' from top...
2978 #
2979 # Revision 1.154  2006/02/26 00:08:20  kados
2980 # moving all $Zconn s to z3950_extended_services (currently, nothing
2981 # works).
2982 #
2983 # Revision 1.153  2006/02/25 22:39:10  kados
2984 # Another purely documentation commit. Just changing formatting to ease
2985 # readability.
2986 #
2987 # Revision 1.152  2006/02/25 21:17:20  kados
2988 # Purely documentation change: converted all =head2 entries to use function
2989 # name as title rather than usage as title
2990 #
2991 # Revision 1.151  2006/02/25 21:02:20  kados
2992 #
2993 # Further cleanup, convering new routines to 4-chars
2994 #
2995 # Revision 1.150  2006/02/25 20:49:15  kados
2996 # Better documentation, added warning if serviceType is 'drop' since it's
2997 # not supported in Zebra.
2998 #
2999 # Revision 1.149  2006/02/25 20:30:32  kados
3000 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
3001 # longer necessary. If we need to convert from MARC-8 for display, we should:
3002 #
3003 # 1. use utf-8
3004 # 2. do it with MARC::Charset
3005 #
3006 # If you still need it, let me know and I'll put it back in.
3007 #
3008 # Revision 1.148  2006/02/25 19:23:01  kados
3009 # cleaning up POD docs, deleting zebra_create as it's no longer used (
3010 # replaced by z3950_extended_services).
3011 #
3012 # Revision 1.147  2006/02/25 19:09:59  kados
3013 # readding some lost subs
3014 #
3015 # Revision 1.145  2006/02/22 01:02:39  kados
3016 # Replacing all calls to zebra_update with calls to
3017 # z3950_extended_services. More work coming, but it's
3018 # working now.
3019 #
3020 # Revision 1.144  2006/02/20 14:22:38  kados
3021 # typo
3022 #
3023 # Revision 1.143  2006/02/20 13:26:11  kados
3024 # A new subroutine to handle Z39.50 extended services. You pass it a
3025 # connection object, service type, service options, and a record, and
3026 # it performs the service and handles any exception found.
3027 #
3028 # Revision 1.142  2006/02/16 20:49:56  kados
3029 # destroy a connection after we're done -- we really should just have one
3030 # connection object and not destroy it until the whole transaction is
3031 # finished -- but this will do for now
3032 #
3033 # Revision 1.141  2006/02/16 19:47:22  rangi
3034 # Trying to error trap a little more.
3035 #
3036 # Revision 1.140  2006/02/14 21:36:03  kados
3037 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3038 # also adding diagnostic error if not able to connect to Zebra
3039 #
3040 # Revision 1.139  2006/02/14 19:53:25  rangi
3041 # Just a little missing my
3042 #
3043 # Seems to be working great Paul, and I like what you did with zebradb
3044 #
3045 # Revision 1.138  2006/02/14 11:25:22  tipaul
3046 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3047 #
3048 # Revision 1.137  2006/02/13 16:34:26  tipaul
3049 # fixing some warnings (perl -w should be quiet)
3050 #
3051 # Revision 1.136  2006/01/10 17:01:29  tipaul
3052 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3053 #
3054 # Revision 1.135  2006/01/06 16:39:37  tipaul
3055 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3056 # Seems not to break too many things, but i'm probably wrong here.
3057 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3058 #
3059 # - removing useless directories (koha-html and koha-plucene)
3060 #
3061 # Revision 1.134  2006/01/04 15:54:55  tipaul
3062 # utf8 is a : go for beta test in HEAD.
3063 # some explanations :
3064 # - updater/updatedatabase => will transform all tables in innoDB (not related to utf8, just to warn you) AND collate them in utf8 / utf8_general_ci. The SQL command is : ALTER TABLE tablename DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci.
3065 # - *-top.inc will show the pages in utf8
3066 # - THE HARD THING : for me, mysql-client and mysql-server were set up to communicate in iso8859-1, whatever the mysql collation ! Thus, pages were improperly shown, as datas were transmitted in iso8859-1 format ! After a full day of investigation, someone on usenet pointed "set NAMES 'utf8'" to explain that I wanted utf8. I could put this in my.cnf, but if I do that, ALL databases will "speak" in utf8, that's not what we want. Thus, I added a line in Context.pm : everytime a DB handle is opened, the communication is set to utf8.
3067 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3068 #
3069 # Revision 1.133  2005/12/12 14:25:51  thd
3070 #
3071 #
3072 # Reverse array filled with elements from repeated subfields
3073 # to avoid last to first concatenation of elements in Koha DB.-
3074 #
3075 # Revision 1.132  2005-10-26 09:12:33  tipaul
3076 # big commit, still breaking things...
3077 #
3078 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3079 # * code cleaning (cleaning warnings from perl -w) continued
3080 #
3081 # Revision 1.131  2005/09/22 10:01:45  tipaul
3082 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3083 #
3084 # Revision 1.130  2005/09/02 14:34:14  tipaul
3085 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3086 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3087 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3088 #
3089 # Revision 1.129  2005/08/12 13:50:31  tipaul
3090 # removing useless sub declarations
3091 #
3092 # Revision 1.128  2005/08/11 16:12:47  tipaul
3093 # Playing with the zebra...
3094 #
3095 # * go to koha cvs home directory
3096 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3097 # * put your zebra.cfg files here & create your database.
3098 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3099 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3100 #
3101 # NOTE :
3102 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3103 # * deletion still not work
3104 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3105 # in zebra.cfg :
3106 # recordId: (bib1,Local-number)
3107 # storeKeys:1
3108 #
3109 # in .abs file :
3110 # elm 090            Local-number            -
3111 # elm 090/?          Local-number            -
3112 # elm 090/?/9        Local-number            !:w
3113 #
3114 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3115 #
3116 # Revision 1.127  2005/08/11 14:37:32  tipaul
3117 # * POD documenting
3118 # * removing useless subs
3119 # * removing some subs that are also elsewhere
3120 # * 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)
3121 #
3122 # Revision 1.126  2005/08/11 09:13:28  tipaul
3123 # just removing useless subs (a lot !!!) for code cleaning
3124 #
3125 # Revision 1.125  2005/08/11 09:00:07  tipaul
3126 # Ok guys, this time, it seems that item add and modif begin working as expected...
3127 # Still a lot of bugs to fix, of course
3128 #
3129 # Revision 1.124  2005/08/10 10:21:15  tipaul
3130 # continuing the road to zebra :
3131 # - the biblio add begins to work.
3132 # - the biblio modif begins to work.
3133 #
3134 # (still without doing anything on zebra)
3135 # (no new change in updatedatabase)
3136 #
3137 # Revision 1.123  2005/08/09 14:10:28  tipaul
3138 # 1st commit to go to zebra.
3139 # don't update your cvs if you want to have a working head...
3140 #
3141 # this commit contains :
3142 # * 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...
3143 # * 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.
3144 # * other files : get rid of bibid and use biblionumber instead.
3145 #
3146 # What is broken :
3147 # * does not do anything on zebra yet.
3148 # * if you rename marc_subfield_table, you can't search anymore.
3149 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3150 # * 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 ;-) )
3151 #
3152 # 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
3153 # 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.
3154
3155 # tipaul cutted previous commit notes