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