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;
29 use vars qw($VERSION @ISA @EXPORT);
31 # set the version for version checking
32 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
33 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
38 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
39 # as the old-style API and the NEW one are the only public functions.
42 &newbiblio &newbiblioitem
43 &newsubject &newsubtitle &newitems
45 &modbiblio &checkitems &modbibitem
46 &modsubtitle &modsubject &modaddauthor &moditem
48 &delitem &deletebiblioitem &delbiblio
50 &getbiblio &bibdata &bibitems &bibitemdata
51 &barcodes &ItemInfo &itemdata &itemissues &itemcount
52 &getsubject &getaddauthor &getsubtitle
53 &getwebbiblioitems &getwebsites
54 &getbiblioitembybiblionumber
55 &getbiblioitem &getitemsbybiblioitem
57 &MARCfind_marc_from_kohafield
58 &MARCfind_frameworkcode
59 &find_biblioitemnumber
62 &NEWnewbiblio &NEWnewitem
63 &NEWmodbiblio &NEWmoditem
64 &NEWdelbiblio &NEWdelitem
65 &NEWmodbiblioframework
67 &MARCkoha2marcBiblio &MARCmarc2koha
68 &MARCkoha2marcItem &MARChtml2marc
69 &MARCgetbiblio &MARCgetitem
75 &z3950_extended_services
78 &get_item_from_barcode
79 &MARCfind_MARCbibid_from_oldbiblionumber
85 C4::Biblio - Acquisitions, Catalog Management Functions
89 ( lot of changes for Koha 3.X)
91 Koha 1.2 and previous versions used a specific API to manage biblios. This API uses old-DB style parameters.
92 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors,
93 bibliosubject and bibliosubtitle where applicable).
95 In Koha 2.X, we introduced a MARC-DB.
97 In Koha 3.X, we removed this MARC-DB for search as we wanted to use Zebra as search system.
99 So in Koha 3.X, saving a record means :
101 - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items information.
102 - storing the "decoded information" in biblio/biblioitems/items as previously.
103 - using zebra to manage search & indexing on the MARC data.
105 In Koha, there is a systempreference for "MARC=ON" or "MARC=OFF" :
107 * MARC=ON : when MARC=ON, Koha uses a MARC::Record object (in sub parameters). Saving information in the DB means :
109 - transform the MARC record into a hash
110 - add the raw MARC record into the hash
111 - store them & update Zebra
113 * MARC=OFF : when MARC=OFF, Koha uses a hash object (in sub parameters). Saving information in the DB means :
115 - transform the hash into a MARC record
116 - add the raw marc record into the hash
117 - store them & update zebra
119 That's why we need 3 types of subs :
123 all I<subs beginning by REAL> do the effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in Zebra. REAL subs should be only for internal use (called by NEW or "something else" subs).
125 =head2 NEWxxx related subs
129 all I<subs beginning by NEW> use MARC::Record as parameters. It's the API that MUST be used in the MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
131 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. They sometimes require another parameter.
135 =head2 something_elsexxx related subs
139 all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and call REAL subs.
141 all subs require/use $dbh as 1st parameter and a hash as 2nd parameter.
147 =head2 z3950_extended_services
149 z3950_extended_services($serviceType,$serviceOptions,$record);
151 z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
153 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
155 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
157 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
161 recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
162 syntax => the record syntax (transfer syntax)
163 databaseName = Database from connection object
165 To set serviceOptions, call set_service_options($serviceType)
167 C<$record> the record, if one is needed for the service type
169 A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
172 sub z3950_extended_services {
173 my ($serviceType,$serviceOptions,$record) = @_;
175 my $Zconn = C4::Context->Zconn;
176 # create a new package object
177 my $Zpackage = $Zconn->package();
180 $Zpackage->option(action => $serviceOptions->{'action'});
182 if ($serviceOptions->{'databaseName'}) {
183 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
185 if ($serviceOptions->{'recordIdNumber'}) {
186 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
188 if ($serviceOptions->{'recordIdOpaque'}) {
189 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
192 # this is an ILL request (Zebra doesn't support it)
193 #if ($serviceType eq 'itemorder') {
194 # $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
195 # $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
196 # $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
197 # $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
201 my $xmlrecord = marc2xml($record);
202 $Zpackage->option(record => $xmlrecord);
203 if ($serviceOptions->{'syntax'}) {
204 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
208 # send the request, handle any exception encountered
209 eval { $Zpackage->send($serviceType) };
210 if ($@ && $@->isa("ZOOM::Exception")) {
211 print "Oops! ", $@->message(), "\n";
214 # free up package resources
215 $Zpackage->destroy();
218 =head2 set_service_options
220 my $serviceOptions = set_service_options($serviceType);
222 C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
224 Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
228 sub set_service_options {
229 my ($serviceType) = @_;
232 if ($serviceType eq 'update') {
233 $serviceOptions->{ 'action' } = 'specialUpdate';
235 # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
236 # $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
239 if ($serviceType eq 'commit') {
243 if ($serviceType eq 'create') {
246 if ($serviceType eq 'drop') {
247 die "ERROR: 'drop' not currently supported (by Zebra)";
249 return $serviceOptions;
254 my $xmlrecord = marc2xml($record);
256 Convert from MARC to XML. Note that MARC::File::XML will automatically encode from MARC-8 to UTF-8 as of version .8
258 C<$record> a MARC record
265 eval { $xmlrecord=$record->as_xml() };
266 #TODO: better error handling here
268 warn "ERROR: I suspect a badly formatted MARC record";
273 =head2 MARCgettagslib
275 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
279 2nd param is 1 for liblibrarian and 0 for libopac
280 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
282 returns a hash with all values for all fields and subfields for a given MARC framework :
283 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
285 ->{mandatory} = $mandatory;
286 ->{repeatable} = $repeatable;
287 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
289 ->{mandatory} = $mandatory;
290 ->{repeatable} = $repeatable;
291 ->{authorised_value} = $authorised_value;
292 ->{authtypecode} = $authtypecode;
293 ->{value_builder} = $value_builder;
294 ->{kohafield} = $kohafield;
295 ->{seealso} = $seealso;
296 ->{hidden} = $hidden;
305 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
306 $frameworkcode = "" unless $frameworkcode;
307 $forlibrarian = 1 unless $forlibrarian;
309 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
311 # check that framework exists
314 "select count(*) from marc_tag_structure where frameworkcode=?");
315 $sth->execute($frameworkcode);
316 my ($total) = $sth->fetchrow;
317 $frameworkcode = "" unless ( $total > 0 );
320 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
322 $sth->execute($frameworkcode);
323 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
325 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
326 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
327 $res->{$tag}->{tab} = ""; # XXX
328 $res->{$tag}->{mandatory} = $mandatory;
329 $res->{$tag}->{repeatable} = $repeatable;
334 "select tagfield,tagsubfield,liblibrarian,libopac,tab, mandatory, repeatable,authorised_value,authtypecode,value_builder,kohafield,seealso,hidden,isurl,link from marc_subfield_structure where frameworkcode=? order by tagfield,tagsubfield"
336 $sth->execute($frameworkcode);
339 my $authorised_value;
349 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
350 $mandatory, $repeatable, $authorised_value, $authtypecode,
351 $value_builder, $kohafield, $seealso, $hidden,
356 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
357 $res->{$tag}->{$subfield}->{tab} = $tab;
358 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
359 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
360 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
361 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
362 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
363 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
364 $res->{$tag}->{$subfield}->{seealso} = $seealso;
365 $res->{$tag}->{$subfield}->{hidden} = $hidden;
366 $res->{$tag}->{$subfield}->{isurl} = $isurl;
367 $res->{$tag}->{$subfield}->{link} = $link;
372 =head2 MARCfind_marc_from_kohafield
374 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
378 finds MARC tag and subfield for a given kohafield
379 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
385 sub MARCfind_marc_from_kohafield {
386 my ( $dbh, $kohafield,$frameworkcode ) = @_;
387 return 0, 0 unless $kohafield;
388 $frameworkcode='' unless $frameworkcode;
389 my $relations = C4::Context->marcfromkohafield;
390 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
395 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
399 Returns a MARC::Record for the biblio $biblionumber.
405 # Returns MARC::Record of the biblio passed in parameter.
406 my ( $dbh, $biblionumber ) = @_;
407 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
408 $sth->execute($biblionumber);
409 my ($marc) = $sth->fetchrow;
410 my $record = MARC::Record::new_from_usmarc($marc);
416 $XML = &XMLgetbiblio($dbh,$biblionumber);
420 Returns a raw XML for the biblio $biblionumber.
426 # Returns MARC::Record of the biblio passed in parameter.
427 my ( $dbh, $biblionumber ) = @_;
428 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
429 $sth->execute($biblionumber);
430 my ($XML,$marc) = $sth->fetchrow;
431 # my $record =MARC::Record::new_from_usmarc($marc);
432 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
438 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
442 Returns a MARC::Record with all items of biblio # $biblionumber
450 my ( $dbh, $biblionumber, $itemnumber ) = @_;
451 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
452 # get the complete MARC record
453 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
454 $sth->execute($biblionumber);
455 my ($rawmarc) = $sth->fetchrow;
456 my $record = MARC::File::USMARC::decode($rawmarc);
457 # now, find the relevant itemnumber
458 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
459 # prepare the new item record
460 my $itemrecord = MARC::Record->new();
461 # parse all fields fields from the complete record
462 foreach ($record->field($itemnumberfield)) {
463 # when the item field is found, save it
464 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
465 $itemrecord->append_fields($_);
472 =head2 find_biblioitemnumber
474 my $biblioitemnumber = find_biblioitemnumber($dbh,$biblionumber);
478 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
479 This sub is useless when MARC=OFF
484 sub find_biblioitemnumber {
485 my ( $dbh, $biblionumber ) = @_;
486 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
487 $sth->execute($biblionumber);
488 my ($biblioitemnumber) = $sth->fetchrow;
489 return $biblioitemnumber;
492 =head2 MARCfind_frameworkcode
494 my $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 MARCkoha2marcBiblio
514 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
518 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
519 all entries of the hash are transformed into their matching MARC field/subfield.
525 sub MARCkoha2marcBiblio {
527 # this function builds partial MARC::Record from the old koha-DB fields
528 my ( $dbh, $bibliohash ) = @_;
529 # we don't have biblio entries in the hash, so we add them first
530 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
531 $sth->execute($bibliohash->{biblionumber});
532 my $biblio = $sth->fetchrow_hashref;
533 foreach (keys %$biblio) {
534 $bibliohash->{$_}=$biblio->{$_};
536 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
537 my $record = MARC::Record->new();
538 foreach ( keys %$bibliohash ) {
539 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
540 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
543 # other fields => additional authors, subjects, subtitles
544 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
545 $sth2->execute($bibliohash->{biblionumber});
546 while ( my $row = $sth2->fetchrow_hashref ) {
547 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
549 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
550 $sth2->execute($bibliohash->{biblionumber});
551 while ( my $row = $sth2->fetchrow_hashref ) {
552 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
554 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
555 $sth2->execute($bibliohash->{biblionumber});
556 while ( my $row = $sth2->fetchrow_hashref ) {
557 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
563 =head2 MARCkoha2marcItem
565 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
567 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
568 all entries of the hash are transformed into their matching MARC field/subfield.
576 sub MARCkoha2marcItem {
578 # this function builds partial MARC::Record from the old koha-DB fields
579 my ( $dbh, $item ) = @_;
581 # my $dbh=&C4Connect;
582 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
583 my $record = MARC::Record->new();
585 foreach( keys %$item ) {
587 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
594 =head2 MARCkoha2marcOnefield
598 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
604 sub MARCkoha2marcOnefield {
605 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
608 $sth->execute($frameworkcode,$kohafieldname);
609 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
610 if ( $record->field($tagfield) ) {
611 my $tag = $record->field($tagfield);
613 $tag->add_subfields( $tagsubfield, $value );
614 $record->delete_field($tag);
615 $record->add_fields($tag);
619 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
627 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
631 transforms the parameters (coming from HTML form) into a MARC::Record
632 parameters with r are references to arrays.
634 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
641 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
643 my $record = MARC::Record->new();
644 # my %subfieldlist=();
645 my $prevvalue; # if tag <10
646 my $field; # if tag >=10
647 for (my $i=0; $i< @$rtags; $i++) {
648 next unless @$rvalues[$i];
649 # rebuild MARC::Record
650 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
651 if (@$rtags[$i] ne $prevtag) {
654 if ($prevtag ne '000') {
655 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
657 $record->leader($prevvalue);
662 $record->add_fields($field);
665 $indicators{@$rtags[$i]}.=' ';
666 if (@$rtags[$i] <10) {
667 $prevvalue= @$rvalues[$i];
671 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
672 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
674 $prevtag = @$rtags[$i];
676 if (@$rtags[$i] <10) {
677 $prevvalue=@$rvalues[$i];
679 if (length(@$rvalues[$i])>0) {
680 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
681 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
684 $prevtag= @$rtags[$i];
687 # the last has not been included inside the loop... do it now !
688 $record->add_fields($field) if $field;
689 # warn "HTML2MARC=".$record->as_formatted;
696 $hash = &MARCmarc2koha($dbh,$MARCRecord);
700 builds a hash with old-db datas from a MARC::Record
707 my ($dbh,$record,$frameworkcode) = @_;
708 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
710 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
713 while (($field)=$sth2->fetchrow) {
714 # warn "biblio.".$field;
715 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
717 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
719 while (($field)=$sth2->fetchrow) {
720 if ($field eq 'notes') { $field = 'bnotes'; }
721 # warn "biblioitems".$field;
722 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
724 $sth2=$dbh->prepare("SHOW COLUMNS from items");
726 while (($field)=$sth2->fetchrow) {
727 # warn "items".$field;
728 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
730 # additional authors : specific
731 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
732 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
733 # modify copyrightdate to keep only the 1st year found
734 my $temp = $result->{'copyrightdate'};
736 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
738 $result->{'copyrightdate'} = $1;
739 } else { # if no cYYYY, get the 1st date.
740 $temp =~ m/(\d\d\d\d)/;
741 $result->{'copyrightdate'} = $1;
744 # modify publicationyear to keep only the 1st year found
745 $temp = $result->{'publicationyear'};
746 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
748 $result->{'publicationyear'} = $1;
749 } else { # if no cYYYY, get the 1st date.
750 $temp =~ m/(\d\d\d\d)/;
751 $result->{'publicationyear'} = $1;
756 sub MARCmarc2kohaOneField {
758 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
759 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
760 # warn "kohatable / $kohafield / $result / ";
764 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
765 foreach my $field ( $record->field($tagfield) ) {
766 if ($field->tag()<10) {
767 if ($result->{$kohafield}) {
768 # Reverse array filled with elements from repeated subfields
769 # from first to last to avoid last to first concatenation of
770 # elements in Koha DB. -- thd.
771 $result->{$kohafield} .= " | ".reverse($field->data());
773 $result->{$kohafield} = $field->data();
776 if ( $field->subfields ) {
777 my @subfields = $field->subfields();
778 foreach my $subfieldcount ( 0 .. $#subfields ) {
779 if ($subfields[$subfieldcount][0] eq $subfield) {
780 if ( $result->{$kohafield} ) {
781 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
784 $result->{$kohafield} = $subfields[$subfieldcount][1];
791 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
797 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
801 creates a biblio from a MARC::Record.
808 my ( $dbh,$record,$frameworkcode ) = @_;
810 my $biblioitemnumber;
811 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
812 $olddata->{frameworkcode} = $frameworkcode;
813 $biblionumber = REALnewbiblio( $dbh, $olddata );
814 $olddata->{biblionumber} = $biblionumber;
815 # add biblionumber into the MARC record (it's the ID for zebra)
816 my ( $tagfield, $tagsubfield ) =
817 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
821 $newfield = MARC::Field->new(
822 $tagfield, $biblionumber,
825 $newfield = MARC::Field->new(
826 $tagfield, '', '', "$tagsubfield" => $biblionumber,
829 # drop old field (just in case it already exist and create new one...
830 my $old_field = $record->field($tagfield);
831 $record->delete_field($old_field);
832 $record->add_fields($newfield);
834 #create the marc entry, that stores the rax marc record in Koha 3.0
835 $olddata->{marc} = $record->as_usmarc();
836 $olddata->{marcxml} = $record->as_xml();
837 # and create biblioitem, that's all folks !
838 $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
840 # search subtiles, addiauthors and subjects
841 ( $tagfield, $tagsubfield ) =
842 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
843 my @addiauthfields = $record->field($tagfield);
844 foreach my $addiauthfield (@addiauthfields) {
845 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
846 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
847 REALmodaddauthor( $dbh, $biblionumber,
848 $addiauthsubfields[$subfieldcount] );
851 ( $tagfield, $tagsubfield ) =
852 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
853 my @subtitlefields = $record->field($tagfield);
854 foreach my $subtitlefield (@subtitlefields) {
855 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
856 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
857 REALnewsubtitle( $dbh, $biblionumber,
858 $subtitlesubfields[$subfieldcount] );
861 ( $tagfield, $tagsubfield ) =
862 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
863 my @subj = $record->field($tagfield);
865 foreach my $subject (@subj) {
866 my @subjsubfield = $subject->subfield($tagsubfield);
867 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
868 push @subjects, $subjsubfield[$subfieldcount];
871 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
872 return ( $biblionumber, $biblioitemnumber );
875 =head2 NEWmodbilbioframework
877 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
881 modify the framework of a biblio
887 sub NEWmodbiblioframework {
888 my ($dbh,$biblionumber,$frameworkcode) =@_;
889 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
890 $sth->execute($frameworkcode,$biblionumber);
896 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
900 modify a biblio (MARC=ON)
907 my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
908 $frameworkcode="" unless $frameworkcode;
909 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
910 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
912 $oldbiblio->{frameworkcode} = $frameworkcode;
913 #create the marc entry, that stores the rax marc record in Koha 3.0
914 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
915 $oldbiblio->{marc} = $record->as_usmarc();
916 $oldbiblio->{marcxml} = $record->as_xml();
917 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
918 REALmodbiblio($dbh,$oldbiblio);
919 REALmodbiblioitem($dbh,$oldbiblio);
920 # now, modify addi authors, subject, addititles.
921 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
922 my @addiauthfields = $record->field($tagfield);
923 foreach my $addiauthfield (@addiauthfields) {
924 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
925 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
926 foreach my $subfieldcount (0..$#addiauthsubfields) {
927 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
930 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
931 my @subtitlefields = $record->field($tagfield);
932 foreach my $subtitlefield (@subtitlefields) {
933 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
934 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
936 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
937 foreach my $subfieldcount (0..$#subtitlesubfields) {
938 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
939 REALnewsubtitle($dbh,$biblionumber,$subtit);
943 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
944 my @subj = $record->field($tagfield);
946 foreach my $subject (@subj) {
947 my @subjsubfield = $subject->subfield($tagsubfield);
948 foreach my $subfieldcount (0..$#subjsubfield) {
949 push @subjects,$subjsubfield[$subfieldcount];
952 REALmodsubject($dbh,$biblionumber,1,@subjects);
956 =head2 NEWmodbilbioframework
958 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
969 my ( $dbh, $bibid ) = @_;
970 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
971 &REALdelbiblio( $dbh, $biblio );
974 "select biblioitemnumber from biblioitems where biblionumber=?");
975 $sth->execute($biblio);
976 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
977 REALdelbiblioitem( $dbh, $biblioitemnumber );
979 &MARCdelbiblio( $dbh, $bibid, 0 );
984 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
988 creates an item from a MARC::Record
995 my ( $dbh,$record,$biblionumber,$biblioitemnumber ) = @_;
998 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
999 my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
1000 # needs old biblionumber and biblioitemnumber
1001 $item->{'biblionumber'} = $biblionumber;
1002 $item->{'biblioitemnumber'}=$biblioitemnumber;
1003 $item->{marc} = $record->as_usmarc();
1004 #warn $item->{marc};
1005 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
1012 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1023 my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1025 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1026 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1028 $olditem->{marc} = $record->as_usmarc();
1029 $olditem->{biblionumber} = $biblionumber;
1030 $olditem->{biblioitemnumber} = $biblioitemnumber;
1032 REALmoditem( $dbh, $olditem );
1038 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1049 my ( $dbh, $bibid, $itemnumber ) = @_;
1050 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1051 &REALdelitem( $dbh, $itemnumber );
1052 &MARCdelitem( $dbh, $bibid, $itemnumber );
1056 =head2 REALnewbiblio
1058 $biblionumber = REALnewbiblio($dbh,$biblio);
1062 adds a record in biblio table. Datas are in the hash $biblio.
1069 my ( $dbh, $biblio ) = @_;
1071 $dbh->do('lock tables biblio WRITE');
1072 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1074 my $data = $sth->fetchrow_arrayref;
1075 my $bibnum = $$data[0] + 1;
1078 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1081 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1082 serial=?, seriestitle=?, notes=?, abstract=?,
1086 $bibnum, $biblio->{'title'},
1087 $biblio->{'author'}, $biblio->{'copyrightdate'},
1088 $biblio->{'serial'}, $biblio->{'seriestitle'},
1089 $biblio->{'notes'}, $biblio->{'abstract'},
1090 $biblio->{'unititle'}
1094 $dbh->do('unlock tables');
1098 =head2 REALmodbiblio
1100 $biblionumber = REALmodbiblio($dbh,$biblio);
1104 modify a record in biblio table. Datas are in the hash $biblio.
1111 my ( $dbh, $biblio ) = @_;
1112 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1113 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1114 where biblionumber = ?"
1117 $biblio->{'title'}, $biblio->{'author'},
1118 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1119 $biblio->{'seriestitle'}, $biblio->{'serial'},
1120 $biblio->{'unititle'}, $biblio->{'notes'},
1121 $biblio->{frameworkcode},
1122 $biblio->{'biblionumber'}
1125 return ( $biblio->{'biblionumber'} );
1128 =head2 REALmodsubtitle
1130 REALmodsubtitle($dbh,$bibnum,$subtitle);
1134 modify subtitles in bibliosubtitle table.
1140 sub REALmodsubtitle {
1141 my ( $dbh, $bibnum, $subtitle ) = @_;
1144 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1145 $sth->execute( $subtitle, $bibnum );
1149 =head2 REALmodaddauthor
1151 REALmodaddauthor($dbh,$bibnum,$author);
1155 adds or modify additional authors
1156 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1162 sub REALmodaddauthor {
1163 my ( $dbh, $bibnum, @authors ) = @_;
1165 # my $dbh = C4Connect;
1167 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1169 $sth->execute($bibnum);
1171 foreach my $author (@authors) {
1172 if ( $author ne '' ) {
1175 "Insert into additionalauthors set author = ?, biblionumber = ?"
1178 $sth->execute( $author, $bibnum );
1183 } # sub modaddauthor
1185 =head2 REALmodsubject
1187 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1191 modify/adds subjects
1196 sub REALmodsubject {
1197 my ( $dbh, $bibnum, $force, @subject ) = @_;
1199 # my $dbh = C4Connect;
1200 my $count = @subject;
1202 for ( my $i = 0 ; $i < $count ; $i++ ) {
1203 $subject[$i] =~ s/^ //g;
1204 $subject[$i] =~ s/ $//g;
1207 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1209 $sth->execute( $subject[$i] );
1211 if ( my $data = $sth->fetchrow_hashref ) {
1214 if ( $force eq $subject[$i] || $force == 1 ) {
1216 # subject not in aut, chosen to force anway
1217 # so insert into cataloguentry so its in auth file
1220 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1223 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1228 "$subject[$i]\n does not exist in the subject authority file";
1231 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1233 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1235 while ( my $data = $sth2->fetchrow_hashref ) {
1236 $error .= "<br>$data->{'catalogueentry'}";
1245 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1246 $sth->execute($bibnum);
1250 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1252 foreach $query (@subject) {
1253 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1262 =head2 REALmodbiblioitem
1264 REALmodbiblioitem($dbh, $biblioitem);
1273 sub REALmodbiblioitem {
1274 my ( $dbh, $biblioitem ) = @_;
1277 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1278 itemtype=?, url=?, isbn=?, issn=?,
1279 publishercode=?, publicationyear=?, classification=?, dewey=?,
1280 subclass=?, illus=?, pages=?, volumeddesc=?,
1281 notes=?, size=?, place=?, marc=?,
1283 where biblioitemnumber=?");
1284 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1285 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1286 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1287 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1288 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1289 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1291 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1293 z3950_extended_services('update',set_service_options('update'),$record);
1296 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1299 =head2 REALnewbiblioitem
1301 REALnewbiblioitem($dbh,$biblioitem);
1305 adds a biblioitem ($biblioitem is a hash with the values)
1311 sub REALnewbiblioitem {
1312 my ( $dbh, $biblioitem ) = @_;
1314 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1315 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1317 my $biblioitemnumber;
1320 $data = $sth->fetchrow_arrayref;
1321 $biblioitemnumber = $$data[0] + 1;
1323 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1324 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1325 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1326 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1327 my $field=$record->field($biblioitemnumberfield);
1328 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1329 $biblioitem->{marc} = $record->as_usmarc();
1330 $biblioitem->{marcxml} = $record->as_xml();
1332 $sth = $dbh->prepare( "insert into biblioitems set
1333 biblioitemnumber = ?, biblionumber = ?,
1334 volume = ?, number = ?,
1335 classification = ?, itemtype = ?,
1337 issn = ?, dewey = ?,
1338 subclass = ?, publicationyear = ?,
1339 publishercode = ?, volumedate = ?,
1340 volumeddesc = ?, illus = ?,
1341 pages = ?, notes = ?,
1343 marc = ?, place = ?,
1347 $biblioitemnumber, $biblioitem->{'biblionumber'},
1348 $biblioitem->{'volume'}, $biblioitem->{'number'},
1349 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1350 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1351 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1352 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1353 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1354 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1355 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1356 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1357 $biblioitem->{'marc'}, $biblioitem->{'place'},
1358 $biblioitem->{marcxml},
1360 $dbh->do("unlock tables");
1361 z3950_extended_services('update',set_service_options('update'),$record);
1362 return ($biblioitemnumber);
1365 =head2 REALnewsubtitle
1367 REALnewsubtitle($dbh,$bibnum,$subtitle);
1371 create a new subtitle
1376 sub REALnewsubtitle {
1377 my ( $dbh, $bibnum, $subtitle ) = @_;
1380 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1381 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1387 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1391 create a item. $item is a hash and $barcode the barcode.
1398 my ( $dbh, $item, $barcode ) = @_;
1400 # warn "OLDNEWITEMS";
1402 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1403 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1408 $data = $sth->fetchrow_hashref;
1409 $itemnumber = $data->{'max(itemnumber)'} + 1;
1411 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1412 if ( $item->{'loan'} ) {
1413 $item->{'notforloan'} = $item->{'loan'};
1415 $item->{'biblioitemnumber'} = 1;
1416 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1417 if ( $item->{'dateaccessioned'} ) {
1418 $sth = $dbh->prepare( "Insert into items set
1419 itemnumber = ?, biblionumber = ?,
1420 multivolumepart = ?,
1421 biblioitemnumber = ?, barcode = ?,
1422 booksellerid = ?, dateaccessioned = ?,
1423 homebranch = ?, holdingbranch = ?,
1424 price = ?, replacementprice = ?,
1425 replacementpricedate = NOW(), datelastseen = NOW(),
1426 multivolume = ?, stack = ?,
1427 itemlost = ?, wthdrawn = ?,
1428 paidfor = ?, itemnotes = ?,
1429 itemcallnumber =?, notforloan = ?,
1434 $itemnumber, $item->{'biblionumber'},
1435 $item->{'multivolumepart'},
1436 $item->{'biblioitemnumber'},$item->{barcode},
1437 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1438 $item->{'homebranch'}, $item->{'holdingbranch'},
1439 $item->{'price'}, $item->{'replacementprice'},
1440 $item->{multivolume}, $item->{stack},
1441 $item->{itemlost}, $item->{wthdrawn},
1442 $item->{paidfor}, $item->{'itemnotes'},
1443 $item->{'itemcallnumber'}, $item->{'notforloan'},
1446 if ( defined $sth->errstr ) {
1447 $error .= $sth->errstr;
1451 $sth = $dbh->prepare( "Insert into items set
1452 itemnumber = ?, biblionumber = ?,
1453 multivolumepart = ?,
1454 biblioitemnumber = ?, barcode = ?,
1455 booksellerid = ?, dateaccessioned = NOW(),
1456 homebranch = ?, holdingbranch = ?,
1457 price = ?, replacementprice = ?,
1458 replacementpricedate = NOW(), datelastseen = NOW(),
1459 multivolume = ?, stack = ?,
1460 itemlost = ?, wthdrawn = ?,
1461 paidfor = ?, itemnotes = ?,
1462 itemcallnumber =?, notforloan = ?,
1467 $itemnumber, $item->{'biblionumber'},
1468 $item->{'multivolumepart'},
1469 $item->{'biblioitemnumber'},$item->{barcode},
1470 $item->{'booksellerid'},
1471 $item->{'homebranch'}, $item->{'holdingbranch'},
1472 $item->{'price'}, $item->{'replacementprice'},
1473 $item->{multivolume}, $item->{stack},
1474 $item->{itemlost}, $item->{wthdrawn},
1475 $item->{paidfor}, $item->{'itemnotes'},
1476 $item->{'itemcallnumber'}, $item->{'notforloan'},
1479 if ( defined $sth->errstr ) {
1480 $error .= $sth->errstr;
1483 # item stored, now, deal with the marc part...
1484 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1485 where biblio.biblionumber=biblioitems.biblionumber and
1486 biblio.biblionumber=?");
1487 $sth->execute($item->{biblionumber});
1488 if ( defined $sth->errstr ) {
1489 $error .= $sth->errstr;
1491 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1492 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1493 my $record = MARC::File::USMARC::decode($rawmarc);
1494 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1495 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1496 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1498 #warn $itemnumberfield;
1499 #warn $itemrecord->field($itemnumberfield);
1500 my $itemfield = $itemrecord->field($itemnumberfield);
1501 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1502 $record->insert_grouped_field($itemfield);
1503 # save the record into biblioitem
1504 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1505 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1506 if ( defined $sth->errstr ) {
1507 $error .= $sth->errstr;
1509 z3950_extended_services('update',set_service_options('update'),$record);
1510 $dbh->do('unlock tables');
1511 return ( $itemnumber, $error );
1514 =head2 REALmoditem($dbh,$item);
1525 my ( $dbh, $item ) = @_;
1526 $item->{'bibitemnum'} = 1;
1528 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1529 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1530 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1532 $item->{'barcode'}, $item->{'itemnotes'},
1533 $item->{'itemcallnumber'}, $item->{'notforloan'},
1534 $item->{'location'}, $item->{multivolumepart},
1535 $item->{multivolume}, $item->{stack},
1538 if ( $item->{'lost'} ne '' ) {
1539 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1540 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1541 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1543 $item->{'bibitemnum'}, $item->{'barcode'},
1544 $item->{'itemnotes'}, $item->{'homebranch'},
1545 $item->{'lost'}, $item->{'wthdrawn'},
1546 $item->{'itemcallnumber'}, $item->{'notforloan'},
1547 $item->{'location'}, $item->{multivolumepart},
1548 $item->{multivolume}, $item->{stack},
1551 if ($item->{homebranch}) {
1552 $query.=",homebranch=?";
1553 push @bind, $item->{homebranch};
1555 if ($item->{holdingbranch}) {
1556 $query.=",holdingbranch=?";
1557 push @bind, $item->{holdingbranch};
1560 $query.=" where itemnumber=?";
1561 push @bind,$item->{'itemnum'};
1562 if ( $item->{'replacement'} ne '' ) {
1563 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1565 my $sth = $dbh->prepare($query);
1566 $sth->execute(@bind);
1568 # item stored, now, deal with the marc part...
1569 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1570 where biblio.biblionumber=biblioitems.biblionumber and
1571 biblio.biblionumber=? and
1572 biblioitems.biblioitemnumber=?");
1573 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1574 if ( defined $sth->errstr ) {
1575 $error .= $sth->errstr;
1577 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1578 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1579 my $record = MARC::File::USMARC::decode($rawmarc);
1580 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1581 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1582 # prepare the new item record
1583 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1584 my $itemfield = $itemrecord->field($itemnumberfield);
1585 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1586 # parse all fields fields from the complete record
1587 foreach ($record->field($itemnumberfield)) {
1588 # when the previous field is found, replace by the new one
1589 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1590 $_->replace_with($itemfield);
1593 # $record->insert_grouped_field($itemfield);
1594 # save the record into biblioitem
1595 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1596 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1597 z3950_extended_services('update',set_service_options('update'),$record);
1598 if ( defined $sth->errstr ) {
1599 $error .= $sth->errstr;
1601 $dbh->do('unlock tables');
1605 =head2 REALdelitem($dbh,$itemnum);
1616 my ( $dbh, $itemnum ) = @_;
1618 # my $dbh=C4Connect;
1619 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1620 $sth->execute($itemnum);
1621 my $data = $sth->fetchrow_hashref;
1623 my $query = "Insert into deleteditems set ";
1625 foreach my $temp ( keys %$data ) {
1626 $query .= "$temp = ?,";
1627 push ( @bind, $data->{$temp} );
1632 $sth = $dbh->prepare($query);
1633 $sth->execute(@bind);
1635 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1636 $sth->execute($itemnum);
1642 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1646 deletes a biblioitem
1647 NOTE : not standard sub name. Should be REALdelbiblioitem()
1653 sub REALdelbiblioitem {
1654 my ( $dbh, $biblioitemnumber ) = @_;
1656 # my $dbh = C4Connect;
1657 my $sth = $dbh->prepare( "Select * from biblioitems
1658 where biblioitemnumber = ?"
1662 $sth->execute($biblioitemnumber);
1664 if ( $results = $sth->fetchrow_hashref ) {
1668 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1669 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1670 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1674 $results->{biblioitemnumber}, $results->{biblionumber},
1675 $results->{volume}, $results->{number},
1676 $results->{classification}, $results->{itemtype},
1677 $results->{isbn}, $results->{issn},
1678 $results->{dewey}, $results->{subclass},
1679 $results->{publicationyear}, $results->{publishercode},
1680 $results->{volumedate}, $results->{volumeddesc},
1681 $results->{timestamp}, $results->{illus},
1682 $results->{pages}, $results->{notes},
1683 $results->{size}, $results->{url},
1687 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1688 $sth2->execute($biblioitemnumber);
1693 # Now delete all the items attached to the biblioitem
1694 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1695 $sth->execute($biblioitemnumber);
1697 while ( my $data = $sth->fetchrow_hashref ) {
1698 my $query = "Insert into deleteditems set ";
1700 foreach my $temp ( keys %$data ) {
1701 $query .= "$temp = ?,";
1702 push ( @bind, $data->{$temp} );
1705 my $sth2 = $dbh->prepare($query);
1706 $sth2->execute(@bind);
1709 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1710 $sth->execute($biblioitemnumber);
1714 } # sub deletebiblioitem
1716 =head2 REALdelbiblio($dbh,$biblio);
1727 my ( $dbh, $biblio ) = @_;
1728 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1729 $sth->execute($biblio);
1730 if ( my $data = $sth->fetchrow_hashref ) {
1732 my $query = "Insert into deletedbiblio set ";
1734 foreach my $temp ( keys %$data ) {
1735 $query .= "$temp = ?,";
1736 push ( @bind, $data->{$temp} );
1739 #replacing the last , by ",?)"
1741 $sth = $dbh->prepare($query);
1742 $sth->execute(@bind);
1744 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1745 $sth->execute($biblio);
1753 $number = itemcount($biblio);
1757 returns the number of items attached to a biblio
1765 my $dbh = C4::Context->dbh;
1768 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1769 $sth->execute($biblio);
1770 my $data = $sth->fetchrow_hashref;
1772 return ( $data->{'count(*)'} );
1777 $biblionumber = newbiblio($biblio);
1781 create a biblio. The parameter is a hash
1789 my $dbh = C4::Context->dbh;
1790 my $bibnum = REALnewbiblio( $dbh, $biblio );
1791 # finds new (MARC bibid
1792 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1793 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1794 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1800 $biblionumber = &modbiblio($biblio);
1804 Update a biblio record.
1806 C<$biblio> is a reference-to-hash whose keys are the fields in the
1807 biblio table in the Koha database. All fields must be present, not
1808 just the ones you wish to change.
1810 C<&modbiblio> updates the record defined by
1811 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1813 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1822 my $dbh = C4::Context->dbh;
1823 my $biblionumber=REALmodbiblio($dbh,$biblio);
1824 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1825 # finds new (MARC bibid
1826 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1827 MARCmodbiblio($dbh,$bibid,$record,"",0);
1828 return($biblionumber);
1831 =head2 &modsubtitle($biblionumber, $subtitle);
1835 Sets the subtitle of a book.
1837 C<$biblionumber> is the biblionumber of the book to modify.
1839 C<$subtitle> is the new subtitle.
1846 my ( $bibnum, $subtitle ) = @_;
1847 my $dbh = C4::Context->dbh;
1848 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1851 =head2 &modaddauthor($biblionumber, $author);
1855 Replaces all additional authors for the book with biblio number
1856 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1857 C<&modaddauthor> deletes all additional authors.
1864 my ( $bibnum, @authors ) = @_;
1865 my $dbh = C4::Context->dbh;
1866 &REALmodaddauthor( $dbh, $bibnum, @authors );
1867 } # sub modaddauthor
1871 $error = &modsubject($biblionumber, $force, @subjects);
1875 $force - a subject to force
1876 $error - Error message, or undef if successful.
1883 my ( $bibnum, $force, @subject ) = @_;
1884 my $dbh = C4::Context->dbh;
1885 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1887 # When MARC is off, ensures that the MARC biblio table gets updated with new
1888 # subjects, of course, it deletes the biblio in marc, and then recreates.
1889 # This check is to ensure that no MARC data exists to lose.
1890 # if (C4::Context->preference("MARC") eq '0'){
1891 # warn "in modSUBJECT";
1892 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1893 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1894 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1900 =head2 modbibitem($dbh, $biblioitem);
1904 modify a biblioitem. The parameter is a hash
1911 my ($dbh, $biblioitem) = @_;
1912 #my $dbh = C4::Context->dbh;
1913 &REALmodbiblioitem( $dbh, $biblioitem );
1916 =head2 newbiblioitem
1918 $biblioitemnumber = newbiblioitem($biblioitem)
1922 create a biblioitem, the parameter is a hash
1929 my ($dbh, $biblioitem) = @_;
1930 #my $dbh = C4::Context->dbh;
1931 # add biblio information to the hash
1932 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1933 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1934 my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1935 return ($bibitemnum);
1938 =head2 newsubtitle($biblionumber,$subtitle);
1942 insert a subtitle for $biblionumber biblio
1950 my ( $bibnum, $subtitle ) = @_;
1951 my $dbh = C4::Context->dbh;
1952 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1957 $errors = newitems($dbh, $item, @barcodes);
1961 insert items ($item is a hash)
1969 my ( $dbh, $item, @barcodes ) = @_;
1970 #my $dbh = C4::Context->dbh;
1974 foreach my $barcode (@barcodes) {
1975 # add items, one by one for each barcode.
1977 $oneitem->{barcode}= $barcode;
1978 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1979 $oneitem->{marc} = $MARCitem->as_usmarc;
1980 ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
1981 # $errors .= $error;
1982 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1987 =head2 moditem($dbh,$item);
1991 modify an item ($item is a hash with all item informations)
1999 my ($dbh, $item) = @_;
2000 #my $dbh = C4::Context->dbh;
2001 &REALmoditem( $dbh, $item );
2003 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
2005 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
2006 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
2011 $error = checkitems($count,@barcodes);
2015 check for each @barcode entry that the barcode is not a duplicate
2022 my ( $count, @barcodes ) = @_;
2023 my $dbh = C4::Context->dbh;
2025 my $sth = $dbh->prepare("Select * from items where barcode=?");
2026 for ( my $i = 0 ; $i < $count ; $i++ ) {
2027 $barcodes[$i] = uc $barcodes[$i];
2028 $sth->execute( $barcodes[$i] );
2029 if ( my $data = $sth->fetchrow_hashref ) {
2030 $error .= " Duplicate Barcode: $barcodes[$i]";
2037 =head2 delitem($itemnum);
2041 delete item $itemnum being the item number to delete
2049 my $dbh = C4::Context->dbh;
2050 &REALdelitem( $dbh, $itemnum );
2053 =head2 deletebiblioitem($biblioitemnumber);
2057 delete the biblioitem $biblioitemnumber
2063 sub deletebiblioitem {
2064 my ($biblioitemnumber) = @_;
2065 my $dbh = C4::Context->dbh;
2066 &REALdelbiblioitem( $dbh, $biblioitemnumber );
2067 } # sub deletebiblioitem
2069 =head2 delbiblio($biblionumber)
2073 delete biblio $biblionumber
2081 my $dbh = C4::Context->dbh;
2082 &REALdelbiblio( $dbh, $biblio );
2083 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2084 &MARCdelbiblio( $dbh, $bibid, 0 );
2089 ($count,@results) = getbiblio($biblionumber);
2093 return an array with hash of biblios.
2095 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2102 my ($biblionumber) = @_;
2103 my $dbh = C4::Context->dbh;
2104 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2106 # || die "Cannot prepare $query\n" . $dbh->errstr;
2110 $sth->execute($biblionumber);
2112 # || die "Cannot execute $query\n" . $sth->errstr;
2113 while ( my $data = $sth->fetchrow_hashref ) {
2114 $results[$count] = $data;
2119 return ( $count, @results );
2124 $data = &bibdata($biblionumber, $type);
2126 Returns information about the book with the given biblionumber.
2128 C<$type> is ignored.
2130 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2131 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2134 In addition, C<$data-E<gt>{subject}> is the list of the book's
2135 subjects, separated by C<" , "> (space, comma, space).
2137 If there are multiple biblioitems with the given biblionumber, only
2138 the first one is considered.
2143 my ($bibnum, $type) = @_;
2144 my $dbh = C4::Context->dbh;
2145 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2147 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2148 left join bibliosubtitle on
2149 biblio.biblionumber = bibliosubtitle.biblionumber
2150 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2151 where biblio.biblionumber = ?
2153 $sth->execute($bibnum);
2155 $data = $sth->fetchrow_hashref;
2157 # handle management of repeated subtitle
2158 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2159 $sth->execute($bibnum);
2161 while (my $dat = $sth->fetchrow_hashref){
2163 $line{subtitle} = $dat->{subtitle};
2164 push @subtitles, \%line;
2166 $data->{subtitles} = \@subtitles;
2168 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2169 $sth->execute($bibnum);
2171 while (my $dat = $sth->fetchrow_hashref){
2173 $line{subject} = $dat->{'subject'};
2174 push @subjects, \%line;
2176 $data->{subjects} = \@subjects;
2178 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2179 $sth->execute($bibnum);
2180 while (my $dat = $sth->fetchrow_hashref){
2181 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2183 chop $data->{'additionalauthors'};
2184 chop $data->{'additionalauthors'};
2185 chop $data->{'additionalauthors'};
2190 =head2 getbiblioitem
2192 ($count,@results) = getbiblioitem($biblioitemnumber);
2196 return an array with hash of biblioitemss.
2198 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2205 my ($biblioitemnum) = @_;
2206 my $dbh = C4::Context->dbh;
2207 my $sth = $dbh->prepare( "Select * from biblioitems where
2208 biblioitemnumber = ?"
2213 $sth->execute($biblioitemnum);
2215 while ( my $data = $sth->fetchrow_hashref ) {
2216 $results[$count] = $data;
2221 return ( $count, @results );
2222 } # sub getbiblioitem
2224 =head2 getbiblioitembybiblionumber
2226 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2230 return an array with hash of biblioitems for the given biblionumber.
2236 sub getbiblioitembybiblionumber {
2237 my ($biblionumber) = @_;
2238 my $dbh = C4::Context->dbh;
2239 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2243 $sth->execute($biblionumber);
2245 while ( my $data = $sth->fetchrow_hashref ) {
2246 $results[$count] = $data;
2251 return ( $count, @results );
2254 =head2 getitemsbybiblioitem
2256 ($count,@results) = getitemsbybiblioitem($biblionumber);
2260 returns an array with hash of items
2266 sub getitemsbybiblioitem {
2267 my ($biblioitemnum) = @_;
2268 my $dbh = C4::Context->dbh;
2269 my $sth = $dbh->prepare( "Select * from items, biblio where
2270 biblio.biblionumber = items.biblionumber and biblioitemnumber
2274 # || die "Cannot prepare $query\n" . $dbh->errstr;
2278 $sth->execute($biblioitemnum);
2280 # || die "Cannot execute $query\n" . $sth->errstr;
2281 while ( my $data = $sth->fetchrow_hashref ) {
2282 $results[$count] = $data;
2287 return ( $count, @results );
2288 } # sub getitemsbybiblioitem
2292 @results = &ItemInfo($env, $biblionumber, $type);
2294 Returns information about books with the given biblionumber.
2296 C<$type> may be either C<intra> or anything else. If it is not set to
2297 C<intra>, then the search will exclude lost, very overdue, and
2302 C<&ItemInfo> returns a list of references-to-hash. Each element
2303 contains a number of keys. Most of them are table items from the
2304 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2305 Koha database. Other keys include:
2309 =item C<$data-E<gt>{branchname}>
2311 The name (not the code) of the branch to which the book belongs.
2313 =item C<$data-E<gt>{datelastseen}>
2315 This is simply C<items.datelastseen>, except that while the date is
2316 stored in YYYY-MM-DD format in the database, here it is converted to
2317 DD/MM/YYYY format. A NULL date is returned as C<//>.
2319 =item C<$data-E<gt>{datedue}>
2321 =item C<$data-E<gt>{class}>
2323 This is the concatenation of C<biblioitems.classification>, the book's
2324 Dewey code, and C<biblioitems.subclass>.
2326 =item C<$data-E<gt>{ocount}>
2328 I think this is the number of copies of the book available.
2330 =item C<$data-E<gt>{order}>
2332 If this is set, it is set to C<One Order>.
2339 my ($env,$biblionumber,$type) = @_;
2340 my $dbh = C4::Context->dbh;
2341 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2342 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2343 WHERE items.biblionumber = ?
2344 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2345 AND biblio.biblionumber = items.biblionumber";
2346 $query .= " order by items.dateaccessioned desc";
2347 my $sth=$dbh->prepare($query);
2348 $sth->execute($biblionumber);
2351 while (my $data=$sth->fetchrow_hashref){
2353 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2354 $isth->execute($data->{'itemnumber'});
2355 if (my $idata=$isth->fetchrow_hashref){
2356 $data->{borrowernumber} = $idata->{borrowernumber};
2357 $data->{cardnumber} = $idata->{cardnumber};
2358 $datedue = format_date($idata->{'date_due'});
2360 if ($datedue eq ''){
2361 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2367 #get branch information.....
2368 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2369 $bsth->execute($data->{'holdingbranch'});
2370 if (my $bdata=$bsth->fetchrow_hashref){
2371 $data->{'branchname'} = $bdata->{'branchname'};
2373 my $date=format_date($data->{'datelastseen'});
2374 $data->{'datelastseen'}=$date;
2375 $data->{'datedue'}=$datedue;
2376 # get notforloan complete status if applicable
2377 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2378 $sthnflstatus->execute;
2379 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2380 if ($authorised_valuecode) {
2381 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2382 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2383 my ($lib) = $sthnflstatus->fetchrow;
2384 $data->{notforloan} = $lib;
2395 ($count, @results) = &bibitems($biblionumber);
2397 Given the biblionumber for a book, C<&bibitems> looks up that book's
2398 biblioitems (different publications of the same book, the audio book
2399 and film versions, etc.).
2401 C<$count> is the number of elements in C<@results>.
2403 C<@results> is an array of references-to-hash; the keys are the fields
2404 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2405 addition, C<itemlost> indicates the availability of the item: if it is
2406 "2", then all copies of the item are long overdue; if it is "1", then
2407 all copies are lost; otherwise, there is at least one copy available.
2413 my $dbh = C4::Context->dbh;
2414 my $sth = $dbh->prepare("SELECT biblioitems.*,
2416 MIN(items.itemlost) as itemlost,
2417 MIN(items.dateaccessioned) as dateaccessioned
2418 FROM biblioitems, itemtypes, items
2419 WHERE biblioitems.biblionumber = ?
2420 AND biblioitems.itemtype = itemtypes.itemtype
2421 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2422 GROUP BY items.biblioitemnumber");
2425 $sth->execute($bibnum);
2426 while (my $data = $sth->fetchrow_hashref) {
2427 $results[$count] = $data;
2431 return($count, @results);
2437 $itemdata = &bibitemdata($biblioitemnumber);
2439 Looks up the biblioitem with the given biblioitemnumber. Returns a
2440 reference-to-hash. The keys are the fields from the C<biblio>,
2441 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2442 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2448 my $dbh = C4::Context->dbh;
2449 my $sth = $dbh->prepare("Select *,biblioitems.notes as bnotes from biblio, biblioitems,itemtypes where biblio.biblionumber = biblioitems.biblionumber and biblioitemnumber = ? and biblioitems.itemtype = itemtypes.itemtype");
2452 $sth->execute($bibitem);
2454 $data = $sth->fetchrow_hashref;
2461 =head2 getbibliofromitemnumber
2463 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2465 Looks up the item with the given itemnumber.
2467 C<$env> and C<$dbh> are ignored.
2469 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2470 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2475 sub getbibliofromitemnumber {
2476 my ($env,$dbh,$itemnumber) = @_;
2477 $dbh = C4::Context->dbh;
2478 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2479 where items.itemnumber = ?
2480 and biblio.biblionumber = items.biblionumber
2481 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2483 $sth->execute($itemnumber);
2484 my $data=$sth->fetchrow_hashref;
2491 @barcodes = &barcodes($biblioitemnumber);
2493 Given a biblioitemnumber, looks up the corresponding items.
2495 Returns an array of references-to-hash; the keys are C<barcode> and
2498 The returned items include very overdue items, but not lost ones.
2503 #called from request.pl
2504 my ($biblioitemnumber)=@_;
2505 my $dbh = C4::Context->dbh;
2506 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2507 WHERE biblioitemnumber = ?
2508 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2509 $sth->execute($biblioitemnumber);
2512 while (my $data=$sth->fetchrow_hashref){
2513 $barcodes[$i]=$data;
2523 $item = &itemdata($barcode);
2525 Looks up the item with the given barcode, and returns a
2526 reference-to-hash containing information about that item. The keys of
2527 the hash are the fields from the C<items> and C<biblioitems> tables in
2532 sub get_item_from_barcode {
2534 my $dbh = C4::Context->dbh;
2535 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2536 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2537 $sth->execute($barcode);
2538 my $data=$sth->fetchrow_hashref;
2546 @issues = &itemissues($biblioitemnumber, $biblio);
2548 Looks up information about who has borrowed the bookZ<>(s) with the
2549 given biblioitemnumber.
2551 C<$biblio> is ignored.
2553 C<&itemissues> returns an array of references-to-hash. The keys
2554 include the fields from the C<items> table in the Koha database.
2555 Additional keys include:
2561 If the item is currently on loan, this gives the due date.
2563 If the item is not on loan, then this is either "Available" or
2564 "Cancelled", if the item has been withdrawn.
2568 If the item is currently on loan, this gives the card number of the
2569 patron who currently has the item.
2571 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2573 These give the timestamp for the last three times the item was
2576 =item C<card0>, C<card1>, C<card2>
2578 The card number of the last three patrons who borrowed this item.
2580 =item C<borrower0>, C<borrower1>, C<borrower2>
2582 The borrower number of the last three patrons who borrowed this item.
2589 my ($bibitem, $biblio)=@_;
2590 my $dbh = C4::Context->dbh;
2591 # FIXME - If this function die()s, the script will abort, and the
2592 # user won't get anything; depending on how far the script has
2593 # gotten, the user might get a blank page. It would be much better
2594 # to at least print an error message. The easiest way to do this
2595 # is to set $SIG{__DIE__}.
2596 my $sth = $dbh->prepare("Select * from items where
2597 items.biblioitemnumber = ?")
2598 || die $dbh->errstr;
2602 $sth->execute($bibitem)
2603 || die $sth->errstr;
2605 while (my $data = $sth->fetchrow_hashref) {
2606 # Find out who currently has this item.
2607 # FIXME - Wouldn't it be better to do this as a left join of
2608 # some sort? Currently, this code assumes that if
2609 # fetchrow_hashref() fails, then the book is on the shelf.
2610 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2611 # database server crash), not just because no items match the
2613 my $sth2 = $dbh->prepare("select * from issues,borrowers
2614 where itemnumber = ?
2615 and returndate is NULL
2616 and issues.borrowernumber = borrowers.borrowernumber");
2618 $sth2->execute($data->{'itemnumber'});
2619 if (my $data2 = $sth2->fetchrow_hashref) {
2620 $data->{'date_due'} = $data2->{'date_due'};
2621 $data->{'card'} = $data2->{'cardnumber'};
2622 $data->{'borrower'} = $data2->{'borrowernumber'};
2624 if ($data->{'wthdrawn'} eq '1') {
2625 $data->{'date_due'} = 'Cancelled';
2627 $data->{'date_due'} = 'Available';
2633 # Find the last 3 people who borrowed this item.
2634 $sth2 = $dbh->prepare("select * from issues, borrowers
2635 where itemnumber = ?
2636 and issues.borrowernumber = borrowers.borrowernumber
2637 and returndate is not NULL
2638 order by returndate desc,timestamp desc") || die $dbh->errstr;
2639 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2640 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2641 if (my $data2 = $sth2->fetchrow_hashref) {
2642 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2643 $data->{"card$i2"} = $data2->{'cardnumber'};
2644 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2649 $results[$i] = $data;
2659 ($count, $subjects) = &getsubject($biblionumber);
2661 Looks up the subjects of the book with the given biblionumber. Returns
2662 a two-element list. C<$subjects> is a reference-to-array, where each
2663 element is a subject of the book, and C<$count> is the number of
2664 elements in C<$subjects>.
2670 my $dbh = C4::Context->dbh;
2671 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2672 $sth->execute($bibnum);
2675 while (my $data=$sth->fetchrow_hashref){
2680 return($i,\@results);
2685 ($count, $authors) = &getaddauthor($biblionumber);
2687 Looks up the additional authors for the book with the given
2690 Returns a two-element list. C<$authors> is a reference-to-array, where
2691 each element is an additional author, and C<$count> is the number of
2692 elements in C<$authors>.
2698 my $dbh = C4::Context->dbh;
2699 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2700 $sth->execute($bibnum);
2703 while (my $data=$sth->fetchrow_hashref){
2708 return($i,\@results);
2714 ($count, $subtitles) = &getsubtitle($biblionumber);
2716 Looks up the subtitles for the book with the given biblionumber.
2718 Returns a two-element list. C<$subtitles> is a reference-to-array,
2719 where each element is a subtitle, and C<$count> is the number of
2720 elements in C<$subtitles>.
2726 my $dbh = C4::Context->dbh;
2727 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2728 $sth->execute($bibnum);
2731 while (my $data=$sth->fetchrow_hashref){
2736 return($i,\@results);
2742 ($count, @websites) = &getwebsites($biblionumber);
2744 Looks up the web sites pertaining to the book with the given
2747 C<$count> is the number of elements in C<@websites>.
2749 C<@websites> is an array of references-to-hash; the keys are the
2750 fields from the C<websites> table in the Koha database.
2753 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2754 #(with add / modify / delete subs)
2757 my ($biblionumber) = @_;
2758 my $dbh = C4::Context->dbh;
2759 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2763 $sth->execute($biblionumber);
2764 while (my $data = $sth->fetchrow_hashref) {
2765 # FIXME - The URL scheme shouldn't be stripped off, at least
2766 # not here, since it's part of the URL, and will be useful in
2767 # constructing a link to the site. If you don't want the user
2768 # to see the "http://" part, strip that off when building the
2770 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2772 $results[$count] = $data;
2777 return($count, @results);
2780 =head2 getwebbiblioitems
2782 ($count, @results) = &getwebbiblioitems($biblionumber);
2784 Given a book's biblionumber, looks up the web versions of the book
2785 (biblioitems with itemtype C<WEB>).
2787 C<$count> is the number of items in C<@results>. C<@results> is an
2788 array of references-to-hash; the keys are the items from the
2789 C<biblioitems> table of the Koha database.
2793 sub getwebbiblioitems {
2794 my ($biblionumber) = @_;
2795 my $dbh = C4::Context->dbh;
2796 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2797 and itemtype = 'WEB'");
2801 $sth->execute($biblionumber);
2802 while (my $data = $sth->fetchrow_hashref) {
2803 $data->{'url'} =~ s/^http:\/\///;
2804 $results[$count] = $data;
2809 return($count, @results);
2810 } # sub getwebbiblioitems
2813 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2814 my $NSE = '\x89'; # NSE : Non Sorting Block end
2815 # handles non sorting blocks
2819 s/[ ]{0,1}$NSE/) /gm;
2826 my $dbh = C4::Context->dbh;
2827 my $result = MARCmarc2koha($dbh,$record,'');
2829 my ($biblionumber,$bibid,$title);
2830 # search duplicate on ISBN, easy and fast...
2831 if ($result->{isbn}) {
2832 $sth = $dbh->prepare("select biblio.biblionumber,bibid,title from biblio,biblioitems,marc_biblio where biblio.biblionumber=biblioitems.biblionumber and marc_biblio.biblionumber=biblioitems.biblionumber and isbn=?");
2833 $sth->execute($result->{'isbn'});
2834 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2835 return $biblionumber,$bibid,$title if ($biblionumber);
2837 # a more complex search : build a request for SearchMarc::catalogsearch()
2838 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2839 # search on biblio.title
2840 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2841 if ($record->field($tag)) {
2842 if ($record->field($tag)->subfields($subfield)) {
2843 push @tags, "'".$tag.$subfield."'";
2844 push @and_or, "and";
2845 push @excluding, "";
2846 push @operator, "contains";
2847 push @value, $record->field($tag)->subfield($subfield);
2848 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2851 # ... and on biblio.author
2852 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2853 if ($record->field($tag)) {
2854 if ($record->field($tag)->subfields($subfield)) {
2855 push @tags, "'".$tag.$subfield."'";
2856 push @and_or, "and";
2857 push @excluding, "";
2858 push @operator, "contains";
2859 push @value, $record->field($tag)->subfield($subfield);
2860 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2863 # ... and on publicationyear.
2864 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2865 if ($record->field($tag)) {
2866 if ($record->field($tag)->subfields($subfield)) {
2867 push @tags, "'".$tag.$subfield."'";
2868 push @and_or, "and";
2869 push @excluding, "";
2870 push @operator, "=";
2871 push @value, $record->field($tag)->subfield($subfield);
2872 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2876 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2877 if ($record->field($tag)) {
2878 if ($record->field($tag)->subfields($subfield)) {
2879 push @tags, "'".$tag.$subfield."'";
2880 push @and_or, "and";
2881 push @excluding, "";
2882 push @operator, "=";
2883 push @value, $record->field($tag)->subfield($subfield);
2884 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2887 # ... and on publisher.
2888 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2889 if ($record->field($tag)) {
2890 if ($record->field($tag)->subfields($subfield)) {
2891 push @tags, "'".$tag.$subfield."'";
2892 push @and_or, "and";
2893 push @excluding, "";
2894 push @operator, "=";
2895 push @value, $record->field($tag)->subfield($subfield);
2896 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2899 # ... and on volume.
2900 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2901 if ($record->field($tag)) {
2902 if ($record->field($tag)->subfields($subfield)) {
2903 push @tags, "'".$tag.$subfield."'";
2904 push @and_or, "and";
2905 push @excluding, "";
2906 push @operator, "=";
2907 push @value, $record->field($tag)->subfield($subfield);
2908 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2912 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2913 # there is at least 1 result => return the 1st one
2915 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2916 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2918 # no result, returns nothing
2925 if(substr($isbn, 0, 1) <=7) {
2926 $seg1 = substr($isbn, 0, 1);
2927 } elsif(substr($isbn, 0, 2) <= 94) {
2928 $seg1 = substr($isbn, 0, 2);
2929 } elsif(substr($isbn, 0, 3) <= 995) {
2930 $seg1 = substr($isbn, 0, 3);
2931 } elsif(substr($isbn, 0, 4) <= 9989) {
2932 $seg1 = substr($isbn, 0, 4);
2934 $seg1 = substr($isbn, 0, 5);
2936 my $x = substr($isbn, length($seg1));
2938 if(substr($x, 0, 2) <= 19) {
2939 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2940 $seg2 = substr($x, 0, 2);
2941 } elsif(substr($x, 0, 3) <= 699) {
2942 $seg2 = substr($x, 0, 3);
2943 } elsif(substr($x, 0, 4) <= 8399) {
2944 $seg2 = substr($x, 0, 4);
2945 } elsif(substr($x, 0, 5) <= 89999) {
2946 $seg2 = substr($x, 0, 5);
2947 } elsif(substr($x, 0, 6) <= 9499999) {
2948 $seg2 = substr($x, 0, 6);
2950 $seg2 = substr($x, 0, 7);
2952 my $seg3=substr($x,length($seg2));
2953 $seg3=substr($seg3,0,length($seg3)-1) ;
2954 my $seg4 = substr($x, -1, 1);
2955 return "$seg1-$seg2-$seg3-$seg4";
2959 END { } # module clean-up code here (global destructor)
2965 Koha Developement team <info@koha.org>
2967 Paul POULAIN paul.poulain@free.fr
2973 # Revision 1.157 2006/03/01 03:07:54 kados
2974 # rollback ... by accident I committed a rel_2_2 Biblio.pm
2976 # Revision 1.155 2006/02/27 01:08:31 kados
2977 # Removing 'our Zconn' from top...
2979 # Revision 1.154 2006/02/26 00:08:20 kados
2980 # moving all $Zconn s to z3950_extended_services (currently, nothing
2983 # Revision 1.153 2006/02/25 22:39:10 kados
2984 # Another purely documentation commit. Just changing formatting to ease
2987 # Revision 1.152 2006/02/25 21:17:20 kados
2988 # Purely documentation change: converted all =head2 entries to use function
2989 # name as title rather than usage as title
2991 # Revision 1.151 2006/02/25 21:02:20 kados
2993 # Further cleanup, convering new routines to 4-chars
2995 # Revision 1.150 2006/02/25 20:49:15 kados
2996 # Better documentation, added warning if serviceType is 'drop' since it's
2997 # not supported in Zebra.
2999 # Revision 1.149 2006/02/25 20:30:32 kados
3000 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
3001 # longer necessary. If we need to convert from MARC-8 for display, we should:
3004 # 2. do it with MARC::Charset
3006 # If you still need it, let me know and I'll put it back in.
3008 # Revision 1.148 2006/02/25 19:23:01 kados
3009 # cleaning up POD docs, deleting zebra_create as it's no longer used (
3010 # replaced by z3950_extended_services).
3012 # Revision 1.147 2006/02/25 19:09:59 kados
3013 # readding some lost subs
3015 # Revision 1.145 2006/02/22 01:02:39 kados
3016 # Replacing all calls to zebra_update with calls to
3017 # z3950_extended_services. More work coming, but it's
3020 # Revision 1.144 2006/02/20 14:22:38 kados
3023 # Revision 1.143 2006/02/20 13:26:11 kados
3024 # A new subroutine to handle Z39.50 extended services. You pass it a
3025 # connection object, service type, service options, and a record, and
3026 # it performs the service and handles any exception found.
3028 # Revision 1.142 2006/02/16 20:49:56 kados
3029 # destroy a connection after we're done -- we really should just have one
3030 # connection object and not destroy it until the whole transaction is
3031 # finished -- but this will do for now
3033 # Revision 1.141 2006/02/16 19:47:22 rangi
3034 # Trying to error trap a little more.
3036 # Revision 1.140 2006/02/14 21:36:03 kados
3037 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3038 # also adding diagnostic error if not able to connect to Zebra
3040 # Revision 1.139 2006/02/14 19:53:25 rangi
3041 # Just a little missing my
3043 # Seems to be working great Paul, and I like what you did with zebradb
3045 # Revision 1.138 2006/02/14 11:25:22 tipaul
3046 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3048 # Revision 1.137 2006/02/13 16:34:26 tipaul
3049 # fixing some warnings (perl -w should be quiet)
3051 # Revision 1.136 2006/01/10 17:01:29 tipaul
3052 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3054 # Revision 1.135 2006/01/06 16:39:37 tipaul
3055 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3056 # Seems not to break too many things, but i'm probably wrong here.
3057 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3059 # - removing useless directories (koha-html and koha-plucene)
3061 # Revision 1.134 2006/01/04 15:54:55 tipaul
3062 # utf8 is a : go for beta test in HEAD.
3063 # some explanations :
3064 # - updater/updatedatabase => will transform all tables in innoDB (not related to utf8, just to warn you) AND collate them in utf8 / utf8_general_ci. The SQL command is : ALTER TABLE tablename DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci.
3065 # - *-top.inc will show the pages in utf8
3066 # - THE HARD THING : for me, mysql-client and mysql-server were set up to communicate in iso8859-1, whatever the mysql collation ! Thus, pages were improperly shown, as datas were transmitted in iso8859-1 format ! After a full day of investigation, someone on usenet pointed "set NAMES 'utf8'" to explain that I wanted utf8. I could put this in my.cnf, but if I do that, ALL databases will "speak" in utf8, that's not what we want. Thus, I added a line in Context.pm : everytime a DB handle is opened, the communication is set to utf8.
3067 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3069 # Revision 1.133 2005/12/12 14:25:51 thd
3072 # Reverse array filled with elements from repeated subfields
3073 # to avoid last to first concatenation of elements in Koha DB.-
3075 # Revision 1.132 2005-10-26 09:12:33 tipaul
3076 # big commit, still breaking things...
3078 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3079 # * code cleaning (cleaning warnings from perl -w) continued
3081 # Revision 1.131 2005/09/22 10:01:45 tipaul
3082 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3084 # Revision 1.130 2005/09/02 14:34:14 tipaul
3085 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3086 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3087 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3089 # Revision 1.129 2005/08/12 13:50:31 tipaul
3090 # removing useless sub declarations
3092 # Revision 1.128 2005/08/11 16:12:47 tipaul
3093 # Playing with the zebra...
3095 # * go to koha cvs home directory
3096 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3097 # * put your zebra.cfg files here & create your database.
3098 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3099 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3102 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3103 # * deletion still not work
3104 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3106 # recordId: (bib1,Local-number)
3110 # elm 090 Local-number -
3111 # elm 090/? Local-number -
3112 # elm 090/?/9 Local-number !:w
3114 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3116 # Revision 1.127 2005/08/11 14:37:32 tipaul
3118 # * removing useless subs
3119 # * removing some subs that are also elsewhere
3120 # * renaming all OLDxxx subs to REALxxx subs (should not change anything, as OLDxxx, as well as REAL, are supposed to be for Biblio.pm internal use only)
3122 # Revision 1.126 2005/08/11 09:13:28 tipaul
3123 # just removing useless subs (a lot !!!) for code cleaning
3125 # Revision 1.125 2005/08/11 09:00:07 tipaul
3126 # Ok guys, this time, it seems that item add and modif begin working as expected...
3127 # Still a lot of bugs to fix, of course
3129 # Revision 1.124 2005/08/10 10:21:15 tipaul
3130 # continuing the road to zebra :
3131 # - the biblio add begins to work.
3132 # - the biblio modif begins to work.
3134 # (still without doing anything on zebra)
3135 # (no new change in updatedatabase)
3137 # Revision 1.123 2005/08/09 14:10:28 tipaul
3138 # 1st commit to go to zebra.
3139 # don't update your cvs if you want to have a working head...
3141 # this commit contains :
3142 # * updater/updatedatabase : get rid with marc_* tables, but DON'T remove them. As a lot of things uses them, it would not be a good idea for instance to drop them. If you really want to play, you can rename them to test head without them but being still able to reintroduce them...
3143 # * Biblio.pm : modify MARCgetbiblio to find the raw marc record in biblioitems.marc field, not from marc_subfield_table, modify MARCfindframeworkcode to find frameworkcode in biblio.frameworkcode, modify some other subs to use biblio.biblionumber & get rid of bibid.
3144 # * other files : get rid of bibid and use biblionumber instead.
3147 # * does not do anything on zebra yet.
3148 # * if you rename marc_subfield_table, you can't search anymore.
3149 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3150 # * don't try to add a biblio, it would add data poorly... (don't try to delete either, it may work, but that would be a surprise ;-) )
3152 # IMPORTANT NOTE : you need MARC::XML package (http://search.cpan.org/~esummers/MARC-XML-0.7/lib/MARC/File/XML.pm), that requires a recent version of MARC::Record
3153 # Updatedatabase stores the iso2709 data in biblioitems.marc field & an xml version in biblioitems.marcxml Not sure we will keep it when releasing the stable version, but I think it's a good idea to have something readable in sql, at least for development stage.
3155 # tipaul cutted previous commit notes