3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
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
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.
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
26 use MARC::File::USMARC;
30 use vars qw($VERSION @ISA @EXPORT);
32 # set the version for version checking
33 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
34 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
39 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
40 # as the old-style API and the NEW one are the only public functions.
43 &newbiblio &newbiblioitem
44 &newsubject &newsubtitle &newitems
46 &modbiblio &checkitems &modbibitem
47 &modsubtitle &modsubject &modaddauthor &moditem
49 &delitem &deletebiblioitem &delbiblio
51 &getbiblio &bibdata &bibitems &bibitemdata
52 &barcodes &ItemInfo &itemdata &itemissues &itemcount
53 &getsubject &getaddauthor &getsubtitle
54 &getwebbiblioitems &getwebsites
55 &getbiblioitembybiblionumber
56 &getbiblioitem &getitemsbybiblioitem
58 &MARCfind_marc_from_kohafield
59 &MARCfind_frameworkcode
60 &find_biblioitemnumber
63 &NEWnewbiblio &NEWnewitem
64 &NEWmodbiblio &NEWmoditem
65 &NEWdelbiblio &NEWdelitem
66 &NEWmodbiblioframework
68 &MARCkoha2marcBiblio &MARCmarc2koha
69 &MARCkoha2marcItem &MARChtml2marc
70 &MARCgetbiblio &MARCgetitem
76 &z3950_extended_services
80 MARCfind_MARCbibid_from_oldbiblionumber
85 C4::Biblio - acquisition, catalog management functions
89 ( lot of changes for Koha 3.0)
91 Koha 1.2 and previous version used a specific API to manage biblios. This API uses old-DB style parameters.
92 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, bibliosubject and bibliosubtitle where applicable)
94 In Koha 2.0, we introduced a MARC-DB.
96 In Koha 3.0 we removed this MARC-DB for search as we wanted to use Zebra as search system.
98 So in Koha 3.0, saving a record means :
99 - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items informations.
100 - storing the "decoded information" in biblio/biblioitems/items as previously.
101 - using zebra to manage search & indexing on the MARC datas.
103 In Koha, there is a systempreference saying "MARC=ON" or "MARC=OFF"
105 * MARC=ON : when MARC=ON, koha uses a MARC::Record object (in sub parameters). Saving informations in the DB means :
106 - transform the MARC record into a hash
107 - add the raw marc record into the hash
108 - store them & update zebra
110 * MARC=OFF : when MARC=OFF, koha uses a hash object (in sub parameters). Saving informations in the DB means :
111 - transform the hash into a MARC record
112 - add the raw marc record into the hash
113 - store them and update zebra
116 That's why we need 3 types of subs :
120 all I<subs beginning by REAL> does effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in zebra. REAL subs should be only for internal use (called by NEW or "something else" subs
122 =head2 NEWxxx related subs
126 all I<subs beginning by NEW> use MARC::Record as parameters. it's the API that MUST be used in MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
128 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. they sometimes requires another parameter.
132 =head2 something_elsexxx related subs
136 all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and calls REAL subs.
138 all subs requires/use $dbh as 1st parameter and a hash as 2nd parameter.
147 my ($biblionumber,$record) = @_;
148 # create the iso2709 file for zebra
149 # my $cgidir = C4::Context->intranetdir ."/cgi-bin";
150 # unless (opendir(DIR, "$cgidir")) {
151 # $cgidir = C4::Context->intranetdir."/";
154 # my $filename = $cgidir."/zebra/biblios/BIBLIO".$biblionumber."iso2709";
155 # open F,"> $filename";
156 # print F $record->as_usmarc();
158 # my $res = system("cd $cgidir/zebra;/usr/local/bin/zebraidx update biblios");
162 warn "zebra_create : $biblionumber =".$record->as_formatted;
164 $xmlrecord=$record->as_xml();
167 warn "ERROR badly formatted marc record";
168 warn "Skipping record";
172 $Zconn = new ZOOM::Connection(C4::Context->config("zebradb"));
175 warn "Error ", $@->code(), ": ", $@->message(), "\n";
176 die "Fatal error, cant connect to z3950 server";
179 $Zconn->option(cqlfile => C4::Context->config("intranetdir")."/zebra/pqf.properties");
180 my $Zpackage = $Zconn->package();
181 $Zpackage->option(action => "specialUpdate");
182 $Zpackage->option(record => $xmlrecord);
183 $Zpackage->send("update");
190 z3950_extended_services can handle any interaction with Zebra's extended serices package.
192 $Zconn contains the server connection object (which is set before calling this s
195 $service type is one of:
196 itemorder,create,drop,commit,update,xmlupdate
198 $service_options is a hash of key/value pairs. For instance,
199 if service_type is 'update', $service_options should contain:
201 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
202 (recordidOpaque => Opaque Record ID (user supplied)
206 recordidNumber => Record ID number (system number))
207 record => the record itself
211 syntax => the record syntax (transfer syntax)
212 databaseName = Database from connection object
215 sub z3950_extended_services {
216 my ($Zconn,$serviceType,$serviceOptions,$record) = @_;
218 # create a new package object
219 my $Zpackage = $Zconn->package();
222 $Zpackage->option(action => $serviceOptions->{'action'});
224 if ($serviceOptions->{'databaseName'}) {
225 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
227 if ($serviceOptions->{'recordIdNumber'}) {
228 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
230 if ($serviceOptions->{'recordIdOpaque'}) {
231 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
234 # this is an ILL request (Zebra doesn't support it)
235 if ($serviceType eq 'itemorder') {
236 $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
237 $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
238 $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
239 $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
243 my $xmlrecord = marc2xml($record);
244 $Zpackage->option(record => $xmlrecord);
245 if ($serviceOptions->{'syntax'}) {
246 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
250 # send the request, handle any exception encountered
251 eval { $Zpackage->send($serviceType) };
252 if ($@ && $@->isa("ZOOM::Exception")) {
253 print "Oops! ", $@->message(), "\n";
256 # free up package resources
257 $Zpackage->destroy();
264 $xmlrecord=$record->as_xml();
267 warn "ERROR badly formatted marc record";
268 warn "Skipping record";
272 sub set_service_options {
275 if ($option eq 'update') {
276 $serviceOptions->{ 'action' } = 'specialUpdate';
277 $serviceOptions->{ 'syntax' } = 'xml'; #zebra doesn't support others
279 if ($option eq 'commit') {
283 return $serviceOptions;
287 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
291 2nd param is 1 for liblibrarian and 0 for libopac
292 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
294 returns a hash with all values for all fields and subfields for a given MARC framework :
295 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
297 ->{mandatory} = $mandatory;
298 ->{repeatable} = $repeatable;
299 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
301 ->{mandatory} = $mandatory;
302 ->{repeatable} = $repeatable;
303 ->{authorised_value} = $authorised_value;
304 ->{authtypecode} = $authtypecode;
305 ->{value_builder} = $value_builder;
306 ->{kohafield} = $kohafield;
307 ->{seealso} = $seealso;
308 ->{hidden} = $hidden;
317 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
318 $frameworkcode = "" unless $frameworkcode;
319 $forlibrarian = 1 unless $forlibrarian;
321 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
323 # check that framework exists
326 "select count(*) from marc_tag_structure where frameworkcode=?");
327 $sth->execute($frameworkcode);
328 my ($total) = $sth->fetchrow;
329 $frameworkcode = "" unless ( $total > 0 );
332 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
334 $sth->execute($frameworkcode);
335 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
337 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
338 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
339 $res->{$tag}->{tab} = ""; # XXX
340 $res->{$tag}->{mandatory} = $mandatory;
341 $res->{$tag}->{repeatable} = $repeatable;
346 "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"
348 $sth->execute($frameworkcode);
351 my $authorised_value;
361 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
362 $mandatory, $repeatable, $authorised_value, $authtypecode,
363 $value_builder, $kohafield, $seealso, $hidden,
368 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
369 $res->{$tag}->{$subfield}->{tab} = $tab;
370 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
371 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
372 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
373 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
374 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
375 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
376 $res->{$tag}->{$subfield}->{seealso} = $seealso;
377 $res->{$tag}->{$subfield}->{hidden} = $hidden;
378 $res->{$tag}->{$subfield}->{isurl} = $isurl;
379 $res->{$tag}->{$subfield}->{link} = $link;
384 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
388 finds MARC tag and subfield for a given kohafield
389 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
395 sub MARCfind_marc_from_kohafield {
396 my ( $dbh, $kohafield,$frameworkcode ) = @_;
397 return 0, 0 unless $kohafield;
398 $frameworkcode='' unless $frameworkcode;
399 my $relations = C4::Context->marcfromkohafield;
400 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
403 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
407 Returns a MARC::Record for the biblio $biblionumber.
413 # Returns MARC::Record of the biblio passed in parameter.
414 my ( $dbh, $biblionumber ) = @_;
415 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
416 $sth->execute($biblionumber);
417 my ($marc) = $sth->fetchrow;
418 my $record = MARC::Record::new_from_usmarc($marc);
422 =head2 $XML = &XMLgetbiblio($dbh,$biblionumber);
426 Returns a raw XML for the biblio $biblionumber.
432 # Returns MARC::Record of the biblio passed in parameter.
433 my ( $dbh, $biblionumber ) = @_;
434 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
435 $sth->execute($biblionumber);
436 my ($XML,$marc) = $sth->fetchrow;
437 # my $record =MARC::Record::new_from_usmarc($marc);
438 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
442 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
446 Returns a MARC::Record with all items of biblio # $biblionumber
454 my ( $dbh, $biblionumber, $itemnumber ) = @_;
455 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
456 # get the complete MARC record
457 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
458 $sth->execute($biblionumber);
459 my ($rawmarc) = $sth->fetchrow;
460 my $record = MARC::File::USMARC::decode($rawmarc);
461 # now, find the relevant itemnumber
462 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
463 # prepare the new item record
464 my $itemrecord = MARC::Record->new();
465 # parse all fields fields from the complete record
466 foreach ($record->field($itemnumberfield)) {
467 # when the item field is found, save it
468 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
469 $itemrecord->append_fields($_);
476 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
480 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
481 This sub is useless when MARC=OFF
486 sub find_biblioitemnumber {
487 my ( $dbh, $biblionumber ) = @_;
488 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
489 $sth->execute($biblionumber);
490 my ($biblioitemnumber) = $sth->fetchrow;
491 return $biblioitemnumber;
494 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
498 returns the framework of a given biblio
504 sub MARCfind_frameworkcode {
505 my ( $dbh, $biblionumber ) = @_;
506 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
507 $sth->execute($biblionumber);
508 my ($frameworkcode) = $sth->fetchrow;
509 return $frameworkcode;
512 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
516 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
517 all entries of the hash are transformed into their matching MARC field/subfield.
523 sub MARCkoha2marcBiblio {
525 # this function builds partial MARC::Record from the old koha-DB fields
526 my ( $dbh, $bibliohash ) = @_;
527 # we don't have biblio entries in the hash, so we add them first
528 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
529 $sth->execute($bibliohash->{biblionumber});
530 my $biblio = $sth->fetchrow_hashref;
531 foreach (keys %$biblio) {
532 $bibliohash->{$_}=$biblio->{$_};
534 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
535 my $record = MARC::Record->new();
536 foreach ( keys %$bibliohash ) {
537 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
538 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
541 # other fields => additional authors, subjects, subtitles
542 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
543 $sth2->execute($bibliohash->{biblionumber});
544 while ( my $row = $sth2->fetchrow_hashref ) {
545 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
547 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
548 $sth2->execute($bibliohash->{biblionumber});
549 while ( my $row = $sth2->fetchrow_hashref ) {
550 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
552 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
553 $sth2->execute($bibliohash->{biblionumber});
554 while ( my $row = $sth2->fetchrow_hashref ) {
555 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
561 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
563 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
564 all entries of the hash are transformed into their matching MARC field/subfield.
572 sub MARCkoha2marcItem {
574 # this function builds partial MARC::Record from the old koha-DB fields
575 my ( $dbh, $item ) = @_;
577 # my $dbh=&C4Connect;
578 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
579 my $record = MARC::Record->new();
581 foreach( keys %$item ) {
583 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
590 =head2 MARCkoha2marcOnefield
594 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
600 sub MARCkoha2marcOnefield {
601 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
604 $sth->execute($frameworkcode,$kohafieldname);
605 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
606 if ( $record->field($tagfield) ) {
607 my $tag = $record->field($tagfield);
609 $tag->add_subfields( $tagsubfield, $value );
610 $record->delete_field($tag);
611 $record->add_fields($tag);
615 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
621 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
625 transforms the parameters (coming from HTML form) into a MARC::Record
626 parameters with r are references to arrays.
628 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
635 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
637 my $record = MARC::Record->new();
638 # my %subfieldlist=();
639 my $prevvalue; # if tag <10
640 my $field; # if tag >=10
641 for (my $i=0; $i< @$rtags; $i++) {
642 next unless @$rvalues[$i];
643 # rebuild MARC::Record
644 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
645 if (@$rtags[$i] ne $prevtag) {
648 if ($prevtag ne '000') {
649 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
651 $record->leader($prevvalue);
656 $record->add_fields($field);
659 $indicators{@$rtags[$i]}.=' ';
660 if (@$rtags[$i] <10) {
661 $prevvalue= @$rvalues[$i];
665 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
666 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
668 $prevtag = @$rtags[$i];
670 if (@$rtags[$i] <10) {
671 $prevvalue=@$rvalues[$i];
673 if (length(@$rvalues[$i])>0) {
674 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
675 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
678 $prevtag= @$rtags[$i];
681 # the last has not been included inside the loop... do it now !
682 $record->add_fields($field) if $field;
683 # warn "HTML2MARC=".$record->as_formatted;
688 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
692 builds a hash with old-db datas from a MARC::Record
699 my ($dbh,$record,$frameworkcode) = @_;
700 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
702 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
705 while (($field)=$sth2->fetchrow) {
706 # warn "biblio.".$field;
707 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
709 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
711 while (($field)=$sth2->fetchrow) {
712 if ($field eq 'notes') { $field = 'bnotes'; }
713 # warn "biblioitems".$field;
714 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
716 $sth2=$dbh->prepare("SHOW COLUMNS from items");
718 while (($field)=$sth2->fetchrow) {
719 # warn "items".$field;
720 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
722 # additional authors : specific
723 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
724 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
725 # modify copyrightdate to keep only the 1st year found
726 my $temp = $result->{'copyrightdate'};
728 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
730 $result->{'copyrightdate'} = $1;
731 } else { # if no cYYYY, get the 1st date.
732 $temp =~ m/(\d\d\d\d)/;
733 $result->{'copyrightdate'} = $1;
736 # modify publicationyear to keep only the 1st year found
737 $temp = $result->{'publicationyear'};
738 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
740 $result->{'publicationyear'} = $1;
741 } else { # if no cYYYY, get the 1st date.
742 $temp =~ m/(\d\d\d\d)/;
743 $result->{'publicationyear'} = $1;
748 sub MARCmarc2kohaOneField {
750 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
751 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
752 # warn "kohatable / $kohafield / $result / ";
756 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
757 foreach my $field ( $record->field($tagfield) ) {
758 if ($field->tag()<10) {
759 if ($result->{$kohafield}) {
760 # Reverse array filled with elements from repeated subfields
761 # from first to last to avoid last to first concatenation of
762 # elements in Koha DB. -- thd.
763 $result->{$kohafield} .= " | ".reverse($field->data());
765 $result->{$kohafield} = $field->data();
768 if ( $field->subfields ) {
769 my @subfields = $field->subfields();
770 foreach my $subfieldcount ( 0 .. $#subfields ) {
771 if ($subfields[$subfieldcount][0] eq $subfield) {
772 if ( $result->{$kohafield} ) {
773 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
776 $result->{$kohafield} = $subfields[$subfieldcount][1];
783 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
787 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
791 creates a biblio from a MARC::Record.
798 my ( $dbh,$Zconn,$record,$frameworkcode ) = @_;
800 my $biblioitemnumber;
801 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
802 $olddata->{frameworkcode} = $frameworkcode;
803 $biblionumber = REALnewbiblio( $dbh, $olddata );
804 $olddata->{biblionumber} = $biblionumber;
805 # add biblionumber into the MARC record (it's the ID for zebra)
806 my ( $tagfield, $tagsubfield ) =
807 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
811 $newfield = MARC::Field->new(
812 $tagfield, $biblionumber,
815 $newfield = MARC::Field->new(
816 $tagfield, '', '', "$tagsubfield" => $biblionumber,
819 # drop old field (just in case it already exist and create new one...
820 my $old_field = $record->field($tagfield);
821 $record->delete_field($old_field);
822 $record->add_fields($newfield);
824 #create the marc entry, that stores the rax marc record in Koha 3.0
825 $olddata->{marc} = $record->as_usmarc();
826 $olddata->{marcxml} = $record->as_xml();
827 # and create biblioitem, that's all folks !
828 $biblioitemnumber = REALnewbiblioitem( $dbh, $Zconn, $olddata );
830 # search subtiles, addiauthors and subjects
831 ( $tagfield, $tagsubfield ) =
832 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
833 my @addiauthfields = $record->field($tagfield);
834 foreach my $addiauthfield (@addiauthfields) {
835 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
836 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
837 REALmodaddauthor( $dbh, $biblionumber,
838 $addiauthsubfields[$subfieldcount] );
841 ( $tagfield, $tagsubfield ) =
842 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
843 my @subtitlefields = $record->field($tagfield);
844 foreach my $subtitlefield (@subtitlefields) {
845 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
846 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
847 REALnewsubtitle( $dbh, $biblionumber,
848 $subtitlesubfields[$subfieldcount] );
851 ( $tagfield, $tagsubfield ) =
852 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
853 my @subj = $record->field($tagfield);
855 foreach my $subject (@subj) {
856 my @subjsubfield = $subject->subfield($tagsubfield);
857 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
858 push @subjects, $subjsubfield[$subfieldcount];
861 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
862 return ( $biblionumber, $biblioitemnumber );
865 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
869 modify the framework of a biblio
875 sub NEWmodbiblioframework {
876 my ($dbh,$biblionumber,$frameworkcode) =@_;
877 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
878 $sth->execute($frameworkcode,$biblionumber);
882 =head2 NEWmodbiblio($dbh,$Zconn,$MARCrecord,$biblionumber,$frameworkcode);
886 modify a biblio (MARC=ON)
893 my ($dbh,$Zconn,$record,$biblionumber,$frameworkcode) =@_;
894 $frameworkcode="" unless $frameworkcode;
895 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
896 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
898 $oldbiblio->{frameworkcode} = $frameworkcode;
899 #create the marc entry, that stores the rax marc record in Koha 3.0
900 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
901 $oldbiblio->{marc} = $record->as_usmarc();
902 $oldbiblio->{marcxml} = $record->as_xml();
903 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
904 REALmodbiblio($dbh,$oldbiblio);
905 REALmodbiblioitem($dbh,$Zconn,$oldbiblio);
906 # now, modify addi authors, subject, addititles.
907 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
908 my @addiauthfields = $record->field($tagfield);
909 foreach my $addiauthfield (@addiauthfields) {
910 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
911 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
912 foreach my $subfieldcount (0..$#addiauthsubfields) {
913 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
916 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
917 my @subtitlefields = $record->field($tagfield);
918 foreach my $subtitlefield (@subtitlefields) {
919 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
920 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
922 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
923 foreach my $subfieldcount (0..$#subtitlesubfields) {
924 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
925 REALnewsubtitle($dbh,$biblionumber,$subtit);
929 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
930 my @subj = $record->field($tagfield);
932 foreach my $subject (@subj) {
933 my @subjsubfield = $subject->subfield($tagsubfield);
934 foreach my $subfieldcount (0..$#subjsubfield) {
935 push @subjects,$subjsubfield[$subfieldcount];
938 REALmodsubject($dbh,$biblionumber,1,@subjects);
942 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
953 my ( $dbh, $bibid ) = @_;
954 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
955 &REALdelbiblio( $dbh, $biblio );
958 "select biblioitemnumber from biblioitems where biblionumber=?");
959 $sth->execute($biblio);
960 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
961 REALdelbiblioitem( $dbh, $biblioitemnumber );
963 &MARCdelbiblio( $dbh, $bibid, 0 );
966 =head2 $itemnumber = NEWnewitem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber);
970 creates an item from a MARC::Record
977 my ( $dbh,$Zconn,$record,$biblionumber,$biblioitemnumber ) = @_;
980 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
981 my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
982 # needs old biblionumber and biblioitemnumber
983 $item->{'biblionumber'} = $biblionumber;
984 $item->{'biblioitemnumber'}=$biblioitemnumber;
985 $item->{marc} = $record->as_usmarc();
987 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $Zconn, $item, $item->{barcode} );
992 =head2 $itemnumber = NEWmoditem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1003 my ( $dbh, $Zconn, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1005 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1006 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1008 $olditem->{marc} = $record->as_usmarc();
1009 $olditem->{biblionumber} = $biblionumber;
1010 $olditem->{biblioitemnumber} = $biblioitemnumber;
1012 REALmoditem( $dbh, $Zconn, $olditem );
1016 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1027 my ( $dbh, $bibid, $itemnumber ) = @_;
1028 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1029 &REALdelitem( $dbh, $itemnumber );
1030 &MARCdelitem( $dbh, $bibid, $itemnumber );
1034 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
1038 adds a record in biblio table. Datas are in the hash $biblio.
1045 my ( $dbh, $biblio ) = @_;
1047 $dbh->do('lock tables biblio WRITE');
1048 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1050 my $data = $sth->fetchrow_arrayref;
1051 my $bibnum = $$data[0] + 1;
1054 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1057 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1058 serial=?, seriestitle=?, notes=?, abstract=?,
1062 $bibnum, $biblio->{'title'},
1063 $biblio->{'author'}, $biblio->{'copyrightdate'},
1064 $biblio->{'serial'}, $biblio->{'seriestitle'},
1065 $biblio->{'notes'}, $biblio->{'abstract'},
1066 $biblio->{'unititle'}
1070 $dbh->do('unlock tables');
1074 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
1078 modify a record in biblio table. Datas are in the hash $biblio.
1085 my ( $dbh, $biblio ) = @_;
1086 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1087 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1088 where biblionumber = ?"
1091 $biblio->{'title'}, $biblio->{'author'},
1092 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1093 $biblio->{'seriestitle'}, $biblio->{'serial'},
1094 $biblio->{'unititle'}, $biblio->{'notes'},
1095 $biblio->{frameworkcode},
1096 $biblio->{'biblionumber'}
1099 return ( $biblio->{'biblionumber'} );
1102 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
1106 modify subtitles in bibliosubtitle table.
1112 sub REALmodsubtitle {
1113 my ( $dbh, $bibnum, $subtitle ) = @_;
1116 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1117 $sth->execute( $subtitle, $bibnum );
1121 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1125 adds or modify additional authors
1126 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1132 sub REALmodaddauthor {
1133 my ( $dbh, $bibnum, @authors ) = @_;
1135 # my $dbh = C4Connect;
1137 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1139 $sth->execute($bibnum);
1141 foreach my $author (@authors) {
1142 if ( $author ne '' ) {
1145 "Insert into additionalauthors set author = ?, biblionumber = ?"
1148 $sth->execute( $author, $bibnum );
1153 } # sub modaddauthor
1155 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1159 modify/adds subjects
1164 sub REALmodsubject {
1165 my ( $dbh, $bibnum, $force, @subject ) = @_;
1167 # my $dbh = C4Connect;
1168 my $count = @subject;
1170 for ( my $i = 0 ; $i < $count ; $i++ ) {
1171 $subject[$i] =~ s/^ //g;
1172 $subject[$i] =~ s/ $//g;
1175 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1177 $sth->execute( $subject[$i] );
1179 if ( my $data = $sth->fetchrow_hashref ) {
1182 if ( $force eq $subject[$i] || $force == 1 ) {
1184 # subject not in aut, chosen to force anway
1185 # so insert into cataloguentry so its in auth file
1188 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1191 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1196 "$subject[$i]\n does not exist in the subject authority file";
1199 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1201 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1203 while ( my $data = $sth2->fetchrow_hashref ) {
1204 $error .= "<br>$data->{'catalogueentry'}";
1213 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1214 $sth->execute($bibnum);
1218 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1220 foreach $query (@subject) {
1221 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1230 =head2 REALmodbiblioitem($dbh, $biblioitem);
1239 sub REALmodbiblioitem {
1240 my ( $dbh, $Zconn, $biblioitem ) = @_;
1243 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1244 itemtype=?, url=?, isbn=?, issn=?,
1245 publishercode=?, publicationyear=?, classification=?, dewey=?,
1246 subclass=?, illus=?, pages=?, volumeddesc=?,
1247 notes=?, size=?, place=?, marc=?,
1249 where biblioitemnumber=?");
1250 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1251 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1252 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1253 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1254 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1255 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1256 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1258 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1259 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1260 #z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1263 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1266 =head2 REALnewbiblioitem($dbh,$Zconn,$biblioitem);
1270 adds a biblioitem ($biblioitem is a hash with the values)
1276 sub REALnewbiblioitem {
1277 my ( $dbh, $Zconn, $biblioitem ) = @_;
1279 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1280 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1282 my $biblioitemnumber;
1285 $data = $sth->fetchrow_arrayref;
1286 $biblioitemnumber = $$data[0] + 1;
1288 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1289 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1290 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1291 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1292 my $field=$record->field($biblioitemnumberfield);
1293 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1294 $biblioitem->{marc} = $record->as_usmarc();
1295 $biblioitem->{marcxml} = $record->as_xml();
1297 $sth = $dbh->prepare( "insert into biblioitems set
1298 biblioitemnumber = ?, biblionumber = ?,
1299 volume = ?, number = ?,
1300 classification = ?, itemtype = ?,
1302 issn = ?, dewey = ?,
1303 subclass = ?, publicationyear = ?,
1304 publishercode = ?, volumedate = ?,
1305 volumeddesc = ?, illus = ?,
1306 pages = ?, notes = ?,
1308 marc = ?, place = ?,
1312 $biblioitemnumber, $biblioitem->{'biblionumber'},
1313 $biblioitem->{'volume'}, $biblioitem->{'number'},
1314 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1315 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1316 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1317 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1318 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1319 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1320 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1321 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1322 $biblioitem->{'marc'}, $biblioitem->{'place'},
1323 $biblioitem->{marcxml},
1325 $dbh->do("unlock tables");
1326 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1327 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1328 #z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1329 #zebra_create($biblioitem->{biblionumber}, $record);
1330 return ($biblioitemnumber);
1333 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1337 create a new subtitle
1342 sub REALnewsubtitle {
1343 my ( $dbh, $bibnum, $subtitle ) = @_;
1346 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1347 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1351 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$Zconn,$item,$barcode);
1355 create a item. $item is a hash and $barcode the barcode.
1362 my ( $dbh, $Zconn,$item, $barcode ) = @_;
1364 # warn "OLDNEWITEMS";
1366 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1367 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1372 $data = $sth->fetchrow_hashref;
1373 $itemnumber = $data->{'max(itemnumber)'} + 1;
1375 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1376 if ( $item->{'loan'} ) {
1377 $item->{'notforloan'} = $item->{'loan'};
1379 $item->{'biblioitemnumber'} = 1;
1380 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1381 if ( $item->{'dateaccessioned'} ) {
1382 $sth = $dbh->prepare( "Insert into items set
1383 itemnumber = ?, biblionumber = ?,
1384 multivolumepart = ?,
1385 biblioitemnumber = ?, barcode = ?,
1386 booksellerid = ?, dateaccessioned = ?,
1387 homebranch = ?, holdingbranch = ?,
1388 price = ?, replacementprice = ?,
1389 replacementpricedate = NOW(), datelastseen = NOW(),
1390 multivolume = ?, stack = ?,
1391 itemlost = ?, wthdrawn = ?,
1392 paidfor = ?, itemnotes = ?,
1393 itemcallnumber =?, notforloan = ?,
1398 $itemnumber, $item->{'biblionumber'},
1399 $item->{'multivolumepart'},
1400 $item->{'biblioitemnumber'},$item->{barcode},
1401 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1402 $item->{'homebranch'}, $item->{'holdingbranch'},
1403 $item->{'price'}, $item->{'replacementprice'},
1404 $item->{multivolume}, $item->{stack},
1405 $item->{itemlost}, $item->{wthdrawn},
1406 $item->{paidfor}, $item->{'itemnotes'},
1407 $item->{'itemcallnumber'}, $item->{'notforloan'},
1410 if ( defined $sth->errstr ) {
1411 $error .= $sth->errstr;
1415 $sth = $dbh->prepare( "Insert into items set
1416 itemnumber = ?, biblionumber = ?,
1417 multivolumepart = ?,
1418 biblioitemnumber = ?, barcode = ?,
1419 booksellerid = ?, dateaccessioned = NOW(),
1420 homebranch = ?, holdingbranch = ?,
1421 price = ?, replacementprice = ?,
1422 replacementpricedate = NOW(), datelastseen = NOW(),
1423 multivolume = ?, stack = ?,
1424 itemlost = ?, wthdrawn = ?,
1425 paidfor = ?, itemnotes = ?,
1426 itemcallnumber =?, notforloan = ?,
1431 $itemnumber, $item->{'biblionumber'},
1432 $item->{'multivolumepart'},
1433 $item->{'biblioitemnumber'},$item->{barcode},
1434 $item->{'booksellerid'},
1435 $item->{'homebranch'}, $item->{'holdingbranch'},
1436 $item->{'price'}, $item->{'replacementprice'},
1437 $item->{multivolume}, $item->{stack},
1438 $item->{itemlost}, $item->{wthdrawn},
1439 $item->{paidfor}, $item->{'itemnotes'},
1440 $item->{'itemcallnumber'}, $item->{'notforloan'},
1443 if ( defined $sth->errstr ) {
1444 $error .= $sth->errstr;
1447 # item stored, now, deal with the marc part...
1448 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1449 where biblio.biblionumber=biblioitems.biblionumber and
1450 biblio.biblionumber=?");
1451 $sth->execute($item->{biblionumber});
1452 if ( defined $sth->errstr ) {
1453 $error .= $sth->errstr;
1455 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1456 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1457 my $record = MARC::File::USMARC::decode($rawmarc);
1458 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1459 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1460 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1462 warn $itemnumberfield;
1463 warn $itemrecord->field($itemnumberfield);
1464 my $itemfield = $itemrecord->field($itemnumberfield);
1465 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1466 $record->insert_grouped_field($itemfield);
1467 # save the record into biblioitem
1468 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1469 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1470 if ( defined $sth->errstr ) {
1471 $error .= $sth->errstr;
1473 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1474 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1475 # z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1476 #zebra_create($item->{biblionumber},$record);
1477 $dbh->do('unlock tables');
1478 return ( $itemnumber, $error );
1481 =head2 REALmoditem($dbh,$Zconn,$item);
1492 my ( $dbh, $Zconn, $item ) = @_;
1493 $item->{'bibitemnum'} = 1;
1495 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1496 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1497 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1499 $item->{'barcode'}, $item->{'itemnotes'},
1500 $item->{'itemcallnumber'}, $item->{'notforloan'},
1501 $item->{'location'}, $item->{multivolumepart},
1502 $item->{multivolume}, $item->{stack},
1505 if ( $item->{'lost'} ne '' ) {
1506 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1507 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1508 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1510 $item->{'bibitemnum'}, $item->{'barcode'},
1511 $item->{'itemnotes'}, $item->{'homebranch'},
1512 $item->{'lost'}, $item->{'wthdrawn'},
1513 $item->{'itemcallnumber'}, $item->{'notforloan'},
1514 $item->{'location'}, $item->{multivolumepart},
1515 $item->{multivolume}, $item->{stack},
1518 if ($item->{homebranch}) {
1519 $query.=",homebranch=?";
1520 push @bind, $item->{homebranch};
1522 if ($item->{holdingbranch}) {
1523 $query.=",holdingbranch=?";
1524 push @bind, $item->{holdingbranch};
1527 $query.=" where itemnumber=?";
1528 push @bind,$item->{'itemnum'};
1529 if ( $item->{'replacement'} ne '' ) {
1530 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1532 my $sth = $dbh->prepare($query);
1533 $sth->execute(@bind);
1535 # item stored, now, deal with the marc part...
1536 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1537 where biblio.biblionumber=biblioitems.biblionumber and
1538 biblio.biblionumber=? and
1539 biblioitems.biblioitemnumber=?");
1540 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1541 if ( defined $sth->errstr ) {
1542 $error .= $sth->errstr;
1544 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1545 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1546 my $record = MARC::File::USMARC::decode($rawmarc);
1547 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1548 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1549 # prepare the new item record
1550 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1551 my $itemfield = $itemrecord->field($itemnumberfield);
1552 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1553 # parse all fields fields from the complete record
1554 foreach ($record->field($itemnumberfield)) {
1555 # when the previous field is found, replace by the new one
1556 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1557 $_->replace_with($itemfield);
1560 # $record->insert_grouped_field($itemfield);
1561 # save the record into biblioitem
1562 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1563 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1564 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1565 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1566 # z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1567 #zebra_create($item->biblionumber,$record);
1568 if ( defined $sth->errstr ) {
1569 $error .= $sth->errstr;
1571 $dbh->do('unlock tables');
1576 =head2 REALdelitem($dbh,$itemnum);
1587 my ( $dbh, $itemnum ) = @_;
1589 # my $dbh=C4Connect;
1590 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1591 $sth->execute($itemnum);
1592 my $data = $sth->fetchrow_hashref;
1594 my $query = "Insert into deleteditems set ";
1596 foreach my $temp ( keys %$data ) {
1597 $query .= "$temp = ?,";
1598 push ( @bind, $data->{$temp} );
1603 $sth = $dbh->prepare($query);
1604 $sth->execute(@bind);
1606 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1607 $sth->execute($itemnum);
1613 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1617 deletes a biblioitem
1618 NOTE : not standard sub name. Should be REALdelbiblioitem()
1624 sub REALdelbiblioitem {
1625 my ( $dbh, $biblioitemnumber ) = @_;
1627 # my $dbh = C4Connect;
1628 my $sth = $dbh->prepare( "Select * from biblioitems
1629 where biblioitemnumber = ?"
1633 $sth->execute($biblioitemnumber);
1635 if ( $results = $sth->fetchrow_hashref ) {
1639 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1640 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1641 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1645 $results->{biblioitemnumber}, $results->{biblionumber},
1646 $results->{volume}, $results->{number},
1647 $results->{classification}, $results->{itemtype},
1648 $results->{isbn}, $results->{issn},
1649 $results->{dewey}, $results->{subclass},
1650 $results->{publicationyear}, $results->{publishercode},
1651 $results->{volumedate}, $results->{volumeddesc},
1652 $results->{timestamp}, $results->{illus},
1653 $results->{pages}, $results->{notes},
1654 $results->{size}, $results->{url},
1658 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1659 $sth2->execute($biblioitemnumber);
1664 # Now delete all the items attached to the biblioitem
1665 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1666 $sth->execute($biblioitemnumber);
1668 while ( my $data = $sth->fetchrow_hashref ) {
1669 my $query = "Insert into deleteditems set ";
1671 foreach my $temp ( keys %$data ) {
1672 $query .= "$temp = ?,";
1673 push ( @bind, $data->{$temp} );
1676 my $sth2 = $dbh->prepare($query);
1677 $sth2->execute(@bind);
1680 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1681 $sth->execute($biblioitemnumber);
1685 } # sub deletebiblioitem
1687 =head2 REALdelbiblio($dbh,$biblio);
1698 my ( $dbh, $biblio ) = @_;
1699 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1700 $sth->execute($biblio);
1701 if ( my $data = $sth->fetchrow_hashref ) {
1703 my $query = "Insert into deletedbiblio set ";
1705 foreach my $temp ( keys %$data ) {
1706 $query .= "$temp = ?,";
1707 push ( @bind, $data->{$temp} );
1710 #replacing the last , by ",?)"
1712 $sth = $dbh->prepare($query);
1713 $sth->execute(@bind);
1715 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1716 $sth->execute($biblio);
1722 =head2 $number = itemcount($biblio);
1726 returns the number of items attached to a biblio
1734 my $dbh = C4::Context->dbh;
1737 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1738 $sth->execute($biblio);
1739 my $data = $sth->fetchrow_hashref;
1741 return ( $data->{'count(*)'} );
1744 =head2 $biblionumber = newbiblio($biblio);
1748 create a biblio. The parameter is a hash
1756 my $dbh = C4::Context->dbh;
1757 my $bibnum = REALnewbiblio( $dbh, $biblio );
1758 # finds new (MARC bibid
1759 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1760 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1761 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1765 =head2 $biblionumber = &modbiblio($biblio);
1769 Update a biblio record.
1771 C<$biblio> is a reference-to-hash whose keys are the fields in the
1772 biblio table in the Koha database. All fields must be present, not
1773 just the ones you wish to change.
1775 C<&modbiblio> updates the record defined by
1776 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1778 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1787 my $dbh = C4::Context->dbh;
1788 my $biblionumber=REALmodbiblio($dbh,$biblio);
1789 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1790 # finds new (MARC bibid
1791 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1792 MARCmodbiblio($dbh,$bibid,$record,"",0);
1793 return($biblionumber);
1796 =head2 &modsubtitle($biblionumber, $subtitle);
1800 Sets the subtitle of a book.
1802 C<$biblionumber> is the biblionumber of the book to modify.
1804 C<$subtitle> is the new subtitle.
1811 my ( $bibnum, $subtitle ) = @_;
1812 my $dbh = C4::Context->dbh;
1813 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1816 =head2 &modaddauthor($biblionumber, $author);
1820 Replaces all additional authors for the book with biblio number
1821 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1822 C<&modaddauthor> deletes all additional authors.
1829 my ( $bibnum, @authors ) = @_;
1830 my $dbh = C4::Context->dbh;
1831 &REALmodaddauthor( $dbh, $bibnum, @authors );
1832 } # sub modaddauthor
1834 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1838 $force - a subject to force
1839 $error - Error message, or undef if successful.
1846 my ( $bibnum, $force, @subject ) = @_;
1847 my $dbh = C4::Context->dbh;
1848 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1850 # When MARC is off, ensures that the MARC biblio table gets updated with new
1851 # subjects, of course, it deletes the biblio in marc, and then recreates.
1852 # This check is to ensure that no MARC data exists to lose.
1853 # if (C4::Context->preference("MARC") eq '0'){
1854 # warn "in modSUBJECT";
1855 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1856 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1857 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1863 =head2 modbibitem($dbh, $Zconn,$biblioitem);
1867 modify a biblioitem. The parameter is a hash
1874 my ($dbh, $Zconn, $biblioitem) = @_;
1875 #my $dbh = C4::Context->dbh;
1876 &REALmodbiblioitem( $dbh, $Zconn, $biblioitem );
1879 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1883 create a biblioitem, the parameter is a hash
1890 my ($dbh, $Zconn, $biblioitem) = @_;
1891 #my $dbh = C4::Context->dbh;
1892 # add biblio information to the hash
1893 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1894 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1895 my $bibitemnum = &REALnewbiblioitem( $dbh, $Zconn, $biblioitem );
1896 return ($bibitemnum);
1899 =head2 newsubtitle($biblionumber,$subtitle);
1903 insert a subtitle for $biblionumber biblio
1911 my ( $bibnum, $subtitle ) = @_;
1912 my $dbh = C4::Context->dbh;
1913 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1916 =head2 $errors = newitems($dbh, $Zconn, $item, @barcodes);
1920 insert items ($item is a hash)
1928 my ( $dbh, $Zconn, $item, @barcodes ) = @_;
1929 #my $dbh = C4::Context->dbh;
1933 foreach my $barcode (@barcodes) {
1934 # add items, one by one for each barcode.
1936 $oneitem->{barcode}= $barcode;
1937 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1938 $oneitem->{marc} = $MARCitem->as_usmarc;
1939 ( $itemnumber, $error ) = &REALnewitems( $dbh,$Zconn,$oneitem);
1940 # $errors .= $error;
1941 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1946 =head2 moditem($dbh,$Zconn,$item);
1950 modify an item ($item is a hash with all item informations)
1958 my ($dbh,$Zconn,$item) = @_;
1959 #my $dbh = C4::Context->dbh;
1960 &REALmoditem( $dbh, $Zconn, $item );
1962 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1964 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1965 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1968 =head2 $error = checkitems($count,@barcodes);
1972 check for each @barcode entry that the barcode is not a duplicate
1979 my ( $count, @barcodes ) = @_;
1980 my $dbh = C4::Context->dbh;
1982 my $sth = $dbh->prepare("Select * from items where barcode=?");
1983 for ( my $i = 0 ; $i < $count ; $i++ ) {
1984 $barcodes[$i] = uc $barcodes[$i];
1985 $sth->execute( $barcodes[$i] );
1986 if ( my $data = $sth->fetchrow_hashref ) {
1987 $error .= " Duplicate Barcode: $barcodes[$i]";
1994 =head2 $delitem($itemnum);
1998 delete item $itemnum being the item number to delete
2006 my $dbh = C4::Context->dbh;
2007 &REALdelitem( $dbh, $itemnum );
2010 =head2 deletebiblioitem($biblioitemnumber);
2014 delete the biblioitem $biblioitemnumber
2020 sub deletebiblioitem {
2021 my ($biblioitemnumber) = @_;
2022 my $dbh = C4::Context->dbh;
2023 &REALdelbiblioitem( $dbh, $biblioitemnumber );
2024 } # sub deletebiblioitem
2026 =head2 delbiblio($biblionumber)
2030 delete biblio $biblionumber
2038 my $dbh = C4::Context->dbh;
2039 &REALdelbiblio( $dbh, $biblio );
2040 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2041 &MARCdelbiblio( $dbh, $bibid, 0 );
2044 =head2 ($count,@results) = getbiblio($biblionumber);
2048 return an array with hash of biblios.
2050 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2057 my ($biblionumber) = @_;
2058 my $dbh = C4::Context->dbh;
2059 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2061 # || die "Cannot prepare $query\n" . $dbh->errstr;
2065 $sth->execute($biblionumber);
2067 # || die "Cannot execute $query\n" . $sth->errstr;
2068 while ( my $data = $sth->fetchrow_hashref ) {
2069 $results[$count] = $data;
2074 return ( $count, @results );
2079 $data = &bibdata($biblionumber, $type);
2081 Returns information about the book with the given biblionumber.
2083 C<$type> is ignored.
2085 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2086 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2089 In addition, C<$data-E<gt>{subject}> is the list of the book's
2090 subjects, separated by C<" , "> (space, comma, space).
2092 If there are multiple biblioitems with the given biblionumber, only
2093 the first one is considered.
2098 my ($bibnum, $type) = @_;
2099 my $dbh = C4::Context->dbh;
2100 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2102 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2103 left join bibliosubtitle on
2104 biblio.biblionumber = bibliosubtitle.biblionumber
2105 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2106 where biblio.biblionumber = ?
2108 $sth->execute($bibnum);
2110 $data = $sth->fetchrow_hashref;
2112 # handle management of repeated subtitle
2113 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2114 $sth->execute($bibnum);
2116 while (my $dat = $sth->fetchrow_hashref){
2118 $line{subtitle} = $dat->{subtitle};
2119 push @subtitles, \%line;
2121 $data->{subtitles} = \@subtitles;
2123 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2124 $sth->execute($bibnum);
2126 while (my $dat = $sth->fetchrow_hashref){
2128 $line{subject} = $dat->{'subject'};
2129 push @subjects, \%line;
2131 $data->{subjects} = \@subjects;
2133 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2134 $sth->execute($bibnum);
2135 while (my $dat = $sth->fetchrow_hashref){
2136 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2138 chop $data->{'additionalauthors'};
2139 chop $data->{'additionalauthors'};
2140 chop $data->{'additionalauthors'};
2145 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
2149 return an array with hash of biblioitemss.
2151 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2158 my ($biblioitemnum) = @_;
2159 my $dbh = C4::Context->dbh;
2160 my $sth = $dbh->prepare( "Select * from biblioitems where
2161 biblioitemnumber = ?"
2166 $sth->execute($biblioitemnum);
2168 while ( my $data = $sth->fetchrow_hashref ) {
2169 $results[$count] = $data;
2174 return ( $count, @results );
2175 } # sub getbiblioitem
2177 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2181 return an array with hash of biblioitems for the given biblionumber.
2187 sub getbiblioitembybiblionumber {
2188 my ($biblionumber) = @_;
2189 my $dbh = C4::Context->dbh;
2190 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2194 $sth->execute($biblionumber);
2196 while ( my $data = $sth->fetchrow_hashref ) {
2197 $results[$count] = $data;
2202 return ( $count, @results );
2205 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2209 returns an array with hash of items
2215 sub getitemsbybiblioitem {
2216 my ($biblioitemnum) = @_;
2217 my $dbh = C4::Context->dbh;
2218 my $sth = $dbh->prepare( "Select * from items, biblio where
2219 biblio.biblionumber = items.biblionumber and biblioitemnumber
2223 # || die "Cannot prepare $query\n" . $dbh->errstr;
2227 $sth->execute($biblioitemnum);
2229 # || die "Cannot execute $query\n" . $sth->errstr;
2230 while ( my $data = $sth->fetchrow_hashref ) {
2231 $results[$count] = $data;
2236 return ( $count, @results );
2237 } # sub getitemsbybiblioitem
2241 @results = &ItemInfo($env, $biblionumber, $type);
2243 Returns information about books with the given biblionumber.
2245 C<$type> may be either C<intra> or anything else. If it is not set to
2246 C<intra>, then the search will exclude lost, very overdue, and
2251 C<&ItemInfo> returns a list of references-to-hash. Each element
2252 contains a number of keys. Most of them are table items from the
2253 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2254 Koha database. Other keys include:
2258 =item C<$data-E<gt>{branchname}>
2260 The name (not the code) of the branch to which the book belongs.
2262 =item C<$data-E<gt>{datelastseen}>
2264 This is simply C<items.datelastseen>, except that while the date is
2265 stored in YYYY-MM-DD format in the database, here it is converted to
2266 DD/MM/YYYY format. A NULL date is returned as C<//>.
2268 =item C<$data-E<gt>{datedue}>
2270 =item C<$data-E<gt>{class}>
2272 This is the concatenation of C<biblioitems.classification>, the book's
2273 Dewey code, and C<biblioitems.subclass>.
2275 =item C<$data-E<gt>{ocount}>
2277 I think this is the number of copies of the book available.
2279 =item C<$data-E<gt>{order}>
2281 If this is set, it is set to C<One Order>.
2288 my ($env,$biblionumber,$type) = @_;
2289 my $dbh = C4::Context->dbh;
2290 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2291 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2292 WHERE items.biblionumber = ?
2293 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2294 AND biblio.biblionumber = items.biblionumber";
2295 $query .= " order by items.dateaccessioned desc";
2296 my $sth=$dbh->prepare($query);
2297 $sth->execute($biblionumber);
2300 while (my $data=$sth->fetchrow_hashref){
2302 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2303 $isth->execute($data->{'itemnumber'});
2304 if (my $idata=$isth->fetchrow_hashref){
2305 $data->{borrowernumber} = $idata->{borrowernumber};
2306 $data->{cardnumber} = $idata->{cardnumber};
2307 $datedue = format_date($idata->{'date_due'});
2309 if ($datedue eq ''){
2310 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2316 #get branch information.....
2317 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2318 $bsth->execute($data->{'holdingbranch'});
2319 if (my $bdata=$bsth->fetchrow_hashref){
2320 $data->{'branchname'} = $bdata->{'branchname'};
2322 my $date=format_date($data->{'datelastseen'});
2323 $data->{'datelastseen'}=$date;
2324 $data->{'datedue'}=$datedue;
2325 # get notforloan complete status if applicable
2326 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2327 $sthnflstatus->execute;
2328 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2329 if ($authorised_valuecode) {
2330 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2331 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2332 my ($lib) = $sthnflstatus->fetchrow;
2333 $data->{notforloan} = $lib;
2344 ($count, @results) = &bibitems($biblionumber);
2346 Given the biblionumber for a book, C<&bibitems> looks up that book's
2347 biblioitems (different publications of the same book, the audio book
2348 and film versions, etc.).
2350 C<$count> is the number of elements in C<@results>.
2352 C<@results> is an array of references-to-hash; the keys are the fields
2353 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2354 addition, C<itemlost> indicates the availability of the item: if it is
2355 "2", then all copies of the item are long overdue; if it is "1", then
2356 all copies are lost; otherwise, there is at least one copy available.
2362 my $dbh = C4::Context->dbh;
2363 my $sth = $dbh->prepare("SELECT biblioitems.*,
2365 MIN(items.itemlost) as itemlost,
2366 MIN(items.dateaccessioned) as dateaccessioned
2367 FROM biblioitems, itemtypes, items
2368 WHERE biblioitems.biblionumber = ?
2369 AND biblioitems.itemtype = itemtypes.itemtype
2370 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2371 GROUP BY items.biblioitemnumber");
2374 $sth->execute($bibnum);
2375 while (my $data = $sth->fetchrow_hashref) {
2376 $results[$count] = $data;
2380 return($count, @results);
2386 $itemdata = &bibitemdata($biblioitemnumber);
2388 Looks up the biblioitem with the given biblioitemnumber. Returns a
2389 reference-to-hash. The keys are the fields from the C<biblio>,
2390 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2391 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2397 my $dbh = C4::Context->dbh;
2398 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");
2401 $sth->execute($bibitem);
2403 $data = $sth->fetchrow_hashref;
2410 =item getbibliofromitemnumber
2412 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2414 Looks up the item with the given itemnumber.
2416 C<$env> and C<$dbh> are ignored.
2418 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2419 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2424 sub getbibliofromitemnumber {
2425 my ($env,$dbh,$itemnumber) = @_;
2426 $dbh = C4::Context->dbh;
2427 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2428 where items.itemnumber = ?
2429 and biblio.biblionumber = items.biblionumber
2430 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2432 $sth->execute($itemnumber);
2433 my $data=$sth->fetchrow_hashref;
2440 @barcodes = &barcodes($biblioitemnumber);
2442 Given a biblioitemnumber, looks up the corresponding items.
2444 Returns an array of references-to-hash; the keys are C<barcode> and
2447 The returned items include very overdue items, but not lost ones.
2452 #called from request.pl
2453 my ($biblioitemnumber)=@_;
2454 my $dbh = C4::Context->dbh;
2455 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2456 WHERE biblioitemnumber = ?
2457 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2458 $sth->execute($biblioitemnumber);
2461 while (my $data=$sth->fetchrow_hashref){
2462 $barcodes[$i]=$data;
2472 $item = &itemdata($barcode);
2474 Looks up the item with the given barcode, and returns a
2475 reference-to-hash containing information about that item. The keys of
2476 the hash are the fields from the C<items> and C<biblioitems> tables in
2481 sub get_item_from_barcode {
2483 my $dbh = C4::Context->dbh;
2484 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2485 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2486 $sth->execute($barcode);
2487 my $data=$sth->fetchrow_hashref;
2495 @issues = &itemissues($biblioitemnumber, $biblio);
2497 Looks up information about who has borrowed the bookZ<>(s) with the
2498 given biblioitemnumber.
2500 C<$biblio> is ignored.
2502 C<&itemissues> returns an array of references-to-hash. The keys
2503 include the fields from the C<items> table in the Koha database.
2504 Additional keys include:
2510 If the item is currently on loan, this gives the due date.
2512 If the item is not on loan, then this is either "Available" or
2513 "Cancelled", if the item has been withdrawn.
2517 If the item is currently on loan, this gives the card number of the
2518 patron who currently has the item.
2520 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2522 These give the timestamp for the last three times the item was
2525 =item C<card0>, C<card1>, C<card2>
2527 The card number of the last three patrons who borrowed this item.
2529 =item C<borrower0>, C<borrower1>, C<borrower2>
2531 The borrower number of the last three patrons who borrowed this item.
2538 my ($bibitem, $biblio)=@_;
2539 my $dbh = C4::Context->dbh;
2540 # FIXME - If this function die()s, the script will abort, and the
2541 # user won't get anything; depending on how far the script has
2542 # gotten, the user might get a blank page. It would be much better
2543 # to at least print an error message. The easiest way to do this
2544 # is to set $SIG{__DIE__}.
2545 my $sth = $dbh->prepare("Select * from items where
2546 items.biblioitemnumber = ?")
2547 || die $dbh->errstr;
2551 $sth->execute($bibitem)
2552 || die $sth->errstr;
2554 while (my $data = $sth->fetchrow_hashref) {
2555 # Find out who currently has this item.
2556 # FIXME - Wouldn't it be better to do this as a left join of
2557 # some sort? Currently, this code assumes that if
2558 # fetchrow_hashref() fails, then the book is on the shelf.
2559 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2560 # database server crash), not just because no items match the
2562 my $sth2 = $dbh->prepare("select * from issues,borrowers
2563 where itemnumber = ?
2564 and returndate is NULL
2565 and issues.borrowernumber = borrowers.borrowernumber");
2567 $sth2->execute($data->{'itemnumber'});
2568 if (my $data2 = $sth2->fetchrow_hashref) {
2569 $data->{'date_due'} = $data2->{'date_due'};
2570 $data->{'card'} = $data2->{'cardnumber'};
2571 $data->{'borrower'} = $data2->{'borrowernumber'};
2573 if ($data->{'wthdrawn'} eq '1') {
2574 $data->{'date_due'} = 'Cancelled';
2576 $data->{'date_due'} = 'Available';
2582 # Find the last 3 people who borrowed this item.
2583 $sth2 = $dbh->prepare("select * from issues, borrowers
2584 where itemnumber = ?
2585 and issues.borrowernumber = borrowers.borrowernumber
2586 and returndate is not NULL
2587 order by returndate desc,timestamp desc") || die $dbh->errstr;
2588 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2589 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2590 if (my $data2 = $sth2->fetchrow_hashref) {
2591 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2592 $data->{"card$i2"} = $data2->{'cardnumber'};
2593 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2598 $results[$i] = $data;
2608 ($count, $subjects) = &getsubject($biblionumber);
2610 Looks up the subjects of the book with the given biblionumber. Returns
2611 a two-element list. C<$subjects> is a reference-to-array, where each
2612 element is a subject of the book, and C<$count> is the number of
2613 elements in C<$subjects>.
2619 my $dbh = C4::Context->dbh;
2620 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2621 $sth->execute($bibnum);
2624 while (my $data=$sth->fetchrow_hashref){
2629 return($i,\@results);
2634 ($count, $authors) = &getaddauthor($biblionumber);
2636 Looks up the additional authors for the book with the given
2639 Returns a two-element list. C<$authors> is a reference-to-array, where
2640 each element is an additional author, and C<$count> is the number of
2641 elements in C<$authors>.
2647 my $dbh = C4::Context->dbh;
2648 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2649 $sth->execute($bibnum);
2652 while (my $data=$sth->fetchrow_hashref){
2657 return($i,\@results);
2663 ($count, $subtitles) = &getsubtitle($biblionumber);
2665 Looks up the subtitles for the book with the given biblionumber.
2667 Returns a two-element list. C<$subtitles> is a reference-to-array,
2668 where each element is a subtitle, and C<$count> is the number of
2669 elements in C<$subtitles>.
2675 my $dbh = C4::Context->dbh;
2676 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2677 $sth->execute($bibnum);
2680 while (my $data=$sth->fetchrow_hashref){
2685 return($i,\@results);
2691 ($count, @websites) = &getwebsites($biblionumber);
2693 Looks up the web sites pertaining to the book with the given
2696 C<$count> is the number of elements in C<@websites>.
2698 C<@websites> is an array of references-to-hash; the keys are the
2699 fields from the C<websites> table in the Koha database.
2702 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2703 #(with add / modify / delete subs)
2706 my ($biblionumber) = @_;
2707 my $dbh = C4::Context->dbh;
2708 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2712 $sth->execute($biblionumber);
2713 while (my $data = $sth->fetchrow_hashref) {
2714 # FIXME - The URL scheme shouldn't be stripped off, at least
2715 # not here, since it's part of the URL, and will be useful in
2716 # constructing a link to the site. If you don't want the user
2717 # to see the "http://" part, strip that off when building the
2719 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2721 $results[$count] = $data;
2726 return($count, @results);
2729 =item getwebbiblioitems
2731 ($count, @results) = &getwebbiblioitems($biblionumber);
2733 Given a book's biblionumber, looks up the web versions of the book
2734 (biblioitems with itemtype C<WEB>).
2736 C<$count> is the number of items in C<@results>. C<@results> is an
2737 array of references-to-hash; the keys are the items from the
2738 C<biblioitems> table of the Koha database.
2742 sub getwebbiblioitems {
2743 my ($biblionumber) = @_;
2744 my $dbh = C4::Context->dbh;
2745 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2746 and itemtype = 'WEB'");
2750 $sth->execute($biblionumber);
2751 while (my $data = $sth->fetchrow_hashref) {
2752 $data->{'url'} =~ s/^http:\/\///;
2753 $results[$count] = $data;
2758 return($count, @results);
2759 } # sub getwebbiblioitems
2763 # converts ISO 5426 coded string to ISO 8859-1
2764 # sloppy code : should be improved in next issue
2765 my ( $string, $encoding ) = @_;
2768 # $encoding = C4::Context->preference("marcflavour") unless $encoding;
2769 if ( $encoding eq "UNIMARC" ) {
2838 # this handles non-sorting blocks (if implementation requires this)
2839 $string = nsb_clean($_);
2841 elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
2842 if (/[\xc1-\xff]/) {
2895 # this handles non-sorting blocks (if implementation requires this)
2896 $string = nsb_clean($_);
2903 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2904 my $NSE = '\x89'; # NSE : Non Sorting Block end
2905 # handles non sorting blocks
2909 s/[ ]{0,1}$NSE/) /gm;
2916 my $dbh = C4::Context->dbh;
2917 my $result = MARCmarc2koha($dbh,$record,'');
2919 my ($biblionumber,$bibid,$title);
2920 # search duplicate on ISBN, easy and fast...
2921 if ($result->{isbn}) {
2922 $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=?");
2923 $sth->execute($result->{'isbn'});
2924 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2925 return $biblionumber,$bibid,$title if ($biblionumber);
2927 # a more complex search : build a request for SearchMarc::catalogsearch()
2928 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2929 # search on biblio.title
2930 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2931 if ($record->field($tag)) {
2932 if ($record->field($tag)->subfields($subfield)) {
2933 push @tags, "'".$tag.$subfield."'";
2934 push @and_or, "and";
2935 push @excluding, "";
2936 push @operator, "contains";
2937 push @value, $record->field($tag)->subfield($subfield);
2938 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2941 # ... and on biblio.author
2942 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2943 if ($record->field($tag)) {
2944 if ($record->field($tag)->subfields($subfield)) {
2945 push @tags, "'".$tag.$subfield."'";
2946 push @and_or, "and";
2947 push @excluding, "";
2948 push @operator, "contains";
2949 push @value, $record->field($tag)->subfield($subfield);
2950 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2953 # ... and on publicationyear.
2954 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2955 if ($record->field($tag)) {
2956 if ($record->field($tag)->subfields($subfield)) {
2957 push @tags, "'".$tag.$subfield."'";
2958 push @and_or, "and";
2959 push @excluding, "";
2960 push @operator, "=";
2961 push @value, $record->field($tag)->subfield($subfield);
2962 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2966 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2967 if ($record->field($tag)) {
2968 if ($record->field($tag)->subfields($subfield)) {
2969 push @tags, "'".$tag.$subfield."'";
2970 push @and_or, "and";
2971 push @excluding, "";
2972 push @operator, "=";
2973 push @value, $record->field($tag)->subfield($subfield);
2974 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2977 # ... and on publisher.
2978 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2979 if ($record->field($tag)) {
2980 if ($record->field($tag)->subfields($subfield)) {
2981 push @tags, "'".$tag.$subfield."'";
2982 push @and_or, "and";
2983 push @excluding, "";
2984 push @operator, "=";
2985 push @value, $record->field($tag)->subfield($subfield);
2986 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2989 # ... and on volume.
2990 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2991 if ($record->field($tag)) {
2992 if ($record->field($tag)->subfields($subfield)) {
2993 push @tags, "'".$tag.$subfield."'";
2994 push @and_or, "and";
2995 push @excluding, "";
2996 push @operator, "=";
2997 push @value, $record->field($tag)->subfield($subfield);
2998 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
3002 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
3003 # there is at least 1 result => return the 1st one
3005 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
3006 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
3008 # no result, returns nothing
3015 if(substr($isbn, 0, 1) <=7) {
3016 $seg1 = substr($isbn, 0, 1);
3017 } elsif(substr($isbn, 0, 2) <= 94) {
3018 $seg1 = substr($isbn, 0, 2);
3019 } elsif(substr($isbn, 0, 3) <= 995) {
3020 $seg1 = substr($isbn, 0, 3);
3021 } elsif(substr($isbn, 0, 4) <= 9989) {
3022 $seg1 = substr($isbn, 0, 4);
3024 $seg1 = substr($isbn, 0, 5);
3026 my $x = substr($isbn, length($seg1));
3028 if(substr($x, 0, 2) <= 19) {
3029 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
3030 $seg2 = substr($x, 0, 2);
3031 } elsif(substr($x, 0, 3) <= 699) {
3032 $seg2 = substr($x, 0, 3);
3033 } elsif(substr($x, 0, 4) <= 8399) {
3034 $seg2 = substr($x, 0, 4);
3035 } elsif(substr($x, 0, 5) <= 89999) {
3036 $seg2 = substr($x, 0, 5);
3037 } elsif(substr($x, 0, 6) <= 9499999) {
3038 $seg2 = substr($x, 0, 6);
3040 $seg2 = substr($x, 0, 7);
3042 my $seg3=substr($x,length($seg2));
3043 $seg3=substr($seg3,0,length($seg3)-1) ;
3044 my $seg4 = substr($x, -1, 1);
3045 return "$seg1-$seg2-$seg3-$seg4";
3049 END { } # module clean-up code here (global destructor)
3055 Koha Developement team <info@koha.org>
3057 Paul POULAIN paul.poulain@free.fr
3063 # Revision 1.147 2006/02/25 19:09:59 kados
3064 # readding some lost subs
3066 # Revision 1.145 2006/02/22 01:02:39 kados
3067 # Replacing all calls to zebra_update with calls to
3068 # z3950_extended_services. More work coming, but it's
3071 # Revision 1.144 2006/02/20 14:22:38 kados
3074 # Revision 1.143 2006/02/20 13:26:11 kados
3075 # A new subroutine to handle Z39.50 extended services. You pass it a
3076 # connection object, service type, service options, and a record, and
3077 # it performs the service and handles any exception found.
3079 # Revision 1.142 2006/02/16 20:49:56 kados
3080 # destroy a connection after we're done -- we really should just have one
3081 # connection object and not destroy it until the whole transaction is
3082 # finished -- but this will do for now
3084 # Revision 1.141 2006/02/16 19:47:22 rangi
3085 # Trying to error trap a little more.
3087 # Revision 1.140 2006/02/14 21:36:03 kados
3088 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3089 # also adding diagnostic error if not able to connect to Zebra
3091 # Revision 1.139 2006/02/14 19:53:25 rangi
3092 # Just a little missing my
3094 # Seems to be working great Paul, and I like what you did with zebradb
3096 # Revision 1.138 2006/02/14 11:25:22 tipaul
3097 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3099 # Revision 1.137 2006/02/13 16:34:26 tipaul
3100 # fixing some warnings (perl -w should be quiet)
3102 # Revision 1.136 2006/01/10 17:01:29 tipaul
3103 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3105 # Revision 1.135 2006/01/06 16:39:37 tipaul
3106 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3107 # Seems not to break too many things, but i'm probably wrong here.
3108 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3110 # - removing useless directories (koha-html and koha-plucene)
3112 # Revision 1.134 2006/01/04 15:54:55 tipaul
3113 # utf8 is a : go for beta test in HEAD.
3114 # some explanations :
3115 # - 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.
3116 # - *-top.inc will show the pages in utf8
3117 # - 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.
3118 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3120 # Revision 1.133 2005/12/12 14:25:51 thd
3123 # Reverse array filled with elements from repeated subfields
3124 # to avoid last to first concatenation of elements in Koha DB.-
3126 # Revision 1.132 2005-10-26 09:12:33 tipaul
3127 # big commit, still breaking things...
3129 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3130 # * code cleaning (cleaning warnings from perl -w) continued
3132 # Revision 1.131 2005/09/22 10:01:45 tipaul
3133 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3135 # Revision 1.130 2005/09/02 14:34:14 tipaul
3136 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3137 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3138 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3140 # Revision 1.129 2005/08/12 13:50:31 tipaul
3141 # removing useless sub declarations
3143 # Revision 1.128 2005/08/11 16:12:47 tipaul
3144 # Playing with the zebra...
3146 # * go to koha cvs home directory
3147 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3148 # * put your zebra.cfg files here & create your database.
3149 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3150 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3153 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3154 # * deletion still not work
3155 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3157 # recordId: (bib1,Local-number)
3161 # elm 090 Local-number -
3162 # elm 090/? Local-number -
3163 # elm 090/?/9 Local-number !:w
3165 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3167 # Revision 1.127 2005/08/11 14:37:32 tipaul
3169 # * removing useless subs
3170 # * removing some subs that are also elsewhere
3171 # * 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)
3173 # Revision 1.126 2005/08/11 09:13:28 tipaul
3174 # just removing useless subs (a lot !!!) for code cleaning
3176 # Revision 1.125 2005/08/11 09:00:07 tipaul
3177 # Ok guys, this time, it seems that item add and modif begin working as expected...
3178 # Still a lot of bugs to fix, of course
3180 # Revision 1.124 2005/08/10 10:21:15 tipaul
3181 # continuing the road to zebra :
3182 # - the biblio add begins to work.
3183 # - the biblio modif begins to work.
3185 # (still without doing anything on zebra)
3186 # (no new change in updatedatabase)
3188 # Revision 1.123 2005/08/09 14:10:28 tipaul
3189 # 1st commit to go to zebra.
3190 # don't update your cvs if you want to have a working head...
3192 # this commit contains :
3193 # * 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...
3194 # * 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.
3195 # * other files : get rid of bibid and use biblionumber instead.
3198 # * does not do anything on zebra yet.
3199 # * if you rename marc_subfield_table, you can't search anymore.
3200 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3201 # * 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 ;-) )
3203 # 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
3204 # 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.
3206 # tipaul cutted previous commit notes