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 our $Zconn=C4::Context->Zconn;
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
79 &get_item_from_barcode
80 &MARCfind_MARCbibid_from_oldbiblionumber
86 C4::Biblio - Acquisitions, Catalog Management Functions
90 ( lot of changes for Koha 3.X)
92 Koha 1.2 and previous versions used a specific API to manage biblios. This API uses old-DB style parameters.
93 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors,
94 bibliosubject and bibliosubtitle where applicable).
96 In Koha 2.X, we introduced a MARC-DB.
98 In Koha 3.X, we removed this MARC-DB for search as we wanted to use Zebra as search system.
100 So in Koha 3.X, saving a record means :
102 - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items information.
103 - storing the "decoded information" in biblio/biblioitems/items as previously.
104 - using zebra to manage search & indexing on the MARC data.
106 In Koha, there is a systempreference for "MARC=ON" or "MARC=OFF" :
108 * MARC=ON : when MARC=ON, Koha uses a MARC::Record object (in sub parameters). Saving information in the DB means :
110 - transform the MARC record into a hash
111 - add the raw MARC record into the hash
112 - store them & update Zebra
114 * MARC=OFF : when MARC=OFF, Koha uses a hash object (in sub parameters). Saving information in the DB means :
116 - transform the hash into a MARC record
117 - add the raw marc record into the hash
118 - store them & update zebra
120 That's why we need 3 types of subs :
124 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).
126 =head2 NEWxxx related subs
130 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.
132 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. They sometimes require another parameter.
136 =head2 something_elsexxx related subs
140 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.
142 all subs require/use $dbh as 1st parameter and a hash as 2nd parameter.
148 =head2 z3950_extended_services
150 z3950_extended_services($serviceType,$serviceOptions,$record);
152 z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
154 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
156 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
158 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
162 recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
163 syntax => the record syntax (transfer syntax)
164 databaseName = Database from connection object
166 To set serviceOptions, call set_service_options($serviceType)
168 C<$record> the record, if one is needed for the service type
170 A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
173 sub z3950_extended_services {
174 my ($serviceType,$serviceOptions,$record) = @_;
176 my $Zconn = C4::Context->Zconn;
177 # create a new package object
178 my $Zpackage = $Zconn->package();
181 $Zpackage->option(action => $serviceOptions->{'action'});
183 if ($serviceOptions->{'databaseName'}) {
184 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
186 if ($serviceOptions->{'recordIdNumber'}) {
187 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
189 if ($serviceOptions->{'recordIdOpaque'}) {
190 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
193 # this is an ILL request (Zebra doesn't support it)
194 #if ($serviceType eq 'itemorder') {
195 # $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
196 # $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
197 # $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
198 # $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
202 my $xmlrecord = marc2xml($record);
203 $Zpackage->option(record => $xmlrecord);
204 if ($serviceOptions->{'syntax'}) {
205 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
209 # send the request, handle any exception encountered
210 eval { $Zpackage->send($serviceType) };
211 if ($@ && $@->isa("ZOOM::Exception")) {
212 print "Oops! ", $@->message(), "\n";
215 # free up package resources
216 $Zpackage->destroy();
219 =head2 set_service_options
221 my $serviceOptions = set_service_options($serviceType);
223 C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
225 Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
229 sub set_service_options {
230 my ($serviceType) = @_;
233 if ($serviceType eq 'update') {
234 $serviceOptions->{ 'action' } = 'specialUpdate';
236 # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
237 # $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
240 if ($serviceType eq 'commit') {
244 if ($serviceType eq 'create') {
247 if ($serviceType eq 'drop') {
248 die "ERROR: 'drop' not currently supported (by Zebra)";
250 return $serviceOptions;
255 my $xmlrecord = marc2xml($record);
257 Convert from MARC to XML. Note that MARC::File::XML will automatically encode from MARC-8 to UTF-8 as of version .8
259 C<$record> a MARC record
266 eval { $xmlrecord=$record->as_xml() };
267 #TODO: better error handling here
269 warn "ERROR: I suspect a badly formatted MARC record";
274 =head2 MARCgettagslib
276 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
280 2nd param is 1 for liblibrarian and 0 for libopac
281 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
283 returns a hash with all values for all fields and subfields for a given MARC framework :
284 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
286 ->{mandatory} = $mandatory;
287 ->{repeatable} = $repeatable;
288 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
290 ->{mandatory} = $mandatory;
291 ->{repeatable} = $repeatable;
292 ->{authorised_value} = $authorised_value;
293 ->{authtypecode} = $authtypecode;
294 ->{value_builder} = $value_builder;
295 ->{kohafield} = $kohafield;
296 ->{seealso} = $seealso;
297 ->{hidden} = $hidden;
306 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
307 $frameworkcode = "" unless $frameworkcode;
308 $forlibrarian = 1 unless $forlibrarian;
310 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
312 # check that framework exists
315 "select count(*) from marc_tag_structure where frameworkcode=?");
316 $sth->execute($frameworkcode);
317 my ($total) = $sth->fetchrow;
318 $frameworkcode = "" unless ( $total > 0 );
321 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
323 $sth->execute($frameworkcode);
324 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
326 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
327 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
328 $res->{$tag}->{tab} = ""; # XXX
329 $res->{$tag}->{mandatory} = $mandatory;
330 $res->{$tag}->{repeatable} = $repeatable;
335 "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"
337 $sth->execute($frameworkcode);
340 my $authorised_value;
350 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
351 $mandatory, $repeatable, $authorised_value, $authtypecode,
352 $value_builder, $kohafield, $seealso, $hidden,
357 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
358 $res->{$tag}->{$subfield}->{tab} = $tab;
359 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
360 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
361 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
362 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
363 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
364 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
365 $res->{$tag}->{$subfield}->{seealso} = $seealso;
366 $res->{$tag}->{$subfield}->{hidden} = $hidden;
367 $res->{$tag}->{$subfield}->{isurl} = $isurl;
368 $res->{$tag}->{$subfield}->{link} = $link;
373 =head2 MARCfind_marc_from_kohafield
375 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
379 finds MARC tag and subfield for a given kohafield
380 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
386 sub MARCfind_marc_from_kohafield {
387 my ( $dbh, $kohafield,$frameworkcode ) = @_;
388 return 0, 0 unless $kohafield;
389 $frameworkcode='' unless $frameworkcode;
390 my $relations = C4::Context->marcfromkohafield;
391 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
396 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
400 Returns a MARC::Record for the biblio $biblionumber.
406 # Returns MARC::Record of the biblio passed in parameter.
407 my ( $dbh, $biblionumber ) = @_;
408 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
409 $sth->execute($biblionumber);
410 my ($marc) = $sth->fetchrow;
411 my $record = MARC::Record::new_from_usmarc($marc);
417 $XML = &XMLgetbiblio($dbh,$biblionumber);
421 Returns a raw XML for the biblio $biblionumber.
427 # Returns MARC::Record of the biblio passed in parameter.
428 my ( $dbh, $biblionumber ) = @_;
429 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
430 $sth->execute($biblionumber);
431 my ($XML,$marc) = $sth->fetchrow;
432 # my $record =MARC::Record::new_from_usmarc($marc);
433 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
439 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
443 Returns a MARC::Record with all items of biblio # $biblionumber
451 my ( $dbh, $biblionumber, $itemnumber ) = @_;
452 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
453 # get the complete MARC record
454 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
455 $sth->execute($biblionumber);
456 my ($rawmarc) = $sth->fetchrow;
457 my $record = MARC::File::USMARC::decode($rawmarc);
458 # now, find the relevant itemnumber
459 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
460 # prepare the new item record
461 my $itemrecord = MARC::Record->new();
462 # parse all fields fields from the complete record
463 foreach ($record->field($itemnumberfield)) {
464 # when the item field is found, save it
465 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
466 $itemrecord->append_fields($_);
473 =head2 find_biblioitemnumber
475 my $biblioitemnumber = find_biblioitemnumber($dbh,$biblionumber);
479 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
480 This sub is useless when MARC=OFF
485 sub find_biblioitemnumber {
486 my ( $dbh, $biblionumber ) = @_;
487 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
488 $sth->execute($biblionumber);
489 my ($biblioitemnumber) = $sth->fetchrow;
490 return $biblioitemnumber;
493 =head2 MARCfind_frameworkcode
495 my $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
499 returns the framework of a given biblio
505 sub MARCfind_frameworkcode {
506 my ( $dbh, $biblionumber ) = @_;
507 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
508 $sth->execute($biblionumber);
509 my ($frameworkcode) = $sth->fetchrow;
510 return $frameworkcode;
513 =head2 MARCkoha2marcBiblio
515 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
519 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
520 all entries of the hash are transformed into their matching MARC field/subfield.
526 sub MARCkoha2marcBiblio {
528 # this function builds partial MARC::Record from the old koha-DB fields
529 my ( $dbh, $bibliohash ) = @_;
530 # we don't have biblio entries in the hash, so we add them first
531 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
532 $sth->execute($bibliohash->{biblionumber});
533 my $biblio = $sth->fetchrow_hashref;
534 foreach (keys %$biblio) {
535 $bibliohash->{$_}=$biblio->{$_};
537 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
538 my $record = MARC::Record->new();
539 foreach ( keys %$bibliohash ) {
540 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
541 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
544 # other fields => additional authors, subjects, subtitles
545 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
546 $sth2->execute($bibliohash->{biblionumber});
547 while ( my $row = $sth2->fetchrow_hashref ) {
548 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
550 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
551 $sth2->execute($bibliohash->{biblionumber});
552 while ( my $row = $sth2->fetchrow_hashref ) {
553 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
555 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
556 $sth2->execute($bibliohash->{biblionumber});
557 while ( my $row = $sth2->fetchrow_hashref ) {
558 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
564 =head2 MARCkoha2marcItem
566 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
568 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
569 all entries of the hash are transformed into their matching MARC field/subfield.
577 sub MARCkoha2marcItem {
579 # this function builds partial MARC::Record from the old koha-DB fields
580 my ( $dbh, $item ) = @_;
582 # my $dbh=&C4Connect;
583 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
584 my $record = MARC::Record->new();
586 foreach( keys %$item ) {
588 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
595 =head2 MARCkoha2marcOnefield
599 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
605 sub MARCkoha2marcOnefield {
606 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
609 $sth->execute($frameworkcode,$kohafieldname);
610 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
611 if ( $record->field($tagfield) ) {
612 my $tag = $record->field($tagfield);
614 $tag->add_subfields( $tagsubfield, $value );
615 $record->delete_field($tag);
616 $record->add_fields($tag);
620 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
628 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
632 transforms the parameters (coming from HTML form) into a MARC::Record
633 parameters with r are references to arrays.
635 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
642 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
644 my $record = MARC::Record->new();
645 # my %subfieldlist=();
646 my $prevvalue; # if tag <10
647 my $field; # if tag >=10
648 for (my $i=0; $i< @$rtags; $i++) {
649 next unless @$rvalues[$i];
650 # rebuild MARC::Record
651 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
652 if (@$rtags[$i] ne $prevtag) {
655 if ($prevtag ne '000') {
656 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
658 $record->leader($prevvalue);
663 $record->add_fields($field);
666 $indicators{@$rtags[$i]}.=' ';
667 if (@$rtags[$i] <10) {
668 $prevvalue= @$rvalues[$i];
672 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
673 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
675 $prevtag = @$rtags[$i];
677 if (@$rtags[$i] <10) {
678 $prevvalue=@$rvalues[$i];
680 if (length(@$rvalues[$i])>0) {
681 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
682 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
685 $prevtag= @$rtags[$i];
688 # the last has not been included inside the loop... do it now !
689 $record->add_fields($field) if $field;
690 # warn "HTML2MARC=".$record->as_formatted;
697 $hash = &MARCmarc2koha($dbh,$MARCRecord);
701 builds a hash with old-db datas from a MARC::Record
708 my ($dbh,$record,$frameworkcode) = @_;
709 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
711 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
714 while (($field)=$sth2->fetchrow) {
715 # warn "biblio.".$field;
716 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
718 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
720 while (($field)=$sth2->fetchrow) {
721 if ($field eq 'notes') { $field = 'bnotes'; }
722 # warn "biblioitems".$field;
723 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
725 $sth2=$dbh->prepare("SHOW COLUMNS from items");
727 while (($field)=$sth2->fetchrow) {
728 # warn "items".$field;
729 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
731 # additional authors : specific
732 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
733 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
734 # modify copyrightdate to keep only the 1st year found
735 my $temp = $result->{'copyrightdate'};
737 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
739 $result->{'copyrightdate'} = $1;
740 } else { # if no cYYYY, get the 1st date.
741 $temp =~ m/(\d\d\d\d)/;
742 $result->{'copyrightdate'} = $1;
745 # modify publicationyear to keep only the 1st year found
746 $temp = $result->{'publicationyear'};
747 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
749 $result->{'publicationyear'} = $1;
750 } else { # if no cYYYY, get the 1st date.
751 $temp =~ m/(\d\d\d\d)/;
752 $result->{'publicationyear'} = $1;
757 sub MARCmarc2kohaOneField {
759 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
760 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
761 # warn "kohatable / $kohafield / $result / ";
765 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
766 foreach my $field ( $record->field($tagfield) ) {
767 if ($field->tag()<10) {
768 if ($result->{$kohafield}) {
769 # Reverse array filled with elements from repeated subfields
770 # from first to last to avoid last to first concatenation of
771 # elements in Koha DB. -- thd.
772 $result->{$kohafield} .= " | ".reverse($field->data());
774 $result->{$kohafield} = $field->data();
777 if ( $field->subfields ) {
778 my @subfields = $field->subfields();
779 foreach my $subfieldcount ( 0 .. $#subfields ) {
780 if ($subfields[$subfieldcount][0] eq $subfield) {
781 if ( $result->{$kohafield} ) {
782 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
785 $result->{$kohafield} = $subfields[$subfieldcount][1];
792 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
798 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
802 creates a biblio from a MARC::Record.
809 my ( $dbh,$record,$frameworkcode ) = @_;
811 my $biblioitemnumber;
812 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
813 $olddata->{frameworkcode} = $frameworkcode;
814 $biblionumber = REALnewbiblio( $dbh, $olddata );
815 $olddata->{biblionumber} = $biblionumber;
816 # add biblionumber into the MARC record (it's the ID for zebra)
817 my ( $tagfield, $tagsubfield ) =
818 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
822 $newfield = MARC::Field->new(
823 $tagfield, $biblionumber,
826 $newfield = MARC::Field->new(
827 $tagfield, '', '', "$tagsubfield" => $biblionumber,
830 # drop old field (just in case it already exist and create new one...
831 my $old_field = $record->field($tagfield);
832 $record->delete_field($old_field);
833 $record->add_fields($newfield);
835 #create the marc entry, that stores the rax marc record in Koha 3.0
836 $olddata->{marc} = $record->as_usmarc();
837 $olddata->{marcxml} = $record->as_xml();
838 # and create biblioitem, that's all folks !
839 $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
841 # search subtiles, addiauthors and subjects
842 ( $tagfield, $tagsubfield ) =
843 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
844 my @addiauthfields = $record->field($tagfield);
845 foreach my $addiauthfield (@addiauthfields) {
846 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
847 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
848 REALmodaddauthor( $dbh, $biblionumber,
849 $addiauthsubfields[$subfieldcount] );
852 ( $tagfield, $tagsubfield ) =
853 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
854 my @subtitlefields = $record->field($tagfield);
855 foreach my $subtitlefield (@subtitlefields) {
856 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
857 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
858 REALnewsubtitle( $dbh, $biblionumber,
859 $subtitlesubfields[$subfieldcount] );
862 ( $tagfield, $tagsubfield ) =
863 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
864 my @subj = $record->field($tagfield);
866 foreach my $subject (@subj) {
867 my @subjsubfield = $subject->subfield($tagsubfield);
868 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
869 push @subjects, $subjsubfield[$subfieldcount];
872 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
873 return ( $biblionumber, $biblioitemnumber );
876 =head2 NEWmodbilbioframework
878 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
882 modify the framework of a biblio
888 sub NEWmodbiblioframework {
889 my ($dbh,$biblionumber,$frameworkcode) =@_;
890 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
891 $sth->execute($frameworkcode,$biblionumber);
897 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
901 modify a biblio (MARC=ON)
908 my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
909 $frameworkcode="" unless $frameworkcode;
910 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
911 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
913 $oldbiblio->{frameworkcode} = $frameworkcode;
914 #create the marc entry, that stores the rax marc record in Koha 3.0
915 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
916 $oldbiblio->{marc} = $record->as_usmarc();
917 $oldbiblio->{marcxml} = $record->as_xml();
918 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
919 REALmodbiblio($dbh,$oldbiblio);
920 REALmodbiblioitem($dbh,$oldbiblio);
921 # now, modify addi authors, subject, addititles.
922 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
923 my @addiauthfields = $record->field($tagfield);
924 foreach my $addiauthfield (@addiauthfields) {
925 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
926 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
927 foreach my $subfieldcount (0..$#addiauthsubfields) {
928 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
931 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
932 my @subtitlefields = $record->field($tagfield);
933 foreach my $subtitlefield (@subtitlefields) {
934 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
935 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
937 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
938 foreach my $subfieldcount (0..$#subtitlesubfields) {
939 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
940 REALnewsubtitle($dbh,$biblionumber,$subtit);
944 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
945 my @subj = $record->field($tagfield);
947 foreach my $subject (@subj) {
948 my @subjsubfield = $subject->subfield($tagsubfield);
949 foreach my $subfieldcount (0..$#subjsubfield) {
950 push @subjects,$subjsubfield[$subfieldcount];
953 REALmodsubject($dbh,$biblionumber,1,@subjects);
957 =head2 NEWmodbilbioframework
959 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
970 my ( $dbh, $bibid ) = @_;
971 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
972 &REALdelbiblio( $dbh, $biblio );
975 "select biblioitemnumber from biblioitems where biblionumber=?");
976 $sth->execute($biblio);
977 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
978 REALdelbiblioitem( $dbh, $biblioitemnumber );
980 &MARCdelbiblio( $dbh, $bibid, 0 );
985 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
989 creates an item from a MARC::Record
996 my ( $dbh,$record,$biblionumber,$biblioitemnumber ) = @_;
999 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1000 my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
1001 # needs old biblionumber and biblioitemnumber
1002 $item->{'biblionumber'} = $biblionumber;
1003 $item->{'biblioitemnumber'}=$biblioitemnumber;
1004 $item->{marc} = $record->as_usmarc();
1005 #warn $item->{marc};
1006 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
1013 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1024 my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1026 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1027 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1029 $olditem->{marc} = $record->as_usmarc();
1030 $olditem->{biblionumber} = $biblionumber;
1031 $olditem->{biblioitemnumber} = $biblioitemnumber;
1033 REALmoditem( $dbh, $olditem );
1039 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1050 my ( $dbh, $bibid, $itemnumber ) = @_;
1051 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1052 &REALdelitem( $dbh, $itemnumber );
1053 &MARCdelitem( $dbh, $bibid, $itemnumber );
1057 =head2 REALnewbiblio
1059 $biblionumber = REALnewbiblio($dbh,$biblio);
1063 adds a record in biblio table. Datas are in the hash $biblio.
1070 my ( $dbh, $biblio ) = @_;
1072 $dbh->do('lock tables biblio WRITE');
1073 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1075 my $data = $sth->fetchrow_arrayref;
1076 my $bibnum = $$data[0] + 1;
1079 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1082 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1083 serial=?, seriestitle=?, notes=?, abstract=?,
1087 $bibnum, $biblio->{'title'},
1088 $biblio->{'author'}, $biblio->{'copyrightdate'},
1089 $biblio->{'serial'}, $biblio->{'seriestitle'},
1090 $biblio->{'notes'}, $biblio->{'abstract'},
1091 $biblio->{'unititle'}
1095 $dbh->do('unlock tables');
1099 =head2 REALmodbiblio
1101 $biblionumber = REALmodbiblio($dbh,$biblio);
1105 modify a record in biblio table. Datas are in the hash $biblio.
1112 my ( $dbh, $biblio ) = @_;
1113 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1114 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1115 where biblionumber = ?"
1118 $biblio->{'title'}, $biblio->{'author'},
1119 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1120 $biblio->{'seriestitle'}, $biblio->{'serial'},
1121 $biblio->{'unititle'}, $biblio->{'notes'},
1122 $biblio->{frameworkcode},
1123 $biblio->{'biblionumber'}
1126 return ( $biblio->{'biblionumber'} );
1129 =head2 REALmodsubtitle
1131 REALmodsubtitle($dbh,$bibnum,$subtitle);
1135 modify subtitles in bibliosubtitle table.
1141 sub REALmodsubtitle {
1142 my ( $dbh, $bibnum, $subtitle ) = @_;
1145 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1146 $sth->execute( $subtitle, $bibnum );
1150 =head2 REALmodaddauthor
1152 REALmodaddauthor($dbh,$bibnum,$author);
1156 adds or modify additional authors
1157 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1163 sub REALmodaddauthor {
1164 my ( $dbh, $bibnum, @authors ) = @_;
1166 # my $dbh = C4Connect;
1168 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1170 $sth->execute($bibnum);
1172 foreach my $author (@authors) {
1173 if ( $author ne '' ) {
1176 "Insert into additionalauthors set author = ?, biblionumber = ?"
1179 $sth->execute( $author, $bibnum );
1184 } # sub modaddauthor
1186 =head2 REALmodsubject
1188 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1192 modify/adds subjects
1197 sub REALmodsubject {
1198 my ( $dbh, $bibnum, $force, @subject ) = @_;
1200 # my $dbh = C4Connect;
1201 my $count = @subject;
1203 for ( my $i = 0 ; $i < $count ; $i++ ) {
1204 $subject[$i] =~ s/^ //g;
1205 $subject[$i] =~ s/ $//g;
1208 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1210 $sth->execute( $subject[$i] );
1212 if ( my $data = $sth->fetchrow_hashref ) {
1215 if ( $force eq $subject[$i] || $force == 1 ) {
1217 # subject not in aut, chosen to force anway
1218 # so insert into cataloguentry so its in auth file
1221 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1224 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1229 "$subject[$i]\n does not exist in the subject authority file";
1232 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1234 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1236 while ( my $data = $sth2->fetchrow_hashref ) {
1237 $error .= "<br>$data->{'catalogueentry'}";
1246 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1247 $sth->execute($bibnum);
1251 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1253 foreach $query (@subject) {
1254 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1263 =head2 REALmodbiblioitem
1265 REALmodbiblioitem($dbh, $biblioitem);
1274 sub REALmodbiblioitem {
1275 my ( $dbh, $biblioitem ) = @_;
1278 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1279 itemtype=?, url=?, isbn=?, issn=?,
1280 publishercode=?, publicationyear=?, classification=?, dewey=?,
1281 subclass=?, illus=?, pages=?, volumeddesc=?,
1282 notes=?, size=?, place=?, marc=?,
1284 where biblioitemnumber=?");
1285 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1286 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1287 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1288 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1289 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1290 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1292 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1294 z3950_extended_services('update',set_service_options('update'),$record);
1297 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1300 =head2 REALnewbiblioitem
1302 REALnewbiblioitem($dbh,$biblioitem);
1306 adds a biblioitem ($biblioitem is a hash with the values)
1312 sub REALnewbiblioitem {
1313 my ( $dbh, $biblioitem ) = @_;
1315 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1316 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1318 my $biblioitemnumber;
1321 $data = $sth->fetchrow_arrayref;
1322 $biblioitemnumber = $$data[0] + 1;
1324 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1325 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1326 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1327 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1328 my $field=$record->field($biblioitemnumberfield);
1329 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1330 $biblioitem->{marc} = $record->as_usmarc();
1331 $biblioitem->{marcxml} = $record->as_xml();
1333 $sth = $dbh->prepare( "insert into biblioitems set
1334 biblioitemnumber = ?, biblionumber = ?,
1335 volume = ?, number = ?,
1336 classification = ?, itemtype = ?,
1338 issn = ?, dewey = ?,
1339 subclass = ?, publicationyear = ?,
1340 publishercode = ?, volumedate = ?,
1341 volumeddesc = ?, illus = ?,
1342 pages = ?, notes = ?,
1344 marc = ?, place = ?,
1348 $biblioitemnumber, $biblioitem->{'biblionumber'},
1349 $biblioitem->{'volume'}, $biblioitem->{'number'},
1350 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1351 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1352 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1353 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1354 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1355 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1356 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1357 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1358 $biblioitem->{'marc'}, $biblioitem->{'place'},
1359 $biblioitem->{marcxml},
1361 $dbh->do("unlock tables");
1362 z3950_extended_services('update',set_service_options('update'),$record);
1363 return ($biblioitemnumber);
1366 =head2 REALnewsubtitle
1368 REALnewsubtitle($dbh,$bibnum,$subtitle);
1372 create a new subtitle
1377 sub REALnewsubtitle {
1378 my ( $dbh, $bibnum, $subtitle ) = @_;
1381 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1382 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1388 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1392 create a item. $item is a hash and $barcode the barcode.
1399 my ( $dbh, $item, $barcode ) = @_;
1401 # warn "OLDNEWITEMS";
1403 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1404 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1409 $data = $sth->fetchrow_hashref;
1410 $itemnumber = $data->{'max(itemnumber)'} + 1;
1412 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1413 if ( $item->{'loan'} ) {
1414 $item->{'notforloan'} = $item->{'loan'};
1416 $item->{'biblioitemnumber'} = 1;
1417 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1418 if ( $item->{'dateaccessioned'} ) {
1419 $sth = $dbh->prepare( "Insert into items set
1420 itemnumber = ?, biblionumber = ?,
1421 multivolumepart = ?,
1422 biblioitemnumber = ?, barcode = ?,
1423 booksellerid = ?, dateaccessioned = ?,
1424 homebranch = ?, holdingbranch = ?,
1425 price = ?, replacementprice = ?,
1426 replacementpricedate = NOW(), datelastseen = NOW(),
1427 multivolume = ?, stack = ?,
1428 itemlost = ?, wthdrawn = ?,
1429 paidfor = ?, itemnotes = ?,
1430 itemcallnumber =?, notforloan = ?,
1435 $itemnumber, $item->{'biblionumber'},
1436 $item->{'multivolumepart'},
1437 $item->{'biblioitemnumber'},$item->{barcode},
1438 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1439 $item->{'homebranch'}, $item->{'holdingbranch'},
1440 $item->{'price'}, $item->{'replacementprice'},
1441 $item->{multivolume}, $item->{stack},
1442 $item->{itemlost}, $item->{wthdrawn},
1443 $item->{paidfor}, $item->{'itemnotes'},
1444 $item->{'itemcallnumber'}, $item->{'notforloan'},
1447 if ( defined $sth->errstr ) {
1448 $error .= $sth->errstr;
1452 $sth = $dbh->prepare( "Insert into items set
1453 itemnumber = ?, biblionumber = ?,
1454 multivolumepart = ?,
1455 biblioitemnumber = ?, barcode = ?,
1456 booksellerid = ?, dateaccessioned = NOW(),
1457 homebranch = ?, holdingbranch = ?,
1458 price = ?, replacementprice = ?,
1459 replacementpricedate = NOW(), datelastseen = NOW(),
1460 multivolume = ?, stack = ?,
1461 itemlost = ?, wthdrawn = ?,
1462 paidfor = ?, itemnotes = ?,
1463 itemcallnumber =?, notforloan = ?,
1468 $itemnumber, $item->{'biblionumber'},
1469 $item->{'multivolumepart'},
1470 $item->{'biblioitemnumber'},$item->{barcode},
1471 $item->{'booksellerid'},
1472 $item->{'homebranch'}, $item->{'holdingbranch'},
1473 $item->{'price'}, $item->{'replacementprice'},
1474 $item->{multivolume}, $item->{stack},
1475 $item->{itemlost}, $item->{wthdrawn},
1476 $item->{paidfor}, $item->{'itemnotes'},
1477 $item->{'itemcallnumber'}, $item->{'notforloan'},
1480 if ( defined $sth->errstr ) {
1481 $error .= $sth->errstr;
1484 # item stored, now, deal with the marc part...
1485 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1486 where biblio.biblionumber=biblioitems.biblionumber and
1487 biblio.biblionumber=?");
1488 $sth->execute($item->{biblionumber});
1489 if ( defined $sth->errstr ) {
1490 $error .= $sth->errstr;
1492 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1493 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1494 my $record = MARC::File::USMARC::decode($rawmarc);
1495 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1496 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1497 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1499 #warn $itemnumberfield;
1500 #warn $itemrecord->field($itemnumberfield);
1501 my $itemfield = $itemrecord->field($itemnumberfield);
1502 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1503 $record->insert_grouped_field($itemfield);
1504 # save the record into biblioitem
1505 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1506 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1507 if ( defined $sth->errstr ) {
1508 $error .= $sth->errstr;
1510 z3950_extended_services('update',set_service_options('update'),$record);
1511 $dbh->do('unlock tables');
1512 return ( $itemnumber, $error );
1515 =head2 REALmoditem($dbh,$item);
1526 my ( $dbh, $item ) = @_;
1527 $item->{'bibitemnum'} = 1;
1529 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1530 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1531 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1533 $item->{'barcode'}, $item->{'itemnotes'},
1534 $item->{'itemcallnumber'}, $item->{'notforloan'},
1535 $item->{'location'}, $item->{multivolumepart},
1536 $item->{multivolume}, $item->{stack},
1539 if ( $item->{'lost'} ne '' ) {
1540 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1541 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1542 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1544 $item->{'bibitemnum'}, $item->{'barcode'},
1545 $item->{'itemnotes'}, $item->{'homebranch'},
1546 $item->{'lost'}, $item->{'wthdrawn'},
1547 $item->{'itemcallnumber'}, $item->{'notforloan'},
1548 $item->{'location'}, $item->{multivolumepart},
1549 $item->{multivolume}, $item->{stack},
1552 if ($item->{homebranch}) {
1553 $query.=",homebranch=?";
1554 push @bind, $item->{homebranch};
1556 if ($item->{holdingbranch}) {
1557 $query.=",holdingbranch=?";
1558 push @bind, $item->{holdingbranch};
1561 $query.=" where itemnumber=?";
1562 push @bind,$item->{'itemnum'};
1563 if ( $item->{'replacement'} ne '' ) {
1564 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1566 my $sth = $dbh->prepare($query);
1567 $sth->execute(@bind);
1569 # item stored, now, deal with the marc part...
1570 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1571 where biblio.biblionumber=biblioitems.biblionumber and
1572 biblio.biblionumber=? and
1573 biblioitems.biblioitemnumber=?");
1574 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1575 if ( defined $sth->errstr ) {
1576 $error .= $sth->errstr;
1578 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1579 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1580 my $record = MARC::File::USMARC::decode($rawmarc);
1581 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1582 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1583 # prepare the new item record
1584 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1585 my $itemfield = $itemrecord->field($itemnumberfield);
1586 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1587 # parse all fields fields from the complete record
1588 foreach ($record->field($itemnumberfield)) {
1589 # when the previous field is found, replace by the new one
1590 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1591 $_->replace_with($itemfield);
1594 # $record->insert_grouped_field($itemfield);
1595 # save the record into biblioitem
1596 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1597 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1598 z3950_extended_services('update',set_service_options('update'),$record);
1599 if ( defined $sth->errstr ) {
1600 $error .= $sth->errstr;
1602 $dbh->do('unlock tables');
1606 =head2 REALdelitem($dbh,$itemnum);
1617 my ( $dbh, $itemnum ) = @_;
1619 # my $dbh=C4Connect;
1620 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1621 $sth->execute($itemnum);
1622 my $data = $sth->fetchrow_hashref;
1624 my $query = "Insert into deleteditems set ";
1626 foreach my $temp ( keys %$data ) {
1627 $query .= "$temp = ?,";
1628 push ( @bind, $data->{$temp} );
1633 $sth = $dbh->prepare($query);
1634 $sth->execute(@bind);
1636 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1637 $sth->execute($itemnum);
1643 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1647 deletes a biblioitem
1648 NOTE : not standard sub name. Should be REALdelbiblioitem()
1654 sub REALdelbiblioitem {
1655 my ( $dbh, $biblioitemnumber ) = @_;
1657 # my $dbh = C4Connect;
1658 my $sth = $dbh->prepare( "Select * from biblioitems
1659 where biblioitemnumber = ?"
1663 $sth->execute($biblioitemnumber);
1665 if ( $results = $sth->fetchrow_hashref ) {
1669 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1670 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1671 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1675 $results->{biblioitemnumber}, $results->{biblionumber},
1676 $results->{volume}, $results->{number},
1677 $results->{classification}, $results->{itemtype},
1678 $results->{isbn}, $results->{issn},
1679 $results->{dewey}, $results->{subclass},
1680 $results->{publicationyear}, $results->{publishercode},
1681 $results->{volumedate}, $results->{volumeddesc},
1682 $results->{timestamp}, $results->{illus},
1683 $results->{pages}, $results->{notes},
1684 $results->{size}, $results->{url},
1688 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1689 $sth2->execute($biblioitemnumber);
1694 # Now delete all the items attached to the biblioitem
1695 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1696 $sth->execute($biblioitemnumber);
1698 while ( my $data = $sth->fetchrow_hashref ) {
1699 my $query = "Insert into deleteditems set ";
1701 foreach my $temp ( keys %$data ) {
1702 $query .= "$temp = ?,";
1703 push ( @bind, $data->{$temp} );
1706 my $sth2 = $dbh->prepare($query);
1707 $sth2->execute(@bind);
1710 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1711 $sth->execute($biblioitemnumber);
1715 } # sub deletebiblioitem
1717 =head2 REALdelbiblio($dbh,$biblio);
1728 my ( $dbh, $biblio ) = @_;
1729 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1730 $sth->execute($biblio);
1731 if ( my $data = $sth->fetchrow_hashref ) {
1733 my $query = "Insert into deletedbiblio set ";
1735 foreach my $temp ( keys %$data ) {
1736 $query .= "$temp = ?,";
1737 push ( @bind, $data->{$temp} );
1740 #replacing the last , by ",?)"
1742 $sth = $dbh->prepare($query);
1743 $sth->execute(@bind);
1745 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1746 $sth->execute($biblio);
1754 $number = itemcount($biblio);
1758 returns the number of items attached to a biblio
1766 my $dbh = C4::Context->dbh;
1769 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1770 $sth->execute($biblio);
1771 my $data = $sth->fetchrow_hashref;
1773 return ( $data->{'count(*)'} );
1778 $biblionumber = newbiblio($biblio);
1782 create a biblio. The parameter is a hash
1790 my $dbh = C4::Context->dbh;
1791 my $bibnum = REALnewbiblio( $dbh, $biblio );
1792 # finds new (MARC bibid
1793 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1794 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1795 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1801 $biblionumber = &modbiblio($biblio);
1805 Update a biblio record.
1807 C<$biblio> is a reference-to-hash whose keys are the fields in the
1808 biblio table in the Koha database. All fields must be present, not
1809 just the ones you wish to change.
1811 C<&modbiblio> updates the record defined by
1812 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1814 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1823 my $dbh = C4::Context->dbh;
1824 my $biblionumber=REALmodbiblio($dbh,$biblio);
1825 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1826 # finds new (MARC bibid
1827 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1828 MARCmodbiblio($dbh,$bibid,$record,"",0);
1829 return($biblionumber);
1832 =head2 &modsubtitle($biblionumber, $subtitle);
1836 Sets the subtitle of a book.
1838 C<$biblionumber> is the biblionumber of the book to modify.
1840 C<$subtitle> is the new subtitle.
1847 my ( $bibnum, $subtitle ) = @_;
1848 my $dbh = C4::Context->dbh;
1849 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1852 =head2 &modaddauthor($biblionumber, $author);
1856 Replaces all additional authors for the book with biblio number
1857 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1858 C<&modaddauthor> deletes all additional authors.
1865 my ( $bibnum, @authors ) = @_;
1866 my $dbh = C4::Context->dbh;
1867 &REALmodaddauthor( $dbh, $bibnum, @authors );
1868 } # sub modaddauthor
1872 $error = &modsubject($biblionumber, $force, @subjects);
1876 $force - a subject to force
1877 $error - Error message, or undef if successful.
1884 my ( $bibnum, $force, @subject ) = @_;
1885 my $dbh = C4::Context->dbh;
1886 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1888 # When MARC is off, ensures that the MARC biblio table gets updated with new
1889 # subjects, of course, it deletes the biblio in marc, and then recreates.
1890 # This check is to ensure that no MARC data exists to lose.
1891 # if (C4::Context->preference("MARC") eq '0'){
1892 # warn "in modSUBJECT";
1893 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1894 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1895 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1901 =head2 modbibitem($dbh, $biblioitem);
1905 modify a biblioitem. The parameter is a hash
1912 my ($dbh, $biblioitem) = @_;
1913 #my $dbh = C4::Context->dbh;
1914 &REALmodbiblioitem( $dbh, $biblioitem );
1917 =head2 newbiblioitem
1919 $biblioitemnumber = newbiblioitem($biblioitem)
1923 create a biblioitem, the parameter is a hash
1930 my ($dbh, $biblioitem) = @_;
1931 #my $dbh = C4::Context->dbh;
1932 # add biblio information to the hash
1933 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1934 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1935 my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1936 return ($bibitemnum);
1939 =head2 newsubtitle($biblionumber,$subtitle);
1943 insert a subtitle for $biblionumber biblio
1951 my ( $bibnum, $subtitle ) = @_;
1952 my $dbh = C4::Context->dbh;
1953 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1958 $errors = newitems($dbh, $item, @barcodes);
1962 insert items ($item is a hash)
1970 my ( $dbh, $item, @barcodes ) = @_;
1971 #my $dbh = C4::Context->dbh;
1975 foreach my $barcode (@barcodes) {
1976 # add items, one by one for each barcode.
1978 $oneitem->{barcode}= $barcode;
1979 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1980 $oneitem->{marc} = $MARCitem->as_usmarc;
1981 ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
1982 # $errors .= $error;
1983 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1988 =head2 moditem($dbh,$item);
1992 modify an item ($item is a hash with all item informations)
2000 my ($dbh, $item) = @_;
2001 #my $dbh = C4::Context->dbh;
2002 &REALmoditem( $dbh, $item );
2004 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
2006 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
2007 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
2012 $error = checkitems($count,@barcodes);
2016 check for each @barcode entry that the barcode is not a duplicate
2023 my ( $count, @barcodes ) = @_;
2024 my $dbh = C4::Context->dbh;
2026 my $sth = $dbh->prepare("Select * from items where barcode=?");
2027 for ( my $i = 0 ; $i < $count ; $i++ ) {
2028 $barcodes[$i] = uc $barcodes[$i];
2029 $sth->execute( $barcodes[$i] );
2030 if ( my $data = $sth->fetchrow_hashref ) {
2031 $error .= " Duplicate Barcode: $barcodes[$i]";
2038 =head2 delitem($itemnum);
2042 delete item $itemnum being the item number to delete
2050 my $dbh = C4::Context->dbh;
2051 &REALdelitem( $dbh, $itemnum );
2054 =head2 deletebiblioitem($biblioitemnumber);
2058 delete the biblioitem $biblioitemnumber
2064 sub deletebiblioitem {
2065 my ($biblioitemnumber) = @_;
2066 my $dbh = C4::Context->dbh;
2067 &REALdelbiblioitem( $dbh, $biblioitemnumber );
2068 } # sub deletebiblioitem
2070 =head2 delbiblio($biblionumber)
2074 delete biblio $biblionumber
2082 my $dbh = C4::Context->dbh;
2083 &REALdelbiblio( $dbh, $biblio );
2084 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2085 &MARCdelbiblio( $dbh, $bibid, 0 );
2090 ($count,@results) = getbiblio($biblionumber);
2094 return an array with hash of biblios.
2096 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2103 my ($biblionumber) = @_;
2104 my $dbh = C4::Context->dbh;
2105 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2107 # || die "Cannot prepare $query\n" . $dbh->errstr;
2111 $sth->execute($biblionumber);
2113 # || die "Cannot execute $query\n" . $sth->errstr;
2114 while ( my $data = $sth->fetchrow_hashref ) {
2115 $results[$count] = $data;
2120 return ( $count, @results );
2125 $data = &bibdata($biblionumber, $type);
2127 Returns information about the book with the given biblionumber.
2129 C<$type> is ignored.
2131 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2132 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2135 In addition, C<$data-E<gt>{subject}> is the list of the book's
2136 subjects, separated by C<" , "> (space, comma, space).
2138 If there are multiple biblioitems with the given biblionumber, only
2139 the first one is considered.
2144 my ($bibnum, $type) = @_;
2145 my $dbh = C4::Context->dbh;
2146 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2148 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2149 left join bibliosubtitle on
2150 biblio.biblionumber = bibliosubtitle.biblionumber
2151 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2152 where biblio.biblionumber = ?
2154 $sth->execute($bibnum);
2156 $data = $sth->fetchrow_hashref;
2158 # handle management of repeated subtitle
2159 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2160 $sth->execute($bibnum);
2162 while (my $dat = $sth->fetchrow_hashref){
2164 $line{subtitle} = $dat->{subtitle};
2165 push @subtitles, \%line;
2167 $data->{subtitles} = \@subtitles;
2169 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2170 $sth->execute($bibnum);
2172 while (my $dat = $sth->fetchrow_hashref){
2174 $line{subject} = $dat->{'subject'};
2175 push @subjects, \%line;
2177 $data->{subjects} = \@subjects;
2179 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2180 $sth->execute($bibnum);
2181 while (my $dat = $sth->fetchrow_hashref){
2182 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2184 chop $data->{'additionalauthors'};
2185 chop $data->{'additionalauthors'};
2186 chop $data->{'additionalauthors'};
2191 =head2 getbiblioitem
2193 ($count,@results) = getbiblioitem($biblioitemnumber);
2197 return an array with hash of biblioitemss.
2199 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2206 my ($biblioitemnum) = @_;
2207 my $dbh = C4::Context->dbh;
2208 my $sth = $dbh->prepare( "Select * from biblioitems where
2209 biblioitemnumber = ?"
2214 $sth->execute($biblioitemnum);
2216 while ( my $data = $sth->fetchrow_hashref ) {
2217 $results[$count] = $data;
2222 return ( $count, @results );
2223 } # sub getbiblioitem
2225 =head2 getbiblioitembybiblionumber
2227 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2231 return an array with hash of biblioitems for the given biblionumber.
2237 sub getbiblioitembybiblionumber {
2238 my ($biblionumber) = @_;
2239 my $dbh = C4::Context->dbh;
2240 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2244 $sth->execute($biblionumber);
2246 while ( my $data = $sth->fetchrow_hashref ) {
2247 $results[$count] = $data;
2252 return ( $count, @results );
2255 =head2 getitemsbybiblioitem
2257 ($count,@results) = getitemsbybiblioitem($biblionumber);
2261 returns an array with hash of items
2267 sub getitemsbybiblioitem {
2268 my ($biblioitemnum) = @_;
2269 my $dbh = C4::Context->dbh;
2270 my $sth = $dbh->prepare( "Select * from items, biblio where
2271 biblio.biblionumber = items.biblionumber and biblioitemnumber
2275 # || die "Cannot prepare $query\n" . $dbh->errstr;
2279 $sth->execute($biblioitemnum);
2281 # || die "Cannot execute $query\n" . $sth->errstr;
2282 while ( my $data = $sth->fetchrow_hashref ) {
2283 $results[$count] = $data;
2288 return ( $count, @results );
2289 } # sub getitemsbybiblioitem
2293 @results = &ItemInfo($env, $biblionumber, $type);
2295 Returns information about books with the given biblionumber.
2297 C<$type> may be either C<intra> or anything else. If it is not set to
2298 C<intra>, then the search will exclude lost, very overdue, and
2303 C<&ItemInfo> returns a list of references-to-hash. Each element
2304 contains a number of keys. Most of them are table items from the
2305 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2306 Koha database. Other keys include:
2310 =item C<$data-E<gt>{branchname}>
2312 The name (not the code) of the branch to which the book belongs.
2314 =item C<$data-E<gt>{datelastseen}>
2316 This is simply C<items.datelastseen>, except that while the date is
2317 stored in YYYY-MM-DD format in the database, here it is converted to
2318 DD/MM/YYYY format. A NULL date is returned as C<//>.
2320 =item C<$data-E<gt>{datedue}>
2322 =item C<$data-E<gt>{class}>
2324 This is the concatenation of C<biblioitems.classification>, the book's
2325 Dewey code, and C<biblioitems.subclass>.
2327 =item C<$data-E<gt>{ocount}>
2329 I think this is the number of copies of the book available.
2331 =item C<$data-E<gt>{order}>
2333 If this is set, it is set to C<One Order>.
2340 my ($env,$biblionumber,$type) = @_;
2341 my $dbh = C4::Context->dbh;
2342 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2343 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2344 WHERE items.biblionumber = ?
2345 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2346 AND biblio.biblionumber = items.biblionumber";
2347 $query .= " order by items.dateaccessioned desc";
2348 my $sth=$dbh->prepare($query);
2349 $sth->execute($biblionumber);
2352 while (my $data=$sth->fetchrow_hashref){
2354 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2355 $isth->execute($data->{'itemnumber'});
2356 if (my $idata=$isth->fetchrow_hashref){
2357 $data->{borrowernumber} = $idata->{borrowernumber};
2358 $data->{cardnumber} = $idata->{cardnumber};
2359 $datedue = format_date($idata->{'date_due'});
2361 if ($datedue eq ''){
2362 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2368 #get branch information.....
2369 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2370 $bsth->execute($data->{'holdingbranch'});
2371 if (my $bdata=$bsth->fetchrow_hashref){
2372 $data->{'branchname'} = $bdata->{'branchname'};
2374 my $date=format_date($data->{'datelastseen'});
2375 $data->{'datelastseen'}=$date;
2376 $data->{'datedue'}=$datedue;
2377 # get notforloan complete status if applicable
2378 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2379 $sthnflstatus->execute;
2380 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2381 if ($authorised_valuecode) {
2382 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2383 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2384 my ($lib) = $sthnflstatus->fetchrow;
2385 $data->{notforloan} = $lib;
2396 ($count, @results) = &bibitems($biblionumber);
2398 Given the biblionumber for a book, C<&bibitems> looks up that book's
2399 biblioitems (different publications of the same book, the audio book
2400 and film versions, etc.).
2402 C<$count> is the number of elements in C<@results>.
2404 C<@results> is an array of references-to-hash; the keys are the fields
2405 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2406 addition, C<itemlost> indicates the availability of the item: if it is
2407 "2", then all copies of the item are long overdue; if it is "1", then
2408 all copies are lost; otherwise, there is at least one copy available.
2414 my $dbh = C4::Context->dbh;
2415 my $sth = $dbh->prepare("SELECT biblioitems.*,
2417 MIN(items.itemlost) as itemlost,
2418 MIN(items.dateaccessioned) as dateaccessioned
2419 FROM biblioitems, itemtypes, items
2420 WHERE biblioitems.biblionumber = ?
2421 AND biblioitems.itemtype = itemtypes.itemtype
2422 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2423 GROUP BY items.biblioitemnumber");
2426 $sth->execute($bibnum);
2427 while (my $data = $sth->fetchrow_hashref) {
2428 $results[$count] = $data;
2432 return($count, @results);
2438 $itemdata = &bibitemdata($biblioitemnumber);
2440 Looks up the biblioitem with the given biblioitemnumber. Returns a
2441 reference-to-hash. The keys are the fields from the C<biblio>,
2442 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2443 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2449 my $dbh = C4::Context->dbh;
2450 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");
2453 $sth->execute($bibitem);
2455 $data = $sth->fetchrow_hashref;
2462 =head2 getbibliofromitemnumber
2464 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2466 Looks up the item with the given itemnumber.
2468 C<$env> and C<$dbh> are ignored.
2470 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2471 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2476 sub getbibliofromitemnumber {
2477 my ($env,$dbh,$itemnumber) = @_;
2478 $dbh = C4::Context->dbh;
2479 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2480 where items.itemnumber = ?
2481 and biblio.biblionumber = items.biblionumber
2482 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2484 $sth->execute($itemnumber);
2485 my $data=$sth->fetchrow_hashref;
2492 @barcodes = &barcodes($biblioitemnumber);
2494 Given a biblioitemnumber, looks up the corresponding items.
2496 Returns an array of references-to-hash; the keys are C<barcode> and
2499 The returned items include very overdue items, but not lost ones.
2504 #called from request.pl
2505 my ($biblioitemnumber)=@_;
2506 my $dbh = C4::Context->dbh;
2507 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2508 WHERE biblioitemnumber = ?
2509 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2510 $sth->execute($biblioitemnumber);
2513 while (my $data=$sth->fetchrow_hashref){
2514 $barcodes[$i]=$data;
2524 $item = &itemdata($barcode);
2526 Looks up the item with the given barcode, and returns a
2527 reference-to-hash containing information about that item. The keys of
2528 the hash are the fields from the C<items> and C<biblioitems> tables in
2533 sub get_item_from_barcode {
2535 my $dbh = C4::Context->dbh;
2536 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2537 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2538 $sth->execute($barcode);
2539 my $data=$sth->fetchrow_hashref;
2547 @issues = &itemissues($biblioitemnumber, $biblio);
2549 Looks up information about who has borrowed the bookZ<>(s) with the
2550 given biblioitemnumber.
2552 C<$biblio> is ignored.
2554 C<&itemissues> returns an array of references-to-hash. The keys
2555 include the fields from the C<items> table in the Koha database.
2556 Additional keys include:
2562 If the item is currently on loan, this gives the due date.
2564 If the item is not on loan, then this is either "Available" or
2565 "Cancelled", if the item has been withdrawn.
2569 If the item is currently on loan, this gives the card number of the
2570 patron who currently has the item.
2572 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2574 These give the timestamp for the last three times the item was
2577 =item C<card0>, C<card1>, C<card2>
2579 The card number of the last three patrons who borrowed this item.
2581 =item C<borrower0>, C<borrower1>, C<borrower2>
2583 The borrower number of the last three patrons who borrowed this item.
2590 my ($bibitem, $biblio)=@_;
2591 my $dbh = C4::Context->dbh;
2592 # FIXME - If this function die()s, the script will abort, and the
2593 # user won't get anything; depending on how far the script has
2594 # gotten, the user might get a blank page. It would be much better
2595 # to at least print an error message. The easiest way to do this
2596 # is to set $SIG{__DIE__}.
2597 my $sth = $dbh->prepare("Select * from items where
2598 items.biblioitemnumber = ?")
2599 || die $dbh->errstr;
2603 $sth->execute($bibitem)
2604 || die $sth->errstr;
2606 while (my $data = $sth->fetchrow_hashref) {
2607 # Find out who currently has this item.
2608 # FIXME - Wouldn't it be better to do this as a left join of
2609 # some sort? Currently, this code assumes that if
2610 # fetchrow_hashref() fails, then the book is on the shelf.
2611 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2612 # database server crash), not just because no items match the
2614 my $sth2 = $dbh->prepare("select * from issues,borrowers
2615 where itemnumber = ?
2616 and returndate is NULL
2617 and issues.borrowernumber = borrowers.borrowernumber");
2619 $sth2->execute($data->{'itemnumber'});
2620 if (my $data2 = $sth2->fetchrow_hashref) {
2621 $data->{'date_due'} = $data2->{'date_due'};
2622 $data->{'card'} = $data2->{'cardnumber'};
2623 $data->{'borrower'} = $data2->{'borrowernumber'};
2625 if ($data->{'wthdrawn'} eq '1') {
2626 $data->{'date_due'} = 'Cancelled';
2628 $data->{'date_due'} = 'Available';
2634 # Find the last 3 people who borrowed this item.
2635 $sth2 = $dbh->prepare("select * from issues, borrowers
2636 where itemnumber = ?
2637 and issues.borrowernumber = borrowers.borrowernumber
2638 and returndate is not NULL
2639 order by returndate desc,timestamp desc") || die $dbh->errstr;
2640 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2641 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2642 if (my $data2 = $sth2->fetchrow_hashref) {
2643 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2644 $data->{"card$i2"} = $data2->{'cardnumber'};
2645 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2650 $results[$i] = $data;
2660 ($count, $subjects) = &getsubject($biblionumber);
2662 Looks up the subjects of the book with the given biblionumber. Returns
2663 a two-element list. C<$subjects> is a reference-to-array, where each
2664 element is a subject of the book, and C<$count> is the number of
2665 elements in C<$subjects>.
2671 my $dbh = C4::Context->dbh;
2672 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2673 $sth->execute($bibnum);
2676 while (my $data=$sth->fetchrow_hashref){
2681 return($i,\@results);
2686 ($count, $authors) = &getaddauthor($biblionumber);
2688 Looks up the additional authors for the book with the given
2691 Returns a two-element list. C<$authors> is a reference-to-array, where
2692 each element is an additional author, and C<$count> is the number of
2693 elements in C<$authors>.
2699 my $dbh = C4::Context->dbh;
2700 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2701 $sth->execute($bibnum);
2704 while (my $data=$sth->fetchrow_hashref){
2709 return($i,\@results);
2715 ($count, $subtitles) = &getsubtitle($biblionumber);
2717 Looks up the subtitles for the book with the given biblionumber.
2719 Returns a two-element list. C<$subtitles> is a reference-to-array,
2720 where each element is a subtitle, and C<$count> is the number of
2721 elements in C<$subtitles>.
2727 my $dbh = C4::Context->dbh;
2728 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2729 $sth->execute($bibnum);
2732 while (my $data=$sth->fetchrow_hashref){
2737 return($i,\@results);
2743 ($count, @websites) = &getwebsites($biblionumber);
2745 Looks up the web sites pertaining to the book with the given
2748 C<$count> is the number of elements in C<@websites>.
2750 C<@websites> is an array of references-to-hash; the keys are the
2751 fields from the C<websites> table in the Koha database.
2754 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2755 #(with add / modify / delete subs)
2758 my ($biblionumber) = @_;
2759 my $dbh = C4::Context->dbh;
2760 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2764 $sth->execute($biblionumber);
2765 while (my $data = $sth->fetchrow_hashref) {
2766 # FIXME - The URL scheme shouldn't be stripped off, at least
2767 # not here, since it's part of the URL, and will be useful in
2768 # constructing a link to the site. If you don't want the user
2769 # to see the "http://" part, strip that off when building the
2771 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2773 $results[$count] = $data;
2778 return($count, @results);
2781 =head2 getwebbiblioitems
2783 ($count, @results) = &getwebbiblioitems($biblionumber);
2785 Given a book's biblionumber, looks up the web versions of the book
2786 (biblioitems with itemtype C<WEB>).
2788 C<$count> is the number of items in C<@results>. C<@results> is an
2789 array of references-to-hash; the keys are the items from the
2790 C<biblioitems> table of the Koha database.
2794 sub getwebbiblioitems {
2795 my ($biblionumber) = @_;
2796 my $dbh = C4::Context->dbh;
2797 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2798 and itemtype = 'WEB'");
2802 $sth->execute($biblionumber);
2803 while (my $data = $sth->fetchrow_hashref) {
2804 $data->{'url'} =~ s/^http:\/\///;
2805 $results[$count] = $data;
2810 return($count, @results);
2811 } # sub getwebbiblioitems
2814 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2815 my $NSE = '\x89'; # NSE : Non Sorting Block end
2816 # handles non sorting blocks
2820 s/[ ]{0,1}$NSE/) /gm;
2827 my $dbh = C4::Context->dbh;
2828 my $result = MARCmarc2koha($dbh,$record,'');
2830 my ($biblionumber,$bibid,$title);
2831 # search duplicate on ISBN, easy and fast...
2832 if ($result->{isbn}) {
2833 $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=?");
2834 $sth->execute($result->{'isbn'});
2835 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2836 return $biblionumber,$bibid,$title if ($biblionumber);
2838 # a more complex search : build a request for SearchMarc::catalogsearch()
2839 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2840 # search on biblio.title
2841 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2842 if ($record->field($tag)) {
2843 if ($record->field($tag)->subfields($subfield)) {
2844 push @tags, "'".$tag.$subfield."'";
2845 push @and_or, "and";
2846 push @excluding, "";
2847 push @operator, "contains";
2848 push @value, $record->field($tag)->subfield($subfield);
2849 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2852 # ... and on biblio.author
2853 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2854 if ($record->field($tag)) {
2855 if ($record->field($tag)->subfields($subfield)) {
2856 push @tags, "'".$tag.$subfield."'";
2857 push @and_or, "and";
2858 push @excluding, "";
2859 push @operator, "contains";
2860 push @value, $record->field($tag)->subfield($subfield);
2861 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2864 # ... and on publicationyear.
2865 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2866 if ($record->field($tag)) {
2867 if ($record->field($tag)->subfields($subfield)) {
2868 push @tags, "'".$tag.$subfield."'";
2869 push @and_or, "and";
2870 push @excluding, "";
2871 push @operator, "=";
2872 push @value, $record->field($tag)->subfield($subfield);
2873 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2877 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2878 if ($record->field($tag)) {
2879 if ($record->field($tag)->subfields($subfield)) {
2880 push @tags, "'".$tag.$subfield."'";
2881 push @and_or, "and";
2882 push @excluding, "";
2883 push @operator, "=";
2884 push @value, $record->field($tag)->subfield($subfield);
2885 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2888 # ... and on publisher.
2889 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2890 if ($record->field($tag)) {
2891 if ($record->field($tag)->subfields($subfield)) {
2892 push @tags, "'".$tag.$subfield."'";
2893 push @and_or, "and";
2894 push @excluding, "";
2895 push @operator, "=";
2896 push @value, $record->field($tag)->subfield($subfield);
2897 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2900 # ... and on volume.
2901 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2902 if ($record->field($tag)) {
2903 if ($record->field($tag)->subfields($subfield)) {
2904 push @tags, "'".$tag.$subfield."'";
2905 push @and_or, "and";
2906 push @excluding, "";
2907 push @operator, "=";
2908 push @value, $record->field($tag)->subfield($subfield);
2909 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2913 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2914 # there is at least 1 result => return the 1st one
2916 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2917 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2919 # no result, returns nothing
2926 if(substr($isbn, 0, 1) <=7) {
2927 $seg1 = substr($isbn, 0, 1);
2928 } elsif(substr($isbn, 0, 2) <= 94) {
2929 $seg1 = substr($isbn, 0, 2);
2930 } elsif(substr($isbn, 0, 3) <= 995) {
2931 $seg1 = substr($isbn, 0, 3);
2932 } elsif(substr($isbn, 0, 4) <= 9989) {
2933 $seg1 = substr($isbn, 0, 4);
2935 $seg1 = substr($isbn, 0, 5);
2937 my $x = substr($isbn, length($seg1));
2939 if(substr($x, 0, 2) <= 19) {
2940 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2941 $seg2 = substr($x, 0, 2);
2942 } elsif(substr($x, 0, 3) <= 699) {
2943 $seg2 = substr($x, 0, 3);
2944 } elsif(substr($x, 0, 4) <= 8399) {
2945 $seg2 = substr($x, 0, 4);
2946 } elsif(substr($x, 0, 5) <= 89999) {
2947 $seg2 = substr($x, 0, 5);
2948 } elsif(substr($x, 0, 6) <= 9499999) {
2949 $seg2 = substr($x, 0, 6);
2951 $seg2 = substr($x, 0, 7);
2953 my $seg3=substr($x,length($seg2));
2954 $seg3=substr($seg3,0,length($seg3)-1) ;
2955 my $seg4 = substr($x, -1, 1);
2956 return "$seg1-$seg2-$seg3-$seg4";
2960 END { } # module clean-up code here (global destructor)
2966 Koha Developement team <info@koha.org>
2968 Paul POULAIN paul.poulain@free.fr
2974 # Revision 1.154 2006/02/26 00:08:20 kados
2975 # moving all $Zconn s to z3950_extended_services (currently, nothing
2978 # Revision 1.153 2006/02/25 22:39:10 kados
2979 # Another purely documentation commit. Just changing formatting to ease
2982 # Revision 1.152 2006/02/25 21:17:20 kados
2983 # Purely documentation change: converted all =head2 entries to use function
2984 # name as title rather than usage as title
2986 # Revision 1.151 2006/02/25 21:02:20 kados
2988 # Further cleanup, convering new routines to 4-chars
2990 # Revision 1.150 2006/02/25 20:49:15 kados
2991 # Better documentation, added warning if serviceType is 'drop' since it's
2992 # not supported in Zebra.
2994 # Revision 1.149 2006/02/25 20:30:32 kados
2995 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
2996 # longer necessary. If we need to convert from MARC-8 for display, we should:
2999 # 2. do it with MARC::Charset
3001 # If you still need it, let me know and I'll put it back in.
3003 # Revision 1.148 2006/02/25 19:23:01 kados
3004 # cleaning up POD docs, deleting zebra_create as it's no longer used (
3005 # replaced by z3950_extended_services).
3007 # Revision 1.147 2006/02/25 19:09:59 kados
3008 # readding some lost subs
3010 # Revision 1.145 2006/02/22 01:02:39 kados
3011 # Replacing all calls to zebra_update with calls to
3012 # z3950_extended_services. More work coming, but it's
3015 # Revision 1.144 2006/02/20 14:22:38 kados
3018 # Revision 1.143 2006/02/20 13:26:11 kados
3019 # A new subroutine to handle Z39.50 extended services. You pass it a
3020 # connection object, service type, service options, and a record, and
3021 # it performs the service and handles any exception found.
3023 # Revision 1.142 2006/02/16 20:49:56 kados
3024 # destroy a connection after we're done -- we really should just have one
3025 # connection object and not destroy it until the whole transaction is
3026 # finished -- but this will do for now
3028 # Revision 1.141 2006/02/16 19:47:22 rangi
3029 # Trying to error trap a little more.
3031 # Revision 1.140 2006/02/14 21:36:03 kados
3032 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3033 # also adding diagnostic error if not able to connect to Zebra
3035 # Revision 1.139 2006/02/14 19:53:25 rangi
3036 # Just a little missing my
3038 # Seems to be working great Paul, and I like what you did with zebradb
3040 # Revision 1.138 2006/02/14 11:25:22 tipaul
3041 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3043 # Revision 1.137 2006/02/13 16:34:26 tipaul
3044 # fixing some warnings (perl -w should be quiet)
3046 # Revision 1.136 2006/01/10 17:01:29 tipaul
3047 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3049 # Revision 1.135 2006/01/06 16:39:37 tipaul
3050 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3051 # Seems not to break too many things, but i'm probably wrong here.
3052 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3054 # - removing useless directories (koha-html and koha-plucene)
3056 # Revision 1.134 2006/01/04 15:54:55 tipaul
3057 # utf8 is a : go for beta test in HEAD.
3058 # some explanations :
3059 # - 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.
3060 # - *-top.inc will show the pages in utf8
3061 # - 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.
3062 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3064 # Revision 1.133 2005/12/12 14:25:51 thd
3067 # Reverse array filled with elements from repeated subfields
3068 # to avoid last to first concatenation of elements in Koha DB.-
3070 # Revision 1.132 2005-10-26 09:12:33 tipaul
3071 # big commit, still breaking things...
3073 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3074 # * code cleaning (cleaning warnings from perl -w) continued
3076 # Revision 1.131 2005/09/22 10:01:45 tipaul
3077 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3079 # Revision 1.130 2005/09/02 14:34:14 tipaul
3080 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3081 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3082 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3084 # Revision 1.129 2005/08/12 13:50:31 tipaul
3085 # removing useless sub declarations
3087 # Revision 1.128 2005/08/11 16:12:47 tipaul
3088 # Playing with the zebra...
3090 # * go to koha cvs home directory
3091 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3092 # * put your zebra.cfg files here & create your database.
3093 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3094 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3097 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3098 # * deletion still not work
3099 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3101 # recordId: (bib1,Local-number)
3105 # elm 090 Local-number -
3106 # elm 090/? Local-number -
3107 # elm 090/?/9 Local-number !:w
3109 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3111 # Revision 1.127 2005/08/11 14:37:32 tipaul
3113 # * removing useless subs
3114 # * removing some subs that are also elsewhere
3115 # * 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)
3117 # Revision 1.126 2005/08/11 09:13:28 tipaul
3118 # just removing useless subs (a lot !!!) for code cleaning
3120 # Revision 1.125 2005/08/11 09:00:07 tipaul
3121 # Ok guys, this time, it seems that item add and modif begin working as expected...
3122 # Still a lot of bugs to fix, of course
3124 # Revision 1.124 2005/08/10 10:21:15 tipaul
3125 # continuing the road to zebra :
3126 # - the biblio add begins to work.
3127 # - the biblio modif begins to work.
3129 # (still without doing anything on zebra)
3130 # (no new change in updatedatabase)
3132 # Revision 1.123 2005/08/09 14:10:28 tipaul
3133 # 1st commit to go to zebra.
3134 # don't update your cvs if you want to have a working head...
3136 # this commit contains :
3137 # * 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...
3138 # * 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.
3139 # * other files : get rid of bibid and use biblionumber instead.
3142 # * does not do anything on zebra yet.
3143 # * if you rename marc_subfield_table, you can't search anymore.
3144 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3145 # * 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 ;-) )
3147 # 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
3148 # 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.
3150 # tipaul cutted previous commit notes