New sub to use by Circ2.pm . Allows one subfield of MARC holdings fields to be update...
[koha-ffzg.git] / C4 / Biblio.pm
1 package C4::Biblio;
2
3 # Copyright 2000-2002 Katipo Communications
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA  02111-1307 USA
19
20 use strict;
21 require Exporter;
22 use C4::Context;
23 use C4::Database;
24 use 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
902         #create the marc entry, that stores the rax marc record in Koha 3.0
903         $olddata->{marc} = $record->as_usmarc();
904         $olddata->{marcxml} = $record->as_xml_record();
905         # and create biblioitem, that's all folks !
906     $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
907
908     # search subtiles, addiauthors and subjects
909     ( $tagfield, $tagsubfield ) =
910       MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
911     my @addiauthfields = $record->field($tagfield);
912     foreach my $addiauthfield (@addiauthfields) {
913         my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
914         foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
915             REALmodaddauthor( $dbh, $biblionumber,
916                 $addiauthsubfields[$subfieldcount] );
917         }
918     }
919     ( $tagfield, $tagsubfield ) =
920       MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
921     my @subtitlefields = $record->field($tagfield);
922     foreach my $subtitlefield (@subtitlefields) {
923         my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
924         foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
925             REALnewsubtitle( $dbh, $biblionumber,
926                 $subtitlesubfields[$subfieldcount] );
927         }
928     }
929     ( $tagfield, $tagsubfield ) =
930       MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
931     my @subj = $record->field($tagfield);
932     my @subjects;
933     foreach my $subject (@subj) {
934         my @subjsubfield = $subject->subfield($tagsubfield);
935         foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
936             push @subjects, $subjsubfield[$subfieldcount];
937         }
938     }
939     REALmodsubject( $dbh, $biblionumber, 1, @subjects );
940     return ( $biblionumber, $biblioitemnumber );
941 }
942
943 =head2 NEWmodbilbioframework
944
945 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
946
947 =over 4
948
949 modify the framework of a biblio
950
951 =back
952
953 =cut
954
955 sub NEWmodbiblioframework {
956         my ($dbh,$biblionumber,$frameworkcode) =@_;
957         my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
958         $sth->execute($frameworkcode,$biblionumber);
959         return 1;
960 }
961
962 =head2 NEWmodbiblio
963
964 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
965
966 =over 4
967
968 modify a biblio (MARC=ON)
969
970 =back
971
972 =cut
973
974 sub NEWmodbiblio {
975         my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
976         $frameworkcode="" unless $frameworkcode;
977 #       &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
978         my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
979         
980         $oldbiblio->{frameworkcode} = $frameworkcode;
981         #create the marc entry, that stores the rax marc record in Koha 3.0
982         $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
983         $oldbiblio->{marc} = $record->as_usmarc();
984         $oldbiblio->{marcxml} = $record->as_xml_record();
985         warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
986         REALmodbiblio($dbh,$oldbiblio);
987         REALmodbiblioitem($dbh,$oldbiblio);
988         # now, modify addi authors, subject, addititles.
989         my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
990         my @addiauthfields = $record->field($tagfield);
991         foreach my $addiauthfield (@addiauthfields) {
992                 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
993                 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
994                 foreach my $subfieldcount (0..$#addiauthsubfields) {
995                         REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
996                 }
997         }
998         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
999         my @subtitlefields = $record->field($tagfield);
1000         foreach my $subtitlefield (@subtitlefields) {
1001                 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
1002                 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
1003                 # between 2 modifs
1004                 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
1005                 foreach my $subfieldcount (0..$#subtitlesubfields) {
1006                         foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
1007                                 REALnewsubtitle($dbh,$biblionumber,$subtit);
1008                         }
1009                 }
1010         }
1011         ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
1012         my @subj = $record->field($tagfield);
1013         my @subjects;
1014         foreach my $subject (@subj) {
1015                 my @subjsubfield = $subject->subfield($tagsubfield);
1016                 foreach my $subfieldcount (0..$#subjsubfield) {
1017                         push @subjects,$subjsubfield[$subfieldcount];
1018                 }
1019         }
1020         REALmodsubject($dbh,$biblionumber,1,@subjects);
1021         return 1;
1022 }
1023
1024 =head2 NEWmodbilbioframework
1025
1026 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
1027
1028 =over 4
1029
1030 delete a biblio
1031
1032 =back
1033
1034 =cut
1035
1036 sub NEWdelbiblio {
1037     my ( $dbh, $bibid ) = @_;
1038 #    my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1039     &REALdelbiblio( $dbh, $bibid );
1040     my $sth =
1041       $dbh->prepare(
1042         "select biblioitemnumber from biblioitems where biblionumber=?");
1043     $sth->execute($bibid);
1044     while ( my ($biblioitemnumber) = $sth->fetchrow ) {
1045         REALdelbiblioitem( $dbh, $biblioitemnumber );
1046     }
1047 #    &MARCdelbiblio( $dbh, $bibid, 0 );
1048     # delete from zebra
1049     warn "heres the bibid $bibid";
1050 #    my $record = C4::Search::get_record($bibid);
1051     my $record = C4::Search::get_xml_record($bibid);
1052 #    z3950_extended_services('update',set_service_options('update'),$record);
1053     warn "heres the record to delete $bibid";
1054     my $Zconn = C4::Context->Zconn;
1055     my $p = $Zconn->package();
1056     $p->option(action => "recordDelete");
1057     $p->option(record => $record);
1058     $p->send("update");
1059     $p->destroy();
1060 #    z3950_extended_services('update',set_service_options('update','recordDelete',$record));
1061     z3950_extended_services('commit');
1062 }
1063
1064 =head2 NEWnewitem
1065
1066 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
1067
1068 =over 4
1069
1070 creates an item from a MARC::Record
1071
1072 =back
1073
1074 =cut
1075
1076 sub NEWnewitem {
1077     my ( $dbh,$record,$biblionumber,$biblioitemnumber ) = @_;
1078     warn "here is the $biblioitemnumber";
1079     # add item in old-DB
1080         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1081     my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
1082     # needs old biblionumber and biblioitemnumber
1083     $item->{'biblionumber'} = $biblionumber;
1084     $item->{'biblioitemnumber'}=$biblioitemnumber;
1085     $item->{marc} = $record->as_usmarc();
1086     #warn $item->{marc};
1087     my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
1088         return $itemnumber;
1089 }
1090
1091
1092 =head2 NEWmoditem
1093
1094 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1095
1096 =over 4
1097
1098 Modify an item
1099
1100 =back
1101
1102 =cut
1103
1104 sub NEWmoditem {
1105     my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1106     
1107         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1108     my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1109         # add MARC record
1110         $olditem->{marc} = $record->as_usmarc();
1111         $olditem->{biblionumber} = $biblionumber;
1112         $olditem->{biblioitemnumber} = $biblioitemnumber;
1113         # and modify item
1114     REALmoditem( $dbh, $olditem );
1115 }
1116
1117
1118 =head2 NEWdelitem
1119
1120 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1121
1122 =over 4
1123
1124 delete an item
1125
1126 =back
1127
1128 =cut
1129
1130 sub NEWdelitem {
1131     my ( $dbh, $bibid, $itemnumber ) = @_;
1132     &REALdelitem( $dbh, $itemnumber );
1133 #    &MARCdelitem( $dbh, $bibid, $itemnumber );
1134     # we must now delete the item data from zebra
1135 }
1136
1137
1138 =head2 REALnewbiblio
1139
1140 $biblionumber = REALnewbiblio($dbh,$biblio);
1141
1142 =over 4
1143
1144 adds a record in biblio table. Datas are in the hash $biblio.
1145
1146 =back
1147
1148 =cut
1149
1150 sub REALnewbiblio {
1151     my ( $dbh, $biblio ) = @_;
1152
1153         $dbh->do('lock tables biblio WRITE');
1154     my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1155     $sth->execute;
1156     my $data   = $sth->fetchrow_arrayref;
1157     my $bibnum = $$data[0] + 1;
1158     my $series = 0;
1159
1160     if ( $biblio->{'seriestitle'} ) { $series = 1 }
1161     $sth->finish;
1162     $sth =
1163       $dbh->prepare("insert into biblio set     biblionumber=?, title=?,                author=?,       copyrightdate=?,
1164                                                                                         serial=?,               seriestitle=?,  notes=?,        abstract=?,
1165                                                                                         unititle=?"
1166     );
1167     $sth->execute(
1168         $bibnum,             $biblio->{'title'},
1169         $biblio->{'author'}, $biblio->{'copyrightdate'},
1170         $biblio->{'serial'},             $biblio->{'seriestitle'},
1171         $biblio->{'notes'},  $biblio->{'abstract'},
1172                 $biblio->{'unititle'}
1173     );
1174
1175     $sth->finish;
1176         $dbh->do('unlock tables');
1177     return ($bibnum);
1178 }
1179
1180 =head2 REALmodbiblio
1181
1182 $biblionumber = REALmodbiblio($dbh,$biblio);
1183
1184 =over 4
1185
1186 modify a record in biblio table. Datas are in the hash $biblio.
1187
1188 =back
1189
1190 =cut
1191
1192 sub REALmodbiblio {
1193     my ( $dbh, $biblio ) = @_;
1194     my $sth = $dbh->prepare("Update biblio set  title=?,                author=?,       abstract=?,     copyrightdate=?,
1195                                                                                                 seriestitle=?,  serial=?,       unititle=?,     notes=?,        frameworkcode=? 
1196                                                                                         where biblionumber = ?"
1197     );
1198     $sth->execute(
1199                 $biblio->{'title'},       $biblio->{'author'},
1200                 $biblio->{'abstract'},    $biblio->{'copyrightdate'},
1201                 $biblio->{'seriestitle'}, $biblio->{'serial'},
1202                 $biblio->{'unititle'},    $biblio->{'notes'},
1203                 $biblio->{frameworkcode},
1204                 $biblio->{'biblionumber'}
1205     );
1206         $sth->finish;
1207         return ( $biblio->{'biblionumber'} );
1208 }    # sub modbiblio
1209
1210 =head2 REALmodsubtitle
1211
1212 REALmodsubtitle($dbh,$bibnum,$subtitle);
1213
1214 =over 4
1215
1216 modify subtitles in bibliosubtitle table.
1217
1218 =back
1219
1220 =cut
1221
1222 sub REALmodsubtitle {
1223     my ( $dbh, $bibnum, $subtitle ) = @_;
1224     my $sth =
1225       $dbh->prepare(
1226         "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1227     $sth->execute( $subtitle, $bibnum );
1228     $sth->finish;
1229 }    # sub modsubtitle
1230
1231 =head2 REALmodaddauthor
1232
1233 REALmodaddauthor($dbh,$bibnum,$author);
1234
1235 =over 4
1236
1237 adds or modify additional authors
1238 NOTE :  Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1239
1240 =back
1241
1242 =cut
1243
1244 sub REALmodaddauthor {
1245     my ( $dbh, $bibnum, @authors ) = @_;
1246
1247     #    my $dbh   = C4Connect;
1248     my $sth =
1249       $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1250
1251     $sth->execute($bibnum);
1252     $sth->finish;
1253     foreach my $author (@authors) {
1254         if ( $author ne '' ) {
1255             $sth =
1256               $dbh->prepare(
1257                 "Insert into additionalauthors set author = ?, biblionumber = ?"
1258             );
1259
1260             $sth->execute( $author, $bibnum );
1261
1262             $sth->finish;
1263         }    # if
1264     }
1265 }    # sub modaddauthor
1266
1267 =head2 REALmodsubject
1268
1269 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1270
1271 =over 4
1272
1273 modify/adds subjects
1274
1275 =back
1276
1277 =cut
1278 sub REALmodsubject {
1279     my ( $dbh, $bibnum, $force, @subject ) = @_;
1280
1281     #  my $dbh   = C4Connect;
1282     my $count = @subject;
1283     my $error="";
1284     for ( my $i = 0 ; $i < $count ; $i++ ) {
1285         $subject[$i] =~ s/^ //g;
1286         $subject[$i] =~ s/ $//g;
1287         my $sth =
1288           $dbh->prepare(
1289 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1290         );
1291         $sth->execute( $subject[$i] );
1292
1293         if ( my $data = $sth->fetchrow_hashref ) {
1294         }
1295         else {
1296             if ( $force eq $subject[$i] || $force == 1 ) {
1297
1298                 # subject not in aut, chosen to force anway
1299                 # so insert into cataloguentry so its in auth file
1300                 my $sth2 =
1301                   $dbh->prepare(
1302 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1303                 );
1304
1305                 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1306                 $sth2->finish;
1307             }
1308             else {
1309                 $error =
1310                   "$subject[$i]\n does not exist in the subject authority file";
1311                 my $sth2 =
1312                   $dbh->prepare(
1313 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1314                 );
1315                 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1316                     "% $subject[$i]" );
1317                 while ( my $data = $sth2->fetchrow_hashref ) {
1318                     $error .= "<br>$data->{'catalogueentry'}";
1319                 }    # while
1320                 $sth2->finish;
1321             }    # else
1322         }    # else
1323         $sth->finish;
1324     }    # else
1325     if ($error eq '') {
1326         my $sth =
1327           $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1328         $sth->execute($bibnum);
1329         $sth->finish;
1330         $sth =
1331           $dbh->prepare(
1332             "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1333         my $query;
1334         foreach $query (@subject) {
1335             $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1336         }    # foreach
1337         $sth->finish;
1338     }    # if
1339
1340     #  $dbh->disconnect;
1341     return ($error);
1342 }    # sub modsubject
1343
1344 =head2 REALmodbiblioitem
1345
1346 REALmodbiblioitem($dbh, $biblioitem);
1347
1348 =over 4
1349
1350 modify a biblioitem
1351
1352 =back
1353
1354 =cut
1355 sub REALmodbiblioitem {
1356     my ( $dbh, $biblioitem ) = @_;
1357     my $query;
1358
1359     my $sth = $dbh->prepare("update biblioitems set number=?,volume=?,                  volumedate=?,           lccn=?,
1360                                                                                 itemtype=?,                     url=?,                          isbn=?,                         issn=?,
1361                                                                                 publishercode=?,        publicationyear=?,      classification=?,       dewey=?,
1362                                                                                 subclass=?,                     illus=?,                        pages=?,                        volumeddesc=?,
1363                                                                                 notes=?,                        size=?,                         place=?,                        marc=?,
1364                                                                                 marcxml=?
1365                                                         where biblioitemnumber=?");
1366         $sth->execute(  $biblioitem->{number},                  $biblioitem->{volume},  $biblioitem->{volumedate},      $biblioitem->{lccn},
1367                                         $biblioitem->{itemtype},                $biblioitem->{url},             $biblioitem->{isbn},    $biblioitem->{issn},
1368                                 $biblioitem->{publishercode},   $biblioitem->{publicationyear}, $biblioitem->{classification},  $biblioitem->{dewey},
1369                                 $biblioitem->{subclass},                $biblioitem->{illus},           $biblioitem->{pages},   $biblioitem->{volumeddesc},
1370                                 $biblioitem->{bnotes},                  $biblioitem->{size},            $biblioitem->{place},   $biblioitem->{marc},
1371                                         $biblioitem->{marcxml},                 $biblioitem->{biblioitemnumber});
1372
1373         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1374
1375         z3950_extended_services('update',set_service_options('update'),$record);
1376         z3950_extended_services('commit');
1377
1378
1379 #       warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1380 }    # sub modbibitem
1381
1382 =head2 REALnewbiblioitem
1383
1384 REALnewbiblioitem($dbh,$biblioitem);
1385
1386 =over 4
1387
1388 adds a biblioitem ($biblioitem is a hash with the values)
1389
1390 =back
1391
1392 =cut
1393
1394 sub REALnewbiblioitem {
1395         my ( $dbh, $biblioitem ) = @_;
1396
1397         $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1398         my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1399         my $data;
1400         my $biblioitemnumber;
1401
1402         $sth->execute;
1403         $data       = $sth->fetchrow_arrayref;
1404         $biblioitemnumber = $$data[0] + 1;
1405         
1406         # Insert biblioitemnumber in MARC record, we need it to manage items later...
1407         my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1408         my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1409         my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1410         my $field=$record->field($biblioitemnumberfield);
1411         $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1412         $biblioitem->{marc} = $record->as_usmarc();
1413         $biblioitem->{marcxml} = $record->as_xml_record();
1414
1415         $sth = $dbh->prepare( "insert into biblioitems set
1416                                                                         biblioitemnumber = ?,           biblionumber     = ?,
1417                                                                         volume           = ?,                   number           = ?,
1418                                                                         classification  = ?,                    itemtype         = ?,
1419                                                                         url              = ?,                           isbn             = ?,
1420                                                                         issn             = ?,                           dewey            = ?,
1421                                                                         subclass         = ?,                           publicationyear  = ?,
1422                                                                         publishercode    = ?,           volumedate       = ?,
1423                                                                         volumeddesc      = ?,           illus            = ?,
1424                                                                         pages            = ?,                           notes            = ?,
1425                                                                         size             = ?,                           lccn             = ?,
1426                                                                         marc             = ?,                           place            = ?,
1427                                                                         marcxml          = ?"
1428         );
1429         $sth->execute(
1430                 $biblioitemnumber,               $biblioitem->{'biblionumber'},
1431                 $biblioitem->{'volume'},         $biblioitem->{'number'},
1432                 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1433                 $biblioitem->{'url'},            $biblioitem->{'isbn'},
1434                 $biblioitem->{'issn'},           $biblioitem->{'dewey'},
1435                 $biblioitem->{'subclass'},       $biblioitem->{'publicationyear'},
1436                 $biblioitem->{'publishercode'},  $biblioitem->{'volumedate'},
1437                 $biblioitem->{'volumeddesc'},    $biblioitem->{'illus'},
1438                 $biblioitem->{'pages'},          $biblioitem->{'bnotes'},
1439                 $biblioitem->{'size'},           $biblioitem->{'lccn'},
1440                 $biblioitem->{'marc'},           $biblioitem->{'place'},
1441                 $biblioitem->{marcxml},
1442         );
1443         $dbh->do("unlock tables");
1444         z3950_extended_services('update',set_service_options('update'),$record);
1445         z3950_extended_services('commit');
1446         return ($biblioitemnumber);
1447 }
1448
1449 =head2 REALnewsubtitle
1450
1451 REALnewsubtitle($dbh,$bibnum,$subtitle);
1452
1453 =over 4
1454
1455 create a new subtitle
1456
1457 =back
1458
1459 =cut
1460 sub REALnewsubtitle {
1461     my ( $dbh, $bibnum, $subtitle ) = @_;
1462     my $sth =
1463       $dbh->prepare(
1464         "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1465     $sth->execute( $bibnum, $subtitle ) if $subtitle;
1466     $sth->finish;
1467 }
1468
1469 =head2 REALnewitems
1470
1471 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1472
1473 =over 4
1474
1475 create a item. $item is a hash and $barcode the barcode.
1476
1477 =back
1478
1479 =cut
1480
1481 sub REALnewitems {
1482     my ( $dbh, $item, $barcode ) = @_;
1483
1484 #       warn "OLDNEWITEMS";
1485         
1486         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1487     my $sth = $dbh->prepare("Select max(itemnumber) from items");
1488     my $data;
1489     my $itemnumber;
1490     my $error = "";
1491     $sth->execute;
1492     $data       = $sth->fetchrow_hashref;
1493     $itemnumber = $data->{'max(itemnumber)'} + 1;
1494
1495 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1496     if ( $item->{'loan'} ) {
1497         $item->{'notforloan'} = $item->{'loan'};
1498     }
1499 #       $item->{'biblioitemnumber'} = 1;
1500     # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1501     if ( $item->{'dateaccessioned'} ) {
1502         $sth = $dbh->prepare( "Insert into items set
1503                                                         itemnumber           = ?,                       biblionumber         = ?,
1504                                                         multivolumepart      = ?,
1505                                                         biblioitemnumber     = ?,                       barcode              = ?,
1506                                                         booksellerid         = ?,                       dateaccessioned      = ?,
1507                                                         homebranch           = ?,                       holdingbranch        = ?,
1508                                                         price                = ?,                       replacementprice     = ?,
1509                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1510                                                         multivolume                     = ?,                    stack                           = ?,
1511                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1512                                                         paidfor                         = ?,                    itemnotes            = ?,
1513                                                         itemcallnumber  =?,                                                     notforloan = ?,
1514                                                         location = ?
1515                                                         "
1516         );
1517         $sth->execute(
1518                         $itemnumber,                            $item->{'biblionumber'},
1519                         $item->{'multivolumepart'},
1520                         $item->{'biblioitemnumber'},$item->{barcode},
1521                         $item->{'booksellerid'},        $item->{'dateaccessioned'},
1522                         $item->{'homebranch'},          $item->{'holdingbranch'},
1523                         $item->{'price'},                       $item->{'replacementprice'},
1524                         $item->{multivolume},           $item->{stack},
1525                         $item->{itemlost},                      $item->{wthdrawn},
1526                         $item->{paidfor},                       $item->{'itemnotes'},
1527                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1528                         $item->{'location'}
1529         );
1530                 if ( defined $sth->errstr ) {
1531                         $error .= $sth->errstr;
1532                 }
1533     }
1534     else {
1535         $sth = $dbh->prepare( "Insert into items set
1536                                                         itemnumber           = ?,                       biblionumber         = ?,
1537                                                         multivolumepart      = ?,
1538                                                         biblioitemnumber     = ?,                       barcode              = ?,
1539                                                         booksellerid         = ?,                       dateaccessioned      = NOW(),
1540                                                         homebranch           = ?,                       holdingbranch        = ?,
1541                                                         price                = ?,                       replacementprice     = ?,
1542                                                         replacementpricedate = NOW(),           datelastseen            = NOW(),
1543                                                         multivolume                     = ?,                    stack                           = ?,
1544                                                         itemlost                        = ?,                    wthdrawn                        = ?,
1545                                                         paidfor                         = ?,                    itemnotes            = ?,
1546                                                         itemcallnumber  =?,                                                     notforloan = ?,
1547                                                         location = ?
1548                                                         "
1549         );
1550         $sth->execute(
1551                         $itemnumber,                            $item->{'biblionumber'},
1552                         $item->{'multivolumepart'},
1553                         $item->{'biblioitemnumber'},$item->{barcode},
1554                         $item->{'booksellerid'},
1555                         $item->{'homebranch'},          $item->{'holdingbranch'},
1556                         $item->{'price'},                       $item->{'replacementprice'},
1557                         $item->{multivolume},           $item->{stack},
1558                         $item->{itemlost},                      $item->{wthdrawn},
1559                         $item->{paidfor},                       $item->{'itemnotes'},
1560                         $item->{'itemcallnumber'},      $item->{'notforloan'},
1561                         $item->{'location'}
1562         );
1563                 if ( defined $sth->errstr ) {
1564                         $error .= $sth->errstr;
1565                 }
1566     }
1567         # item stored, now, deal with the marc part...
1568         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1569                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1570                                                                         biblio.biblionumber=?");
1571         $sth->execute($item->{biblionumber});
1572     if ( defined $sth->errstr ) {
1573         $error .= $sth->errstr;
1574     }
1575         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1576         warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1577         my $record = MARC::File::USMARC::decode($rawmarc);
1578         # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1579         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1580         my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1581         #warn $itemrecord;
1582         #warn $itemnumberfield;
1583         #warn $itemrecord->field($itemnumberfield);
1584         my $itemfield = $itemrecord->field($itemnumberfield);
1585         $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1586         $record->insert_grouped_field($itemfield);
1587         # save the record into biblioitem
1588         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1589         $sth->execute($record->as_usmarc(),$record->as_xml_record(),$item->{biblionumber});
1590     if ( defined $sth->errstr ) {
1591         $error .= $sth->errstr;
1592     }
1593         z3950_extended_services('update',set_service_options('update'),$record);
1594         z3950_extended_services('commit');
1595         $dbh->do('unlock tables');
1596     return ( $itemnumber, $error );
1597 }
1598
1599 =head2 REALmoditem($dbh,$item);
1600
1601 =over 4
1602
1603 modify item
1604
1605 =back
1606
1607 =cut
1608
1609 sub REALmoditem {
1610     my ( $dbh, $item ) = @_;
1611     $item->{'bibitemnum'} = 1;
1612         my $error;
1613         $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1614     $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1615     my $query = "update items set  barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1616     my @bind = (
1617         $item->{'barcode'},                     $item->{'itemnotes'},
1618         $item->{'itemcallnumber'},      $item->{'notforloan'},
1619         $item->{'location'},            $item->{multivolumepart},
1620                 $item->{multivolume},           $item->{stack},
1621                 $item->{wthdrawn},
1622     );
1623     if ( $item->{'lost'} ne '' ) {
1624         $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1625                                                         itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1626                                                         location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1627         @bind = (
1628             $item->{'bibitemnum'},     $item->{'barcode'},
1629             $item->{'itemnotes'},          $item->{'homebranch'},
1630             $item->{'lost'},           $item->{'wthdrawn'},
1631             $item->{'itemcallnumber'}, $item->{'notforloan'},
1632             $item->{'location'},                $item->{multivolumepart},
1633                         $item->{multivolume},           $item->{stack},
1634                         $item->{wthdrawn},
1635         );
1636                 if ($item->{homebranch}) {
1637                         $query.=",homebranch=?";
1638                         push @bind, $item->{homebranch};
1639                 }
1640                 if ($item->{holdingbranch}) {
1641                         $query.=",holdingbranch=?";
1642                         push @bind, $item->{holdingbranch};
1643                 }
1644     }
1645         $query.=" where itemnumber=?";
1646         push @bind,$item->{'itemnum'};
1647    if ( $item->{'replacement'} ne '' ) {
1648         $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1649     }
1650     my $sth = $dbh->prepare($query);
1651     $sth->execute(@bind);
1652         
1653         # item stored, now, deal with the marc part...
1654         $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio 
1655                                                         where   biblio.biblionumber=biblioitems.biblionumber and 
1656                                                                         biblio.biblionumber=? and 
1657                                                                         biblioitems.biblioitemnumber=?");
1658         $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1659     if ( defined $sth->errstr ) {
1660         $error .= $sth->errstr;
1661     }
1662         my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1663 #       warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1664 #       my $record = MARC::File::USMARC::decode($rawmarc);
1665         my $record=C4::Search::get_record($item->{biblionumber});
1666 ####$record
1667         # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1668         my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1669         # prepare the new item record
1670         my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1671         my $itemfield = $itemrecord->field($itemnumberfield);
1672
1673 #       $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1674         # parse all fields fields from the complete record
1675         foreach ($record->field($itemnumberfield)) {
1676                 # when the previous field is found, replace by the new one
1677                 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1678                         $_->replace_with($itemfield);
1679                 }
1680             else {
1681                 my $temptest = $_->subfield($itemnumbersubfield);
1682                 warn " failed itemnum is $item->{itemnum} and value in record is $temptest";
1683                 }
1684         }
1685 #       $record->insert_grouped_field($itemfield);
1686         # save the record into biblioitem
1687         $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1688         $sth->execute($record->as_usmarc(),$record->as_xml_record(),$item->{biblionumber},$item->{biblioitemnumber});
1689         z3950_extended_services('update',set_service_options('update'),$record);
1690         z3950_extended_services('commit');
1691     if ( defined $sth->errstr ) {
1692         $error .= $sth->errstr;
1693     }
1694         $dbh->do('unlock tables');
1695
1696 }
1697
1698 =head2 REALdelitem($dbh,$itemnum);
1699
1700 =over 4
1701
1702 delete item
1703
1704 =back
1705
1706 =cut
1707
1708 sub REALdelitem {
1709     my ( $dbh, $itemnum ) = @_;
1710
1711     #  my $dbh=C4Connect;
1712     my $sth = $dbh->prepare("select * from items where itemnumber=?");
1713     $sth->execute($itemnum);
1714     my $data = $sth->fetchrow_hashref;
1715     $sth->finish;
1716     my $query = "Insert into deleteditems set ";
1717     my @bind  = ();
1718     foreach my $temp ( keys %$data ) {
1719         $query .= "$temp = ?,";
1720         push ( @bind, $data->{$temp} );
1721     }
1722     $query =~ s/\,$//;
1723
1724     #  print $query;
1725     $sth = $dbh->prepare($query);
1726     $sth->execute(@bind);
1727     $sth->finish;
1728     $sth = $dbh->prepare("Delete from items where itemnumber=?");
1729     $sth->execute($itemnum);
1730     $sth->finish;
1731
1732     #  $dbh->disconnect;
1733 }
1734
1735 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1736
1737 =over 4
1738
1739 deletes a biblioitem
1740 NOTE : not standard sub name. Should be REALdelbiblioitem()
1741
1742 =back
1743
1744 =cut
1745
1746 sub REALdelbiblioitem {
1747     my ( $dbh, $biblioitemnumber ) = @_;
1748
1749     #    my $dbh   = C4Connect;
1750     my $sth = $dbh->prepare( "Select * from biblioitems
1751 where biblioitemnumber = ?"
1752     );
1753     my $results;
1754
1755     $sth->execute($biblioitemnumber);
1756
1757     if ( $results = $sth->fetchrow_hashref ) {
1758         $sth->finish;
1759         $sth =
1760           $dbh->prepare(
1761 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1762                                         isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1763                                         pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1764         );
1765
1766         $sth->execute(
1767             $results->{biblioitemnumber}, $results->{biblionumber},
1768             $results->{volume},           $results->{number},
1769             $results->{classification},   $results->{itemtype},
1770             $results->{isbn},             $results->{issn},
1771             $results->{dewey},            $results->{subclass},
1772             $results->{publicationyear},  $results->{publishercode},
1773             $results->{volumedate},       $results->{volumeddesc},
1774             $results->{timestamp},        $results->{illus},
1775             $results->{pages},            $results->{notes},
1776             $results->{size},             $results->{url},
1777             $results->{lccn}
1778         );
1779         my $sth2 =
1780           $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1781         $sth2->execute($biblioitemnumber);
1782         $sth2->finish();
1783     }    # if
1784     $sth->finish;
1785
1786     # Now delete all the items attached to the biblioitem
1787     $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1788     $sth->execute($biblioitemnumber);
1789     my @results;
1790     while ( my $data = $sth->fetchrow_hashref ) {
1791         my $query = "Insert into deleteditems set ";
1792         my @bind  = ();
1793         foreach my $temp ( keys %$data ) {
1794             $query .= "$temp = ?,";
1795             push ( @bind, $data->{$temp} );
1796         }
1797         $query =~ s/\,$//;
1798         my $sth2 = $dbh->prepare($query);
1799         $sth2->execute(@bind);
1800     }    # while
1801     $sth->finish;
1802     $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1803     $sth->execute($biblioitemnumber);
1804     $sth->finish();
1805
1806     #    $dbh->disconnect;
1807 }    # sub deletebiblioitem
1808
1809 =head2 REALdelbiblio($dbh,$biblio);
1810
1811 =over 4
1812
1813 delete a biblio
1814
1815 =back
1816
1817 =cut
1818
1819 sub REALdelbiblio {
1820     my ( $dbh, $biblio ) = @_;
1821     my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1822     $sth->execute($biblio);
1823     if ( my $data = $sth->fetchrow_hashref ) {
1824         $sth->finish;
1825         my $query = "Insert into deletedbiblio set ";
1826         my @bind  = ();
1827         foreach my $temp ( keys %$data ) {
1828             $query .= "$temp = ?,";
1829             push ( @bind, $data->{$temp} );
1830         }
1831
1832         #replacing the last , by ",?)"
1833         $query =~ s/\,$//;
1834         $sth = $dbh->prepare($query);
1835         $sth->execute(@bind);
1836         $sth->finish;
1837         $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1838         $sth->execute($biblio);
1839         $sth->finish;
1840     }
1841     $sth->finish;
1842 }
1843
1844 =head2 itemcount
1845
1846 $number = itemcount($biblio);
1847
1848 =over 4
1849
1850 returns the number of items attached to a biblio
1851
1852 =back
1853
1854 =cut
1855
1856 sub itemcount {
1857     my ($biblio) = @_;
1858     my $dbh = C4::Context->dbh;
1859
1860     #  print $query;
1861     my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1862     $sth->execute($biblio);
1863     my $data = $sth->fetchrow_hashref;
1864     $sth->finish;
1865     return ( $data->{'count(*)'} );
1866 }
1867
1868 =head2 newbiblio
1869
1870 $biblionumber = newbiblio($biblio);
1871
1872 =over 4
1873
1874 create a biblio. The parameter is a hash
1875
1876 =back
1877
1878 =cut
1879
1880 sub newbiblio {
1881     my ($biblio) = @_;
1882     my $dbh    = C4::Context->dbh;
1883     my $bibnum = REALnewbiblio( $dbh, $biblio );
1884     # finds new (MARC bibid
1885     #   my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1886 #     my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1887 #     MARCaddbiblio( $dbh, $record, $bibnum,'' );
1888     return ($bibnum);
1889 }
1890
1891 =head2  modbiblio
1892
1893 $biblionumber = &modbiblio($biblio);
1894
1895 =over 4
1896
1897 Update a biblio record.
1898
1899 C<$biblio> is a reference-to-hash whose keys are the fields in the
1900 biblio table in the Koha database. All fields must be present, not
1901 just the ones you wish to change.
1902
1903 C<&modbiblio> updates the record defined by
1904 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1905
1906 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1907 successful or not.
1908
1909 =back
1910
1911 =cut
1912
1913 sub modbiblio {
1914         my ($biblio) = @_;
1915         my $dbh  = C4::Context->dbh;
1916         my $biblionumber=REALmodbiblio($dbh,$biblio);
1917         my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1918         # finds new (MARC bibid
1919         my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1920         MARCmodbiblio($dbh,$bibid,$record,"",0);
1921         return($biblionumber);
1922 } # sub modbiblio
1923
1924 =head2 &modsubtitle($biblionumber, $subtitle);
1925
1926 =over 4
1927
1928 Sets the subtitle of a book.
1929
1930 C<$biblionumber> is the biblionumber of the book to modify.
1931
1932 C<$subtitle> is the new subtitle.
1933
1934 =back
1935
1936 =cut
1937
1938 sub modsubtitle {
1939     my ( $bibnum, $subtitle ) = @_;
1940     my $dbh = C4::Context->dbh;
1941     &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1942 }    # sub modsubtitle
1943
1944 =head2 &modaddauthor($biblionumber, $author);
1945
1946 =over 4
1947
1948 Replaces all additional authors for the book with biblio number
1949 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1950 C<&modaddauthor> deletes all additional authors.
1951
1952 =back
1953
1954 =cut
1955
1956 sub modaddauthor {
1957     my ( $bibnum, @authors ) = @_;
1958     my $dbh = C4::Context->dbh;
1959     &REALmodaddauthor( $dbh, $bibnum, @authors );
1960 }    # sub modaddauthor
1961
1962 =head2 modsubject
1963
1964 $error = &modsubject($biblionumber, $force, @subjects);
1965
1966 =over 4
1967
1968 $force - a subject to force
1969 $error - Error message, or undef if successful.
1970
1971 =back
1972
1973 =cut
1974
1975 sub modsubject {
1976     my ( $bibnum, $force, @subject ) = @_;
1977     my $dbh = C4::Context->dbh;
1978     my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1979     if ($error eq ''){
1980                 # When MARC is off, ensures that the MARC biblio table gets updated with new
1981                 # subjects, of course, it deletes the biblio in marc, and then recreates.
1982                 # This check is to ensure that no MARC data exists to lose.
1983 #               if (C4::Context->preference("MARC") eq '0'){
1984 #               warn "in modSUBJECT";
1985 #                       my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1986 #                       my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1987 #                       &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1988 #               }
1989         }
1990         return ($error);
1991 }    # sub modsubject
1992
1993 =head2 modbibitem($dbh, $biblioitem);
1994
1995 =over 4
1996
1997 modify a biblioitem. The parameter is a hash
1998
1999 =back
2000
2001 =cut
2002
2003 sub modbibitem {
2004     my ($dbh, $biblioitem) = @_;
2005     #my $dbh = C4::Context->dbh;
2006     &REALmodbiblioitem( $dbh, $biblioitem );
2007 }    # sub modbibitem
2008
2009 =head2 newbiblioitem
2010
2011 $biblioitemnumber = newbiblioitem($biblioitem)
2012
2013 =over 4
2014
2015 create a biblioitem, the parameter is a hash
2016
2017 =back
2018
2019 =cut
2020
2021 sub newbiblioitem {
2022     my ($dbh, $biblioitem) = @_;
2023     #my $dbh        = C4::Context->dbh;
2024         # add biblio information to the hash
2025     my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
2026         $biblioitem->{marc} = $MARCbiblio->as_usmarc();
2027     my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
2028     return ($bibitemnum);
2029 }
2030
2031 =head2 newsubtitle($biblionumber,$subtitle);
2032
2033 =over 4
2034
2035 insert a subtitle for $biblionumber biblio
2036
2037 =back
2038
2039 =cut
2040
2041
2042 sub newsubtitle {
2043     my ( $bibnum, $subtitle ) = @_;
2044     my $dbh = C4::Context->dbh;
2045     &REALnewsubtitle( $dbh, $bibnum, $subtitle );
2046 }
2047
2048 =head2 newitems
2049
2050 $errors = newitems($dbh, $item, @barcodes);
2051
2052 =over 4
2053
2054 insert items ($item is a hash)
2055
2056 =back
2057
2058 =cut
2059
2060
2061 sub newitems {
2062     my ( $dbh, $item, @barcodes ) = @_;
2063     #my $dbh = C4::Context->dbh;
2064     my $errors;
2065     my $itemnumber;
2066     my $error;
2067     foreach my $barcode (@barcodes) {
2068                 # add items, one by one for each barcode.
2069                 my $oneitem=$item;
2070                 $oneitem->{barcode}= $barcode;
2071         my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
2072                 $oneitem->{marc} = $MARCitem->as_usmarc;
2073         ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
2074 #         $errors .= $error;
2075 #         &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
2076     }
2077     return ($errors);
2078 }
2079
2080 =head2 moditem($dbh,$item);
2081
2082 =over 4
2083
2084 modify an item ($item is a hash with all item informations)
2085
2086 =back
2087
2088 =cut
2089
2090
2091 sub moditem {
2092     my ($dbh, $item) = @_;
2093     #my $dbh = C4::Context->dbh;
2094     &REALmoditem( $dbh, $item );
2095     my $MARCitem =
2096       &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
2097     my $bibid =
2098       &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
2099     &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
2100 }
2101
2102 =head2 checkitems
2103
2104 $error = checkitems($count,@barcodes);
2105
2106 =over 4
2107
2108 check for each @barcode entry that the barcode is not a duplicate
2109
2110 =back
2111
2112 =cut
2113
2114 sub checkitems {
2115     my ( $count, @barcodes ) = @_;
2116     my $dbh = C4::Context->dbh;
2117     my $error;
2118     my $sth = $dbh->prepare("Select * from items where barcode=?");
2119     for ( my $i = 0 ; $i < $count ; $i++ ) {
2120         $barcodes[$i] = uc $barcodes[$i];
2121         $sth->execute( $barcodes[$i] );
2122         if ( my $data = $sth->fetchrow_hashref ) {
2123             $error .= " Duplicate Barcode: $barcodes[$i]";
2124         }
2125     }
2126     $sth->finish;
2127     return ($error);
2128 }
2129
2130 =head2 delitem($itemnum);
2131
2132 =over 4
2133
2134 delete item $itemnum being the item number to delete
2135
2136 =back
2137
2138 =cut
2139
2140 sub delitem {
2141     my ($itemnum) = @_;
2142     my $dbh = C4::Context->dbh;
2143     &REALdelitem( $dbh, $itemnum );
2144 }
2145
2146 =head2 deletebiblioitem($biblioitemnumber);
2147
2148 =over 4
2149
2150 delete the biblioitem $biblioitemnumber
2151
2152 =back
2153
2154 =cut
2155
2156 sub deletebiblioitem {
2157     my ($biblioitemnumber) = @_;
2158     my $dbh = C4::Context->dbh;
2159     &REALdelbiblioitem( $dbh, $biblioitemnumber );
2160 }    # sub deletebiblioitem
2161
2162 =head2 delbiblio($biblionumber)
2163
2164 =over 4
2165
2166 delete biblio $biblionumber
2167
2168 =back
2169
2170 =cut
2171
2172 sub delbiblio {
2173     my ($biblio) = @_;
2174     my $dbh = C4::Context->dbh;
2175     &REALdelbiblio( $dbh, $biblio );
2176     my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2177     &MARCdelbiblio( $dbh, $bibid, 0 );
2178 }
2179
2180 =head2 getbiblio
2181
2182 ($count,@results) = getbiblio($biblionumber);
2183
2184 =over 4
2185
2186 return an array with hash of biblios.
2187
2188 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2189
2190 =back
2191
2192 =cut
2193
2194 sub getbiblio {
2195     my ($biblionumber) = @_;
2196     my $dbh = C4::Context->dbh;
2197     my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2198
2199     # || die "Cannot prepare $query\n" . $dbh->errstr;
2200     my $count = 0;
2201     my @results;
2202
2203     $sth->execute($biblionumber);
2204
2205     # || die "Cannot execute $query\n" . $sth->errstr;
2206     while ( my $data = $sth->fetchrow_hashref ) {
2207         $results[$count] = $data;
2208         $count++;
2209     }    # while
2210
2211     $sth->finish;
2212     return ( $count, @results );
2213 }    # sub getbiblio
2214
2215 =head2 bibdata
2216
2217   $data = &bibdata($biblionumber, $type);
2218
2219 Returns information about the book with the given biblionumber.
2220
2221 C<$type> is ignored.
2222
2223 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2224 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2225 Koha database.
2226
2227 In addition, C<$data-E<gt>{subject}> is the list of the book's
2228 subjects, separated by C<" , "> (space, comma, space).
2229
2230 If there are multiple biblioitems with the given biblionumber, only
2231 the first one is considered.
2232
2233 =cut
2234 #'
2235 sub bibdata {
2236         my ($bibnum, $type) = @_;
2237         my $dbh   = C4::Context->dbh;
2238         my $sth   = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2239                                                                 from biblio 
2240                                                                 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2241                                                                 left join bibliosubtitle on
2242                                                                 biblio.biblionumber = bibliosubtitle.biblionumber
2243                                                                 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2244                                                                 where biblio.biblionumber = ?
2245                                                                 ");
2246         $sth->execute($bibnum);
2247         my $data;
2248         $data  = $sth->fetchrow_hashref;
2249         $sth->finish;
2250         # handle management of repeated subtitle
2251         $sth   = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2252         $sth->execute($bibnum);
2253         my @subtitles;
2254         while (my $dat = $sth->fetchrow_hashref){
2255                 my %line;
2256                 $line{subtitle} = $dat->{subtitle};
2257                 push @subtitles, \%line;
2258         } # while
2259         $data->{subtitles} = \@subtitles;
2260         $sth->finish;
2261         $sth   = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2262         $sth->execute($bibnum);
2263         my @subjects;
2264         while (my $dat = $sth->fetchrow_hashref){
2265                 my %line;
2266                 $line{subject} = $dat->{'subject'};
2267                 push @subjects, \%line;
2268         } # while
2269         $data->{subjects} = \@subjects;
2270         $sth->finish;
2271         $sth   = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2272         $sth->execute($bibnum);
2273         while (my $dat = $sth->fetchrow_hashref){
2274                 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2275         } # while
2276         chop $data->{'additionalauthors'};
2277         chop $data->{'additionalauthors'};
2278         chop $data->{'additionalauthors'};
2279         $sth->finish;
2280         return($data);
2281 } # sub bibdata
2282
2283 =head2 getbiblioitem
2284
2285 ($count,@results) = getbiblioitem($biblioitemnumber);
2286
2287 =over 4
2288
2289 return an array with hash of biblioitemss.
2290
2291 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2292
2293 =back
2294
2295 =cut
2296
2297 sub getbiblioitem {
2298     my ($biblioitemnum) = @_;
2299     my $dbh = C4::Context->dbh;
2300     my $sth = $dbh->prepare( "Select * from biblioitems where
2301 biblioitemnumber = ?"
2302     );
2303     my $count = 0;
2304     my @results;
2305
2306     $sth->execute($biblioitemnum);
2307
2308     while ( my $data = $sth->fetchrow_hashref ) {
2309         $results[$count] = $data;
2310         $count++;
2311     }    # while
2312
2313     $sth->finish;
2314     return ( $count, @results );
2315 }    # sub getbiblioitem
2316
2317 =head2 getbiblioitembybiblionumber
2318
2319 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2320
2321 =over 4
2322
2323 return an array with hash of biblioitems for the given biblionumber.
2324
2325 =back
2326
2327 =cut
2328
2329 sub getbiblioitembybiblionumber {
2330     my ($biblionumber) = @_;
2331     my $dbh = C4::Context->dbh;
2332     my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2333     my $count = 0;
2334     my @results;
2335
2336     $sth->execute($biblionumber);
2337
2338     while ( my $data = $sth->fetchrow_hashref ) {
2339         $results[$count] = $data;
2340         $count++;
2341     }    # while
2342
2343     $sth->finish;
2344     return ( $count, @results );
2345 }    # sub
2346
2347 =head2 getitemsbybiblioitem
2348
2349 ($count,@results) = getitemsbybiblioitem($biblionumber);
2350
2351 =over 4
2352
2353 returns an array with hash of items
2354
2355 =back
2356
2357 =cut
2358
2359 sub getitemsbybiblioitem {
2360     my ($biblioitemnum) = @_;
2361     my $dbh = C4::Context->dbh;
2362     my $sth = $dbh->prepare( "Select * from items, biblio where
2363 biblio.biblionumber = items.biblionumber and biblioitemnumber
2364 = ?"
2365     );
2366
2367     # || die "Cannot prepare $query\n" . $dbh->errstr;
2368     my $count = 0;
2369     my @results;
2370
2371     $sth->execute($biblioitemnum);
2372
2373     # || die "Cannot execute $query\n" . $sth->errstr;
2374     while ( my $data = $sth->fetchrow_hashref ) {
2375         $results[$count] = $data;
2376         $count++;
2377     }    # while
2378
2379     $sth->finish;
2380     return ( $count, @results );
2381 }    # sub getitemsbybiblioitem
2382
2383 =head2 ItemInfo
2384
2385   @results = &ItemInfo($env, $biblionumber, $type);
2386
2387 Returns information about books with the given biblionumber.
2388
2389 C<$type> may be either C<intra> or anything else. If it is not set to
2390 C<intra>, then the search will exclude lost, very overdue, and
2391 withdrawn items.
2392
2393 C<$env> is ignored.
2394
2395 C<&ItemInfo> returns a list of references-to-hash. Each element
2396 contains a number of keys. Most of them are table items from the
2397 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2398 Koha database. Other keys include:
2399
2400 =over 4
2401
2402 =item C<$data-E<gt>{branchname}>
2403
2404 The name (not the code) of the branch to which the book belongs.
2405
2406 =item C<$data-E<gt>{datelastseen}>
2407
2408 This is simply C<items.datelastseen>, except that while the date is
2409 stored in YYYY-MM-DD format in the database, here it is converted to
2410 DD/MM/YYYY format. A NULL date is returned as C<//>.
2411
2412 =item C<$data-E<gt>{datedue}>
2413
2414 =item C<$data-E<gt>{class}>
2415
2416 This is the concatenation of C<biblioitems.classification>, the book's
2417 Dewey code, and C<biblioitems.subclass>.
2418
2419 =item C<$data-E<gt>{ocount}>
2420
2421 I think this is the number of copies of the book available.
2422
2423 =item C<$data-E<gt>{order}>
2424
2425 If this is set, it is set to C<One Order>.
2426
2427 =back
2428
2429 =cut
2430 #'
2431 sub ItemInfo {
2432         my ($env,$biblionumber,$type) = @_;
2433         my $dbh   = C4::Context->dbh;
2434         my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems 
2435                                         left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2436                                         WHERE items.biblionumber = ?
2437                                         AND biblioitems.biblioitemnumber = items.biblioitemnumber
2438                                         AND biblio.biblionumber = items.biblionumber";
2439         $query .= " order by items.dateaccessioned desc";
2440         my $sth=$dbh->prepare($query);
2441         $sth->execute($biblionumber);
2442         my $i=0;
2443         my @results;
2444         while (my $data=$sth->fetchrow_hashref){
2445                 my $datedue = '';
2446                 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2447                 $isth->execute($data->{'itemnumber'});
2448                 if (my $idata=$isth->fetchrow_hashref){
2449                 $data->{borrowernumber} = $idata->{borrowernumber};
2450                 $data->{cardnumber} = $idata->{cardnumber};
2451                 $datedue = format_date($idata->{'date_due'});
2452                 }
2453                 if ($datedue eq ''){
2454                         my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2455                         if ($restype) {
2456                                 $datedue=$restype;
2457                         }
2458                 }
2459                 $isth->finish;
2460         #get branch information.....
2461                 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2462                 $bsth->execute($data->{'holdingbranch'});
2463                 if (my $bdata=$bsth->fetchrow_hashref){
2464                         $data->{'branchname'} = $bdata->{'branchname'};
2465                 }
2466                 my $date=format_date($data->{'datelastseen'});
2467                 $data->{'datelastseen'}=$date;
2468                 $data->{'datedue'}=$datedue;
2469         # get notforloan complete status if applicable
2470                 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2471                 $sthnflstatus->execute;
2472                 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2473                 if ($authorised_valuecode) {
2474                         $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2475                         $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2476                         my ($lib) = $sthnflstatus->fetchrow;
2477                         $data->{notforloan} = $lib;
2478                 }
2479                 $results[$i]=$data;
2480                 $i++;
2481         }
2482         $sth->finish;
2483         return(@results);
2484 }
2485
2486 =head2 bibitems
2487
2488   ($count, @results) = &bibitems($biblionumber);
2489
2490 Given the biblionumber for a book, C<&bibitems> looks up that book's
2491 biblioitems (different publications of the same book, the audio book
2492 and film versions, etc.).
2493
2494 C<$count> is the number of elements in C<@results>.
2495
2496 C<@results> is an array of references-to-hash; the keys are the fields
2497 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2498 addition, C<itemlost> indicates the availability of the item: if it is
2499 "2", then all copies of the item are long overdue; if it is "1", then
2500 all copies are lost; otherwise, there is at least one copy available.
2501
2502 =cut
2503 #'
2504 sub bibitems {
2505     my ($bibnum) = @_;
2506     my $dbh   = C4::Context->dbh;
2507     my $sth   = $dbh->prepare("SELECT biblioitems.*,
2508                         itemtypes.*,
2509                         MIN(items.itemlost)        as itemlost,
2510                         MIN(items.dateaccessioned) as dateaccessioned
2511                           FROM biblioitems, itemtypes, items
2512                          WHERE biblioitems.biblionumber     = ?
2513                            AND biblioitems.itemtype         = itemtypes.itemtype
2514                            AND biblioitems.biblioitemnumber = items.biblioitemnumber
2515                       GROUP BY items.biblioitemnumber");
2516     my $count = 0;
2517     my @results;
2518     $sth->execute($bibnum);
2519     while (my $data = $sth->fetchrow_hashref) {
2520         $results[$count] = $data;
2521         $count++;
2522     } # while
2523     $sth->finish;
2524     return($count, @results);
2525 } # sub bibitems
2526
2527
2528 =head2 bibitemdata
2529
2530   $itemdata = &bibitemdata($biblioitemnumber);
2531
2532 Looks up the biblioitem with the given biblioitemnumber. Returns a
2533 reference-to-hash. The keys are the fields from the C<biblio>,
2534 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2535 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2536
2537 =cut
2538 #'
2539 sub bibitemdata {
2540     my ($bibitem) = @_;
2541     my $dbh   = C4::Context->dbh;
2542     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");
2543     my $data;
2544
2545     $sth->execute($bibitem);
2546
2547     $data = $sth->fetchrow_hashref;
2548
2549     $sth->finish;
2550     return($data);
2551 } # sub bibitemdata
2552
2553
2554 =head2 getbibliofromitemnumber
2555
2556   $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2557
2558 Looks up the item with the given itemnumber.
2559
2560 C<$env> and C<$dbh> are ignored.
2561
2562 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2563 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2564 database.
2565
2566 =cut
2567 #'
2568 sub getbibliofromitemnumber {
2569   my ($env,$dbh,$itemnumber) = @_;
2570   $dbh = C4::Context->dbh;
2571   my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2572     where items.itemnumber = ?
2573     and biblio.biblionumber = items.biblionumber
2574     and biblioitems.biblioitemnumber = items.biblioitemnumber");
2575 #  print $query;
2576   $sth->execute($itemnumber);
2577   my $data=$sth->fetchrow_hashref;
2578   $sth->finish;
2579   return($data);
2580 }
2581
2582 =head2 barcodes
2583
2584   @barcodes = &barcodes($biblioitemnumber);
2585
2586 Given a biblioitemnumber, looks up the corresponding items.
2587
2588 Returns an array of references-to-hash; the keys are C<barcode> and
2589 C<itemlost>.
2590
2591 The returned items include very overdue items, but not lost ones.
2592
2593 =cut
2594 #'
2595 sub barcodes{
2596     #called from request.pl
2597     my ($biblioitemnumber)=@_;
2598     my $dbh = C4::Context->dbh;
2599     my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2600                            WHERE biblioitemnumber = ?
2601                              AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2602     $sth->execute($biblioitemnumber);
2603     my @barcodes;
2604     my $i=0;
2605     while (my $data=$sth->fetchrow_hashref){
2606         $barcodes[$i]=$data;
2607         $i++;
2608     }
2609     $sth->finish;
2610     return(@barcodes);
2611 }
2612
2613
2614 =head2 itemdata
2615
2616   $item = &itemdata($barcode);
2617
2618 Looks up the item with the given barcode, and returns a
2619 reference-to-hash containing information about that item. The keys of
2620 the hash are the fields from the C<items> and C<biblioitems> tables in
2621 the Koha database.
2622
2623 =cut
2624 #'
2625 sub get_item_from_barcode {
2626   my ($barcode)=@_;
2627   my $dbh = C4::Context->dbh;
2628   my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2629   and items.biblioitemnumber=biblioitems.biblioitemnumber");
2630   $sth->execute($barcode);
2631   my $data=$sth->fetchrow_hashref;
2632   $sth->finish;
2633   return($data);
2634 }
2635
2636
2637 =head2 itemissues
2638
2639   @issues = &itemissues($biblioitemnumber, $biblio);
2640
2641 Looks up information about who has borrowed the bookZ<>(s) with the
2642 given biblioitemnumber.
2643
2644 C<$biblio> is ignored.
2645
2646 C<&itemissues> returns an array of references-to-hash. The keys
2647 include the fields from the C<items> table in the Koha database.
2648 Additional keys include:
2649
2650 =over 4
2651
2652 =item C<date_due>
2653
2654 If the item is currently on loan, this gives the due date.
2655
2656 If the item is not on loan, then this is either "Available" or
2657 "Cancelled", if the item has been withdrawn.
2658
2659 =item C<card>
2660
2661 If the item is currently on loan, this gives the card number of the
2662 patron who currently has the item.
2663
2664 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2665
2666 These give the timestamp for the last three times the item was
2667 borrowed.
2668
2669 =item C<card0>, C<card1>, C<card2>
2670
2671 The card number of the last three patrons who borrowed this item.
2672
2673 =item C<borrower0>, C<borrower1>, C<borrower2>
2674
2675 The borrower number of the last three patrons who borrowed this item.
2676
2677 =back
2678
2679 =cut
2680 #'
2681 sub itemissues {
2682     my ($bibitem, $biblio)=@_;
2683     my $dbh   = C4::Context->dbh;
2684     # FIXME - If this function die()s, the script will abort, and the
2685     # user won't get anything; depending on how far the script has
2686     # gotten, the user might get a blank page. It would be much better
2687     # to at least print an error message. The easiest way to do this
2688     # is to set $SIG{__DIE__}.
2689     my $sth   = $dbh->prepare("Select * from items where
2690 items.biblioitemnumber = ?")
2691       || die $dbh->errstr;
2692     my $i     = 0;
2693     my @results;
2694
2695     $sth->execute($bibitem)
2696       || die $sth->errstr;
2697
2698     while (my $data = $sth->fetchrow_hashref) {
2699         # Find out who currently has this item.
2700         # FIXME - Wouldn't it be better to do this as a left join of
2701         # some sort? Currently, this code assumes that if
2702         # fetchrow_hashref() fails, then the book is on the shelf.
2703         # fetchrow_hashref() can fail for any number of reasons (e.g.,
2704         # database server crash), not just because no items match the
2705         # search criteria.
2706         my $sth2   = $dbh->prepare("select * from issues,borrowers
2707 where itemnumber = ?
2708 and returndate is NULL
2709 and issues.borrowernumber = borrowers.borrowernumber");
2710
2711         $sth2->execute($data->{'itemnumber'});
2712         if (my $data2 = $sth2->fetchrow_hashref) {
2713             $data->{'date_due'} = $data2->{'date_due'};
2714             $data->{'card'}     = $data2->{'cardnumber'};
2715             $data->{'borrower'}     = $data2->{'borrowernumber'};
2716         } else {
2717             if ($data->{'wthdrawn'} eq '1') {
2718                 $data->{'date_due'} = 'Cancelled';
2719             } else {
2720                 $data->{'date_due'} = 'Available';
2721             } # else
2722         } # else
2723
2724         $sth2->finish;
2725
2726         # Find the last 3 people who borrowed this item.
2727         $sth2 = $dbh->prepare("select * from issues, borrowers
2728                                                 where itemnumber = ?
2729                                                                         and issues.borrowernumber = borrowers.borrowernumber
2730                                                                         and returndate is not NULL
2731                                                                         order by returndate desc,timestamp desc") || die $dbh->errstr;
2732         $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2733         for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2734             if (my $data2 = $sth2->fetchrow_hashref) {
2735                 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2736                 $data->{"card$i2"}      = $data2->{'cardnumber'};
2737                 $data->{"borrower$i2"}  = $data2->{'borrowernumber'};
2738             } # if
2739         } # for
2740
2741         $sth2->finish;
2742         $results[$i] = $data;
2743         $i++;
2744     }
2745
2746     $sth->finish;
2747     return(@results);
2748 }
2749
2750 =head2 getsubject
2751
2752   ($count, $subjects) = &getsubject($biblionumber);
2753
2754 Looks up the subjects of the book with the given biblionumber. Returns
2755 a two-element list. C<$subjects> is a reference-to-array, where each
2756 element is a subject of the book, and C<$count> is the number of
2757 elements in C<$subjects>.
2758
2759 =cut
2760 #'
2761 sub getsubject {
2762   my ($bibnum)=@_;
2763   my $dbh = C4::Context->dbh;
2764   my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2765   $sth->execute($bibnum);
2766   my @results;
2767   my $i=0;
2768   while (my $data=$sth->fetchrow_hashref){
2769     $results[$i]=$data;
2770     $i++;
2771   }
2772   $sth->finish;
2773   return($i,\@results);
2774 }
2775
2776 =head2 getaddauthor
2777
2778   ($count, $authors) = &getaddauthor($biblionumber);
2779
2780 Looks up the additional authors for the book with the given
2781 biblionumber.
2782
2783 Returns a two-element list. C<$authors> is a reference-to-array, where
2784 each element is an additional author, and C<$count> is the number of
2785 elements in C<$authors>.
2786
2787 =cut
2788 #'
2789 sub getaddauthor {
2790   my ($bibnum)=@_;
2791   my $dbh = C4::Context->dbh;
2792   my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2793   $sth->execute($bibnum);
2794   my @results;
2795   my $i=0;
2796   while (my $data=$sth->fetchrow_hashref){
2797     $results[$i]=$data;
2798     $i++;
2799   }
2800   $sth->finish;
2801   return($i,\@results);
2802 }
2803
2804
2805 =head2 getsubtitle
2806
2807   ($count, $subtitles) = &getsubtitle($biblionumber);
2808
2809 Looks up the subtitles for the book with the given biblionumber.
2810
2811 Returns a two-element list. C<$subtitles> is a reference-to-array,
2812 where each element is a subtitle, and C<$count> is the number of
2813 elements in C<$subtitles>.
2814
2815 =cut
2816 #'
2817 sub getsubtitle {
2818   my ($bibnum)=@_;
2819   my $dbh = C4::Context->dbh;
2820   my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2821   $sth->execute($bibnum);
2822   my @results;
2823   my $i=0;
2824   while (my $data=$sth->fetchrow_hashref){
2825     $results[$i]=$data;
2826     $i++;
2827   }
2828   $sth->finish;
2829   return($i,\@results);
2830 }
2831
2832
2833 =head2 getwebsites
2834
2835   ($count, @websites) = &getwebsites($biblionumber);
2836
2837 Looks up the web sites pertaining to the book with the given
2838 biblionumber.
2839
2840 C<$count> is the number of elements in C<@websites>.
2841
2842 C<@websites> is an array of references-to-hash; the keys are the
2843 fields from the C<websites> table in the Koha database.
2844
2845 =cut
2846 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2847 #(with add / modify / delete subs)
2848
2849 sub getwebsites {
2850     my ($biblionumber) = @_;
2851     my $dbh   = C4::Context->dbh;
2852     my $sth   = $dbh->prepare("Select * from websites where biblionumber = ?");
2853     my $count = 0;
2854     my @results;
2855
2856     $sth->execute($biblionumber);
2857     while (my $data = $sth->fetchrow_hashref) {
2858         # FIXME - The URL scheme shouldn't be stripped off, at least
2859         # not here, since it's part of the URL, and will be useful in
2860         # constructing a link to the site. If you don't want the user
2861         # to see the "http://" part, strip that off when building the
2862         # HTML code.
2863         $data->{'url'} =~ s/^http:\/\///;       # FIXME - Leaning toothpick
2864                                                 # syndrome
2865         $results[$count] = $data;
2866         $count++;
2867     } # while
2868
2869     $sth->finish;
2870     return($count, @results);
2871 } # sub getwebsites
2872
2873 =head2 getwebbiblioitems
2874
2875   ($count, @results) = &getwebbiblioitems($biblionumber);
2876
2877 Given a book's biblionumber, looks up the web versions of the book
2878 (biblioitems with itemtype C<WEB>).
2879
2880 C<$count> is the number of items in C<@results>. C<@results> is an
2881 array of references-to-hash; the keys are the items from the
2882 C<biblioitems> table of the Koha database.
2883
2884 =cut
2885 #'
2886 sub getwebbiblioitems {
2887     my ($biblionumber) = @_;
2888     my $dbh   = C4::Context->dbh;
2889     my $sth   = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2890 and itemtype = 'WEB'");
2891     my $count = 0;
2892     my @results;
2893
2894     $sth->execute($biblionumber);
2895     while (my $data = $sth->fetchrow_hashref) {
2896         $data->{'url'} =~ s/^http:\/\///;
2897         $results[$count] = $data;
2898         $count++;
2899     } # while
2900
2901     $sth->finish;
2902     return($count, @results);
2903 } # sub getwebbiblioitems
2904
2905 sub nsb_clean {
2906     my $NSB = '\x88';    # NSB : begin Non Sorting Block
2907     my $NSE = '\x89';    # NSE : Non Sorting Block end
2908                          # handles non sorting blocks
2909     my ($string) = @_;
2910     $_ = $string;
2911     s/$NSB/(/gm;
2912     s/[ ]{0,1}$NSE/) /gm;
2913     $string = $_;
2914     return ($string);
2915 }
2916
2917 sub FindDuplicate {
2918         my ($record)=@_;
2919         my $dbh = C4::Context->dbh;
2920         my $result = MARCmarc2koha($dbh,$record,'');
2921         my $sth;
2922         my ($biblionumber,$bibid,$title);
2923         # search duplicate on ISBN, easy and fast...
2924         if ($result->{isbn}) {
2925                 $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=?");
2926                 $sth->execute($result->{'isbn'});
2927                 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2928                 return $biblionumber,$bibid,$title if ($biblionumber);
2929         }
2930         # a more complex search : build a request for SearchMarc::catalogsearch()
2931         my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2932         # search on biblio.title
2933         my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2934         if ($record->field($tag)) {
2935                 if ($record->field($tag)->subfields($subfield)) {
2936                         push @tags, "'".$tag.$subfield."'";
2937                         push @and_or, "and";
2938                         push @excluding, "";
2939                         push @operator, "contains";
2940                         push @value, $record->field($tag)->subfield($subfield);
2941 #                       warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2942                 }
2943         }
2944         # ... and on biblio.author
2945         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2946         if ($record->field($tag)) {
2947                 if ($record->field($tag)->subfields($subfield)) {
2948                         push @tags, "'".$tag.$subfield."'";
2949                         push @and_or, "and";
2950                         push @excluding, "";
2951                         push @operator, "contains";
2952                         push @value, $record->field($tag)->subfield($subfield);
2953 #                       warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2954                 }
2955         }
2956         # ... and on publicationyear.
2957         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2958         if ($record->field($tag)) {
2959                 if ($record->field($tag)->subfields($subfield)) {
2960                         push @tags, "'".$tag.$subfield."'";
2961                         push @and_or, "and";
2962                         push @excluding, "";
2963                         push @operator, "=";
2964                         push @value, $record->field($tag)->subfield($subfield);
2965 #                       warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2966                 }
2967         }
2968         # ... and on size.
2969         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2970         if ($record->field($tag)) {
2971                 if ($record->field($tag)->subfields($subfield)) {
2972                         push @tags, "'".$tag.$subfield."'";
2973                         push @and_or, "and";
2974                         push @excluding, "";
2975                         push @operator, "=";
2976                         push @value, $record->field($tag)->subfield($subfield);
2977 #                       warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2978                 }
2979         }
2980         # ... and on publisher.
2981         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2982         if ($record->field($tag)) {
2983                 if ($record->field($tag)->subfields($subfield)) {
2984                         push @tags, "'".$tag.$subfield."'";
2985                         push @and_or, "and";
2986                         push @excluding, "";
2987                         push @operator, "=";
2988                         push @value, $record->field($tag)->subfield($subfield);
2989 #                       warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2990                 }
2991         }
2992         # ... and on volume.
2993         ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2994         if ($record->field($tag)) {
2995                 if ($record->field($tag)->subfields($subfield)) {
2996                         push @tags, "'".$tag.$subfield."'";
2997                         push @and_or, "and";
2998                         push @excluding, "";
2999                         push @operator, "=";
3000                         push @value, $record->field($tag)->subfield($subfield);
3001 #                       warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
3002                 }
3003         }
3004
3005         my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
3006         # there is at least 1 result => return the 1st one
3007         if ($nbresult) {
3008 #               warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
3009                 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
3010         }
3011         # no result, returns nothing
3012         return;
3013 }
3014
3015 sub DisplayISBN {
3016         my ($isbn)=@_;
3017         my $seg1;
3018         if(substr($isbn, 0, 1) <=7) {
3019                 $seg1 = substr($isbn, 0, 1);
3020         } elsif(substr($isbn, 0, 2) <= 94) {
3021                 $seg1 = substr($isbn, 0, 2);
3022         } elsif(substr($isbn, 0, 3) <= 995) {
3023                 $seg1 = substr($isbn, 0, 3);
3024         } elsif(substr($isbn, 0, 4) <= 9989) {
3025                 $seg1 = substr($isbn, 0, 4);
3026         } else {
3027                 $seg1 = substr($isbn, 0, 5);
3028         }
3029         my $x = substr($isbn, length($seg1));
3030         my $seg2;
3031         if(substr($x, 0, 2) <= 19) {
3032 #               if(sTmp2 < 10) sTmp2 = "0" sTmp2;
3033                 $seg2 = substr($x, 0, 2);
3034         } elsif(substr($x, 0, 3) <= 699) {
3035                 $seg2 = substr($x, 0, 3);
3036         } elsif(substr($x, 0, 4) <= 8399) {
3037                 $seg2 = substr($x, 0, 4);
3038         } elsif(substr($x, 0, 5) <= 89999) {
3039                 $seg2 = substr($x, 0, 5);
3040         } elsif(substr($x, 0, 6) <= 9499999) {
3041                 $seg2 = substr($x, 0, 6);
3042         } else {
3043                 $seg2 = substr($x, 0, 7);
3044         }
3045         my $seg3=substr($x,length($seg2));
3046         $seg3=substr($seg3,0,length($seg3)-1) ;
3047         my $seg4 = substr($x, -1, 1);
3048         return "$seg1-$seg2-$seg3-$seg4";
3049 }
3050
3051
3052 END { }    # module clean-up code here (global destructor)
3053
3054 =back
3055
3056 =head1 AUTHOR
3057
3058 Koha Developement team <info@koha.org>
3059
3060 Paul POULAIN paul.poulain@free.fr
3061
3062 =cut
3063
3064 # $Id$
3065 # $Log$
3066 # Revision 1.169  2006/04/10 20:39:49  tgarip1957
3067 # 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
3068 #
3069 # Revision 1.168  2006/04/03 04:00:02  rangi
3070 # Modify item now works
3071 #
3072 # BUT only if there is only one item, if there is more than one item, it gets messed up.
3073 # They get combined into the form, ill work on this next
3074 #
3075 # Revision 1.167  2006/04/03 02:12:49  kados
3076 # some modifs to improve plugin support
3077 #
3078 # Revision 1.166  2006/04/01 22:10:50  rangi
3079 # Fixing the problem that all items were getting biblioitem=1 set
3080 #
3081 # Revision 1.165  2006/04/01 21:22:05  rangi
3082 # Adding a little fake subroutine that a few scripts in the opac depend on, can be removed once the opac scripts are rewritten
3083 #
3084 # Revision 1.164  2006/03/29 01:56:25  rangi
3085 # Delete isnt working using the extended services method
3086 #
3087 # Revision 1.163  2006/03/28 23:05:08  rangi
3088 # Delete working now
3089 #
3090 # Revision 1.162  2006/03/13 23:12:44  rangi
3091 # Adding commits, so that changes stick
3092 #
3093 # Revision 1.161  2006/03/10 02:40:38  kados
3094 # syncing MARChtml2xml wtih rel_2_2, removing unused MARChtml2marc
3095 #
3096 # Revision 1.160  2006/03/07 22:00:18  kados
3097 # adding support for 'delete' function
3098 #
3099 # Revision 1.159  2006/03/07 21:54:47  rangi
3100 # Starting work on deletes
3101 #
3102 # Revision 1.158  2006/03/06 02:45:41  kados
3103 # Adding fixes to MARC editor to HEAD
3104 #
3105 # Revision 1.157  2006/03/01 03:07:54  kados
3106 # rollback ... by accident I committed a rel_2_2 Biblio.pm
3107 #
3108 # Revision 1.155  2006/02/27 01:08:31  kados
3109 # Removing 'our Zconn' from top...
3110 #
3111 # Revision 1.154  2006/02/26 00:08:20  kados
3112 # moving all $Zconn s to z3950_extended_services (currently, nothing
3113 # works).
3114 #
3115 # Revision 1.153  2006/02/25 22:39:10  kados
3116 # Another purely documentation commit. Just changing formatting to ease
3117 # readability.
3118 #
3119 # Revision 1.152  2006/02/25 21:17:20  kados
3120 # Purely documentation change: converted all =head2 entries to use function
3121 # name as title rather than usage as title
3122 #
3123 # Revision 1.151  2006/02/25 21:02:20  kados
3124 #
3125 # Further cleanup, convering new routines to 4-chars
3126 #
3127 # Revision 1.150  2006/02/25 20:49:15  kados
3128 # Better documentation, added warning if serviceType is 'drop' since it's
3129 # not supported in Zebra.
3130 #
3131 # Revision 1.149  2006/02/25 20:30:32  kados
3132 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
3133 # longer necessary. If we need to convert from MARC-8 for display, we should:
3134 #
3135 # 1. use utf-8
3136 # 2. do it with MARC::Charset
3137 #
3138 # If you still need it, let me know and I'll put it back in.
3139 #
3140 # Revision 1.148  2006/02/25 19:23:01  kados
3141 # cleaning up POD docs, deleting zebra_create as it's no longer used (
3142 # replaced by z3950_extended_services).
3143 #
3144 # Revision 1.147  2006/02/25 19:09:59  kados
3145 # readding some lost subs
3146 #
3147 # Revision 1.145  2006/02/22 01:02:39  kados
3148 # Replacing all calls to zebra_update with calls to
3149 # z3950_extended_services. More work coming, but it's
3150 # working now.
3151 #
3152 # Revision 1.144  2006/02/20 14:22:38  kados
3153 # typo
3154 #
3155 # Revision 1.143  2006/02/20 13:26:11  kados
3156 # A new subroutine to handle Z39.50 extended services. You pass it a
3157 # connection object, service type, service options, and a record, and
3158 # it performs the service and handles any exception found.
3159 #
3160 # Revision 1.142  2006/02/16 20:49:56  kados
3161 # destroy a connection after we're done -- we really should just have one
3162 # connection object and not destroy it until the whole transaction is
3163 # finished -- but this will do for now
3164 #
3165 # Revision 1.141  2006/02/16 19:47:22  rangi
3166 # Trying to error trap a little more.
3167 #
3168 # Revision 1.140  2006/02/14 21:36:03  kados
3169 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3170 # also adding diagnostic error if not able to connect to Zebra
3171 #
3172 # Revision 1.139  2006/02/14 19:53:25  rangi
3173 # Just a little missing my
3174 #
3175 # Seems to be working great Paul, and I like what you did with zebradb
3176 #
3177 # Revision 1.138  2006/02/14 11:25:22  tipaul
3178 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3179 #
3180 # Revision 1.137  2006/02/13 16:34:26  tipaul
3181 # fixing some warnings (perl -w should be quiet)
3182 #
3183 # Revision 1.136  2006/01/10 17:01:29  tipaul
3184 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3185 #
3186 # Revision 1.135  2006/01/06 16:39:37  tipaul
3187 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3188 # Seems not to break too many things, but i'm probably wrong here.
3189 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3190 #
3191 # - removing useless directories (koha-html and koha-plucene)
3192 #
3193 # Revision 1.134  2006/01/04 15:54:55  tipaul
3194 # utf8 is a : go for beta test in HEAD.
3195 # some explanations :
3196 # - 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.
3197 # - *-top.inc will show the pages in utf8
3198 # - 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.
3199 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3200 #
3201 # Revision 1.133  2005/12/12 14:25:51  thd
3202 #
3203 #
3204 # Reverse array filled with elements from repeated subfields
3205 # to avoid last to first concatenation of elements in Koha DB.-
3206 #
3207 # Revision 1.132  2005-10-26 09:12:33  tipaul
3208 # big commit, still breaking things...
3209 #
3210 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3211 # * code cleaning (cleaning warnings from perl -w) continued
3212 #
3213 # Revision 1.131  2005/09/22 10:01:45  tipaul
3214 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3215 #
3216 # Revision 1.130  2005/09/02 14:34:14  tipaul
3217 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3218 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3219 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3220 #
3221 # Revision 1.129  2005/08/12 13:50:31  tipaul
3222 # removing useless sub declarations
3223 #
3224 # Revision 1.128  2005/08/11 16:12:47  tipaul
3225 # Playing with the zebra...
3226 #
3227 # * go to koha cvs home directory
3228 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3229 # * put your zebra.cfg files here & create your database.
3230 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3231 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3232 #
3233 # NOTE :
3234 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3235 # * deletion still not work
3236 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3237 # in zebra.cfg :
3238 # recordId: (bib1,Local-number)
3239 # storeKeys:1
3240 #
3241 # in .abs file :
3242 # elm 090            Local-number            -
3243 # elm 090/?          Local-number            -
3244 # elm 090/?/9        Local-number            !:w
3245 #
3246 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3247 #
3248 # Revision 1.127  2005/08/11 14:37:32  tipaul
3249 # * POD documenting
3250 # * removing useless subs
3251 # * removing some subs that are also elsewhere
3252 # * 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)
3253 #
3254 # Revision 1.126  2005/08/11 09:13:28  tipaul
3255 # just removing useless subs (a lot !!!) for code cleaning
3256 #
3257 # Revision 1.125  2005/08/11 09:00:07  tipaul
3258 # Ok guys, this time, it seems that item add and modif begin working as expected...
3259 # Still a lot of bugs to fix, of course
3260 #
3261 # Revision 1.124  2005/08/10 10:21:15  tipaul
3262 # continuing the road to zebra :
3263 # - the biblio add begins to work.
3264 # - the biblio modif begins to work.
3265 #
3266 # (still without doing anything on zebra)
3267 # (no new change in updatedatabase)
3268 #
3269 # Revision 1.123  2005/08/09 14:10:28  tipaul
3270 # 1st commit to go to zebra.
3271 # don't update your cvs if you want to have a working head...
3272 #
3273 # this commit contains :
3274 # * 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...
3275 # * 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.
3276 # * other files : get rid of bibid and use biblionumber instead.
3277 #
3278 # What is broken :
3279 # * does not do anything on zebra yet.
3280 # * if you rename marc_subfield_table, you can't search anymore.
3281 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3282 # * 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 ;-) )
3283 #
3284 # 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
3285 # 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.
3286
3287 # tipaul cutted previous commit notes