3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA 02111-1307 USA
26 use MARC::File::USMARC;
30 use vars qw($VERSION @ISA @EXPORT);
32 # set the version for version checking
33 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
34 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
39 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
40 # as the old-style API and the NEW one are the only public functions.
43 &newbiblio &newbiblioitem
44 &newsubject &newsubtitle &newitems
46 &modbiblio &checkitems &modbibitem
47 &modsubtitle &modsubject &modaddauthor &moditem
49 &delitem &deletebiblioitem &delbiblio
51 &getbiblio &bibdata &bibitems &bibitemdata
52 &barcodes &ItemInfo &itemdata &itemissues &itemcount
53 &getsubject &getaddauthor &getsubtitle
54 &getwebbiblioitems &getwebsites
55 &getbiblioitembybiblionumber
56 &getbiblioitem &getitemsbybiblioitem
58 &MARCfind_marc_from_kohafield
59 &MARCfind_frameworkcode
60 &find_biblioitemnumber
63 &NEWnewbiblio &NEWnewitem
64 &NEWmodbiblio &NEWmoditem
65 &NEWdelbiblio &NEWdelitem
66 &NEWmodbiblioframework
68 &MARCkoha2marcBiblio &MARCmarc2koha
69 &MARCkoha2marcItem &MARChtml2marc
70 &MARCgetbiblio &MARCgetitem
76 &z3950_extended_services
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.
150 =head3 z3950_extended_services
152 z3950_extended_services($Zconn,$serviceType,$serviceOptions,$record);
154 z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
156 C<$Zconn> a connection object to the Zebra server
158 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
160 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
162 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
166 recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
167 syntax => the record syntax (transfer syntax)
168 databaseName = Database from connection object
170 To set serviceOptions, call set_service_options($serviceType)
172 C<$record> the record, if one is needed for the service type
174 A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
177 sub z3950_extended_services {
178 my ($Zconn,$serviceType,$serviceOptions,$record) = @_;
180 # create a new package object
181 my $Zpackage = $Zconn->package();
184 $Zpackage->option(action => $serviceOptions->{'action'});
186 if ($serviceOptions->{'databaseName'}) {
187 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
189 if ($serviceOptions->{'recordIdNumber'}) {
190 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
192 if ($serviceOptions->{'recordIdOpaque'}) {
193 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
196 # this is an ILL request (Zebra doesn't support it)
197 if ($serviceType eq 'itemorder') {
198 $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
199 $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
200 $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
201 $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
205 my $xmlrecord = marc2xml($record);
206 $Zpackage->option(record => $xmlrecord);
207 if ($serviceOptions->{'syntax'}) {
208 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
212 # send the request, handle any exception encountered
213 eval { $Zpackage->send($serviceType) };
214 if ($@ && $@->isa("ZOOM::Exception")) {
215 print "Oops! ", $@->message(), "\n";
218 # free up package resources
219 $Zpackage->destroy();
222 =head2 set_service_options
224 my $serviceOptions = set_service_options($serviceType);
226 C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
228 Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
232 sub set_service_options {
233 my ($serviceType) = @_;
236 if ($serviceType eq 'update') {
237 $serviceOptions->{ 'action' } = 'specialUpdate';
239 # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
240 # $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
243 if ($serviceType eq 'commit') {
248 if ($serviceType eq 'create') {
253 if (serviceType eq 'drop') {
254 die "ERROR: 'drop' not currently supported (by Zebra)";
256 return $serviceOptions;
261 my $xmlrecord = marc2xml($record);
263 Convert from MARC to XML. Note that MARC::File::XML will automatically encode from MARC-8 to UTF-8 as of version .8
265 C<$record> a MARC record
273 $xmlrecord=$record->as_xml();
275 #TODO: better error handling here
277 warn "ERROR: I suspect a badly formatted MARC record";
282 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
286 2nd param is 1 for liblibrarian and 0 for libopac
287 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
289 returns a hash with all values for all fields and subfields for a given MARC framework :
290 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
292 ->{mandatory} = $mandatory;
293 ->{repeatable} = $repeatable;
294 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
296 ->{mandatory} = $mandatory;
297 ->{repeatable} = $repeatable;
298 ->{authorised_value} = $authorised_value;
299 ->{authtypecode} = $authtypecode;
300 ->{value_builder} = $value_builder;
301 ->{kohafield} = $kohafield;
302 ->{seealso} = $seealso;
303 ->{hidden} = $hidden;
312 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
313 $frameworkcode = "" unless $frameworkcode;
314 $forlibrarian = 1 unless $forlibrarian;
316 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
318 # check that framework exists
321 "select count(*) from marc_tag_structure where frameworkcode=?");
322 $sth->execute($frameworkcode);
323 my ($total) = $sth->fetchrow;
324 $frameworkcode = "" unless ( $total > 0 );
327 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
329 $sth->execute($frameworkcode);
330 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
332 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
333 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
334 $res->{$tag}->{tab} = ""; # XXX
335 $res->{$tag}->{mandatory} = $mandatory;
336 $res->{$tag}->{repeatable} = $repeatable;
341 "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"
343 $sth->execute($frameworkcode);
346 my $authorised_value;
356 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
357 $mandatory, $repeatable, $authorised_value, $authtypecode,
358 $value_builder, $kohafield, $seealso, $hidden,
363 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
364 $res->{$tag}->{$subfield}->{tab} = $tab;
365 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
366 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
367 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
368 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
369 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
370 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
371 $res->{$tag}->{$subfield}->{seealso} = $seealso;
372 $res->{$tag}->{$subfield}->{hidden} = $hidden;
373 $res->{$tag}->{$subfield}->{isurl} = $isurl;
374 $res->{$tag}->{$subfield}->{link} = $link;
379 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
383 finds MARC tag and subfield for a given kohafield
384 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
390 sub MARCfind_marc_from_kohafield {
391 my ( $dbh, $kohafield,$frameworkcode ) = @_;
392 return 0, 0 unless $kohafield;
393 $frameworkcode='' unless $frameworkcode;
394 my $relations = C4::Context->marcfromkohafield;
395 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
398 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
402 Returns a MARC::Record for the biblio $biblionumber.
408 # Returns MARC::Record of the biblio passed in parameter.
409 my ( $dbh, $biblionumber ) = @_;
410 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
411 $sth->execute($biblionumber);
412 my ($marc) = $sth->fetchrow;
413 my $record = MARC::Record::new_from_usmarc($marc);
417 =head2 $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";
437 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
441 Returns a MARC::Record with all items of biblio # $biblionumber
449 my ( $dbh, $biblionumber, $itemnumber ) = @_;
450 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
451 # get the complete MARC record
452 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
453 $sth->execute($biblionumber);
454 my ($rawmarc) = $sth->fetchrow;
455 my $record = MARC::File::USMARC::decode($rawmarc);
456 # now, find the relevant itemnumber
457 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
458 # prepare the new item record
459 my $itemrecord = MARC::Record->new();
460 # parse all fields fields from the complete record
461 foreach ($record->field($itemnumberfield)) {
462 # when the item field is found, save it
463 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
464 $itemrecord->append_fields($_);
471 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
475 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
476 This sub is useless when MARC=OFF
481 sub find_biblioitemnumber {
482 my ( $dbh, $biblionumber ) = @_;
483 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
484 $sth->execute($biblionumber);
485 my ($biblioitemnumber) = $sth->fetchrow;
486 return $biblioitemnumber;
489 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
493 returns the framework of a given biblio
499 sub MARCfind_frameworkcode {
500 my ( $dbh, $biblionumber ) = @_;
501 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
502 $sth->execute($biblionumber);
503 my ($frameworkcode) = $sth->fetchrow;
504 return $frameworkcode;
507 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
511 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
512 all entries of the hash are transformed into their matching MARC field/subfield.
518 sub MARCkoha2marcBiblio {
520 # this function builds partial MARC::Record from the old koha-DB fields
521 my ( $dbh, $bibliohash ) = @_;
522 # we don't have biblio entries in the hash, so we add them first
523 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
524 $sth->execute($bibliohash->{biblionumber});
525 my $biblio = $sth->fetchrow_hashref;
526 foreach (keys %$biblio) {
527 $bibliohash->{$_}=$biblio->{$_};
529 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
530 my $record = MARC::Record->new();
531 foreach ( keys %$bibliohash ) {
532 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
533 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
536 # other fields => additional authors, subjects, subtitles
537 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
538 $sth2->execute($bibliohash->{biblionumber});
539 while ( my $row = $sth2->fetchrow_hashref ) {
540 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
542 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
543 $sth2->execute($bibliohash->{biblionumber});
544 while ( my $row = $sth2->fetchrow_hashref ) {
545 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
547 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
548 $sth2->execute($bibliohash->{biblionumber});
549 while ( my $row = $sth2->fetchrow_hashref ) {
550 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
556 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
558 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
559 all entries of the hash are transformed into their matching MARC field/subfield.
567 sub MARCkoha2marcItem {
569 # this function builds partial MARC::Record from the old koha-DB fields
570 my ( $dbh, $item ) = @_;
572 # my $dbh=&C4Connect;
573 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
574 my $record = MARC::Record->new();
576 foreach( keys %$item ) {
578 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
585 =head2 MARCkoha2marcOnefield
589 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
595 sub MARCkoha2marcOnefield {
596 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
599 $sth->execute($frameworkcode,$kohafieldname);
600 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
601 if ( $record->field($tagfield) ) {
602 my $tag = $record->field($tagfield);
604 $tag->add_subfields( $tagsubfield, $value );
605 $record->delete_field($tag);
606 $record->add_fields($tag);
610 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
616 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
620 transforms the parameters (coming from HTML form) into a MARC::Record
621 parameters with r are references to arrays.
623 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
630 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
632 my $record = MARC::Record->new();
633 # my %subfieldlist=();
634 my $prevvalue; # if tag <10
635 my $field; # if tag >=10
636 for (my $i=0; $i< @$rtags; $i++) {
637 next unless @$rvalues[$i];
638 # rebuild MARC::Record
639 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
640 if (@$rtags[$i] ne $prevtag) {
643 if ($prevtag ne '000') {
644 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
646 $record->leader($prevvalue);
651 $record->add_fields($field);
654 $indicators{@$rtags[$i]}.=' ';
655 if (@$rtags[$i] <10) {
656 $prevvalue= @$rvalues[$i];
660 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
661 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
663 $prevtag = @$rtags[$i];
665 if (@$rtags[$i] <10) {
666 $prevvalue=@$rvalues[$i];
668 if (length(@$rvalues[$i])>0) {
669 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
670 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
673 $prevtag= @$rtags[$i];
676 # the last has not been included inside the loop... do it now !
677 $record->add_fields($field) if $field;
678 # warn "HTML2MARC=".$record->as_formatted;
683 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
687 builds a hash with old-db datas from a MARC::Record
694 my ($dbh,$record,$frameworkcode) = @_;
695 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
697 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
700 while (($field)=$sth2->fetchrow) {
701 # warn "biblio.".$field;
702 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
704 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
706 while (($field)=$sth2->fetchrow) {
707 if ($field eq 'notes') { $field = 'bnotes'; }
708 # warn "biblioitems".$field;
709 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
711 $sth2=$dbh->prepare("SHOW COLUMNS from items");
713 while (($field)=$sth2->fetchrow) {
714 # warn "items".$field;
715 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
717 # additional authors : specific
718 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
719 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
720 # modify copyrightdate to keep only the 1st year found
721 my $temp = $result->{'copyrightdate'};
723 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
725 $result->{'copyrightdate'} = $1;
726 } else { # if no cYYYY, get the 1st date.
727 $temp =~ m/(\d\d\d\d)/;
728 $result->{'copyrightdate'} = $1;
731 # modify publicationyear to keep only the 1st year found
732 $temp = $result->{'publicationyear'};
733 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
735 $result->{'publicationyear'} = $1;
736 } else { # if no cYYYY, get the 1st date.
737 $temp =~ m/(\d\d\d\d)/;
738 $result->{'publicationyear'} = $1;
743 sub MARCmarc2kohaOneField {
745 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
746 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
747 # warn "kohatable / $kohafield / $result / ";
751 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
752 foreach my $field ( $record->field($tagfield) ) {
753 if ($field->tag()<10) {
754 if ($result->{$kohafield}) {
755 # Reverse array filled with elements from repeated subfields
756 # from first to last to avoid last to first concatenation of
757 # elements in Koha DB. -- thd.
758 $result->{$kohafield} .= " | ".reverse($field->data());
760 $result->{$kohafield} = $field->data();
763 if ( $field->subfields ) {
764 my @subfields = $field->subfields();
765 foreach my $subfieldcount ( 0 .. $#subfields ) {
766 if ($subfields[$subfieldcount][0] eq $subfield) {
767 if ( $result->{$kohafield} ) {
768 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
771 $result->{$kohafield} = $subfields[$subfieldcount][1];
778 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
782 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
786 creates a biblio from a MARC::Record.
793 my ( $dbh,$Zconn,$record,$frameworkcode ) = @_;
795 my $biblioitemnumber;
796 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
797 $olddata->{frameworkcode} = $frameworkcode;
798 $biblionumber = REALnewbiblio( $dbh, $olddata );
799 $olddata->{biblionumber} = $biblionumber;
800 # add biblionumber into the MARC record (it's the ID for zebra)
801 my ( $tagfield, $tagsubfield ) =
802 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
806 $newfield = MARC::Field->new(
807 $tagfield, $biblionumber,
810 $newfield = MARC::Field->new(
811 $tagfield, '', '', "$tagsubfield" => $biblionumber,
814 # drop old field (just in case it already exist and create new one...
815 my $old_field = $record->field($tagfield);
816 $record->delete_field($old_field);
817 $record->add_fields($newfield);
819 #create the marc entry, that stores the rax marc record in Koha 3.0
820 $olddata->{marc} = $record->as_usmarc();
821 $olddata->{marcxml} = $record->as_xml();
822 # and create biblioitem, that's all folks !
823 $biblioitemnumber = REALnewbiblioitem( $dbh, $Zconn, $olddata );
825 # search subtiles, addiauthors and subjects
826 ( $tagfield, $tagsubfield ) =
827 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
828 my @addiauthfields = $record->field($tagfield);
829 foreach my $addiauthfield (@addiauthfields) {
830 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
831 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
832 REALmodaddauthor( $dbh, $biblionumber,
833 $addiauthsubfields[$subfieldcount] );
836 ( $tagfield, $tagsubfield ) =
837 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
838 my @subtitlefields = $record->field($tagfield);
839 foreach my $subtitlefield (@subtitlefields) {
840 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
841 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
842 REALnewsubtitle( $dbh, $biblionumber,
843 $subtitlesubfields[$subfieldcount] );
846 ( $tagfield, $tagsubfield ) =
847 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
848 my @subj = $record->field($tagfield);
850 foreach my $subject (@subj) {
851 my @subjsubfield = $subject->subfield($tagsubfield);
852 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
853 push @subjects, $subjsubfield[$subfieldcount];
856 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
857 return ( $biblionumber, $biblioitemnumber );
860 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
864 modify the framework of a biblio
870 sub NEWmodbiblioframework {
871 my ($dbh,$biblionumber,$frameworkcode) =@_;
872 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
873 $sth->execute($frameworkcode,$biblionumber);
877 =head2 NEWmodbiblio($dbh,$Zconn,$MARCrecord,$biblionumber,$frameworkcode);
881 modify a biblio (MARC=ON)
888 my ($dbh,$Zconn,$record,$biblionumber,$frameworkcode) =@_;
889 $frameworkcode="" unless $frameworkcode;
890 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
891 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
893 $oldbiblio->{frameworkcode} = $frameworkcode;
894 #create the marc entry, that stores the rax marc record in Koha 3.0
895 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
896 $oldbiblio->{marc} = $record->as_usmarc();
897 $oldbiblio->{marcxml} = $record->as_xml();
898 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
899 REALmodbiblio($dbh,$oldbiblio);
900 REALmodbiblioitem($dbh,$Zconn,$oldbiblio);
901 # now, modify addi authors, subject, addititles.
902 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
903 my @addiauthfields = $record->field($tagfield);
904 foreach my $addiauthfield (@addiauthfields) {
905 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
906 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
907 foreach my $subfieldcount (0..$#addiauthsubfields) {
908 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
911 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
912 my @subtitlefields = $record->field($tagfield);
913 foreach my $subtitlefield (@subtitlefields) {
914 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
915 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
917 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
918 foreach my $subfieldcount (0..$#subtitlesubfields) {
919 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
920 REALnewsubtitle($dbh,$biblionumber,$subtit);
924 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
925 my @subj = $record->field($tagfield);
927 foreach my $subject (@subj) {
928 my @subjsubfield = $subject->subfield($tagsubfield);
929 foreach my $subfieldcount (0..$#subjsubfield) {
930 push @subjects,$subjsubfield[$subfieldcount];
933 REALmodsubject($dbh,$biblionumber,1,@subjects);
937 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
948 my ( $dbh, $bibid ) = @_;
949 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
950 &REALdelbiblio( $dbh, $biblio );
953 "select biblioitemnumber from biblioitems where biblionumber=?");
954 $sth->execute($biblio);
955 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
956 REALdelbiblioitem( $dbh, $biblioitemnumber );
958 &MARCdelbiblio( $dbh, $bibid, 0 );
961 =head2 $itemnumber = NEWnewitem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber);
965 creates an item from a MARC::Record
972 my ( $dbh,$Zconn,$record,$biblionumber,$biblioitemnumber ) = @_;
975 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
976 my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
977 # needs old biblionumber and biblioitemnumber
978 $item->{'biblionumber'} = $biblionumber;
979 $item->{'biblioitemnumber'}=$biblioitemnumber;
980 $item->{marc} = $record->as_usmarc();
982 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $Zconn, $item, $item->{barcode} );
987 =head2 $itemnumber = NEWmoditem($dbh, $Zconn, $record, $biblionumber, $biblioitemnumber,$itemnumber);
998 my ( $dbh, $Zconn, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1000 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1001 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1003 $olditem->{marc} = $record->as_usmarc();
1004 $olditem->{biblionumber} = $biblionumber;
1005 $olditem->{biblioitemnumber} = $biblioitemnumber;
1007 REALmoditem( $dbh, $Zconn, $olditem );
1011 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1022 my ( $dbh, $bibid, $itemnumber ) = @_;
1023 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1024 &REALdelitem( $dbh, $itemnumber );
1025 &MARCdelitem( $dbh, $bibid, $itemnumber );
1029 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
1033 adds a record in biblio table. Datas are in the hash $biblio.
1040 my ( $dbh, $biblio ) = @_;
1042 $dbh->do('lock tables biblio WRITE');
1043 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1045 my $data = $sth->fetchrow_arrayref;
1046 my $bibnum = $$data[0] + 1;
1049 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1052 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1053 serial=?, seriestitle=?, notes=?, abstract=?,
1057 $bibnum, $biblio->{'title'},
1058 $biblio->{'author'}, $biblio->{'copyrightdate'},
1059 $biblio->{'serial'}, $biblio->{'seriestitle'},
1060 $biblio->{'notes'}, $biblio->{'abstract'},
1061 $biblio->{'unititle'}
1065 $dbh->do('unlock tables');
1069 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
1073 modify a record in biblio table. Datas are in the hash $biblio.
1080 my ( $dbh, $biblio ) = @_;
1081 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1082 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1083 where biblionumber = ?"
1086 $biblio->{'title'}, $biblio->{'author'},
1087 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1088 $biblio->{'seriestitle'}, $biblio->{'serial'},
1089 $biblio->{'unititle'}, $biblio->{'notes'},
1090 $biblio->{frameworkcode},
1091 $biblio->{'biblionumber'}
1094 return ( $biblio->{'biblionumber'} );
1097 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
1101 modify subtitles in bibliosubtitle table.
1107 sub REALmodsubtitle {
1108 my ( $dbh, $bibnum, $subtitle ) = @_;
1111 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1112 $sth->execute( $subtitle, $bibnum );
1116 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1120 adds or modify additional authors
1121 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1127 sub REALmodaddauthor {
1128 my ( $dbh, $bibnum, @authors ) = @_;
1130 # my $dbh = C4Connect;
1132 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1134 $sth->execute($bibnum);
1136 foreach my $author (@authors) {
1137 if ( $author ne '' ) {
1140 "Insert into additionalauthors set author = ?, biblionumber = ?"
1143 $sth->execute( $author, $bibnum );
1148 } # sub modaddauthor
1150 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1154 modify/adds subjects
1159 sub REALmodsubject {
1160 my ( $dbh, $bibnum, $force, @subject ) = @_;
1162 # my $dbh = C4Connect;
1163 my $count = @subject;
1165 for ( my $i = 0 ; $i < $count ; $i++ ) {
1166 $subject[$i] =~ s/^ //g;
1167 $subject[$i] =~ s/ $//g;
1170 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1172 $sth->execute( $subject[$i] );
1174 if ( my $data = $sth->fetchrow_hashref ) {
1177 if ( $force eq $subject[$i] || $force == 1 ) {
1179 # subject not in aut, chosen to force anway
1180 # so insert into cataloguentry so its in auth file
1183 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1186 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1191 "$subject[$i]\n does not exist in the subject authority file";
1194 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1196 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1198 while ( my $data = $sth2->fetchrow_hashref ) {
1199 $error .= "<br>$data->{'catalogueentry'}";
1208 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1209 $sth->execute($bibnum);
1213 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1215 foreach $query (@subject) {
1216 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1225 =head2 REALmodbiblioitem($dbh, $biblioitem);
1234 sub REALmodbiblioitem {
1235 my ( $dbh, $Zconn, $biblioitem ) = @_;
1238 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1239 itemtype=?, url=?, isbn=?, issn=?,
1240 publishercode=?, publicationyear=?, classification=?, dewey=?,
1241 subclass=?, illus=?, pages=?, volumeddesc=?,
1242 notes=?, size=?, place=?, marc=?,
1244 where biblioitemnumber=?");
1245 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1246 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1247 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1248 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1249 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1250 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1251 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1253 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1254 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1255 #z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1258 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1261 =head2 REALnewbiblioitem($dbh,$Zconn,$biblioitem);
1265 adds a biblioitem ($biblioitem is a hash with the values)
1271 sub REALnewbiblioitem {
1272 my ( $dbh, $Zconn, $biblioitem ) = @_;
1274 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1275 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1277 my $biblioitemnumber;
1280 $data = $sth->fetchrow_arrayref;
1281 $biblioitemnumber = $$data[0] + 1;
1283 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1284 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1285 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1286 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1287 my $field=$record->field($biblioitemnumberfield);
1288 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1289 $biblioitem->{marc} = $record->as_usmarc();
1290 $biblioitem->{marcxml} = $record->as_xml();
1292 $sth = $dbh->prepare( "insert into biblioitems set
1293 biblioitemnumber = ?, biblionumber = ?,
1294 volume = ?, number = ?,
1295 classification = ?, itemtype = ?,
1297 issn = ?, dewey = ?,
1298 subclass = ?, publicationyear = ?,
1299 publishercode = ?, volumedate = ?,
1300 volumeddesc = ?, illus = ?,
1301 pages = ?, notes = ?,
1303 marc = ?, place = ?,
1307 $biblioitemnumber, $biblioitem->{'biblionumber'},
1308 $biblioitem->{'volume'}, $biblioitem->{'number'},
1309 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1310 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1311 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1312 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1313 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1314 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1315 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1316 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1317 $biblioitem->{'marc'}, $biblioitem->{'place'},
1318 $biblioitem->{marcxml},
1320 $dbh->do("unlock tables");
1321 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1322 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1323 #z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1324 #zebra_create($biblioitem->{biblionumber}, $record);
1325 return ($biblioitemnumber);
1328 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1332 create a new subtitle
1337 sub REALnewsubtitle {
1338 my ( $dbh, $bibnum, $subtitle ) = @_;
1341 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1342 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1346 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$Zconn,$item,$barcode);
1350 create a item. $item is a hash and $barcode the barcode.
1357 my ( $dbh, $Zconn,$item, $barcode ) = @_;
1359 # warn "OLDNEWITEMS";
1361 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1362 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1367 $data = $sth->fetchrow_hashref;
1368 $itemnumber = $data->{'max(itemnumber)'} + 1;
1370 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1371 if ( $item->{'loan'} ) {
1372 $item->{'notforloan'} = $item->{'loan'};
1374 $item->{'biblioitemnumber'} = 1;
1375 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1376 if ( $item->{'dateaccessioned'} ) {
1377 $sth = $dbh->prepare( "Insert into items set
1378 itemnumber = ?, biblionumber = ?,
1379 multivolumepart = ?,
1380 biblioitemnumber = ?, barcode = ?,
1381 booksellerid = ?, dateaccessioned = ?,
1382 homebranch = ?, holdingbranch = ?,
1383 price = ?, replacementprice = ?,
1384 replacementpricedate = NOW(), datelastseen = NOW(),
1385 multivolume = ?, stack = ?,
1386 itemlost = ?, wthdrawn = ?,
1387 paidfor = ?, itemnotes = ?,
1388 itemcallnumber =?, notforloan = ?,
1393 $itemnumber, $item->{'biblionumber'},
1394 $item->{'multivolumepart'},
1395 $item->{'biblioitemnumber'},$item->{barcode},
1396 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1397 $item->{'homebranch'}, $item->{'holdingbranch'},
1398 $item->{'price'}, $item->{'replacementprice'},
1399 $item->{multivolume}, $item->{stack},
1400 $item->{itemlost}, $item->{wthdrawn},
1401 $item->{paidfor}, $item->{'itemnotes'},
1402 $item->{'itemcallnumber'}, $item->{'notforloan'},
1405 if ( defined $sth->errstr ) {
1406 $error .= $sth->errstr;
1410 $sth = $dbh->prepare( "Insert into items set
1411 itemnumber = ?, biblionumber = ?,
1412 multivolumepart = ?,
1413 biblioitemnumber = ?, barcode = ?,
1414 booksellerid = ?, dateaccessioned = NOW(),
1415 homebranch = ?, holdingbranch = ?,
1416 price = ?, replacementprice = ?,
1417 replacementpricedate = NOW(), datelastseen = NOW(),
1418 multivolume = ?, stack = ?,
1419 itemlost = ?, wthdrawn = ?,
1420 paidfor = ?, itemnotes = ?,
1421 itemcallnumber =?, notforloan = ?,
1426 $itemnumber, $item->{'biblionumber'},
1427 $item->{'multivolumepart'},
1428 $item->{'biblioitemnumber'},$item->{barcode},
1429 $item->{'booksellerid'},
1430 $item->{'homebranch'}, $item->{'holdingbranch'},
1431 $item->{'price'}, $item->{'replacementprice'},
1432 $item->{multivolume}, $item->{stack},
1433 $item->{itemlost}, $item->{wthdrawn},
1434 $item->{paidfor}, $item->{'itemnotes'},
1435 $item->{'itemcallnumber'}, $item->{'notforloan'},
1438 if ( defined $sth->errstr ) {
1439 $error .= $sth->errstr;
1442 # item stored, now, deal with the marc part...
1443 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1444 where biblio.biblionumber=biblioitems.biblionumber and
1445 biblio.biblionumber=?");
1446 $sth->execute($item->{biblionumber});
1447 if ( defined $sth->errstr ) {
1448 $error .= $sth->errstr;
1450 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1451 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1452 my $record = MARC::File::USMARC::decode($rawmarc);
1453 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1454 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1455 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1457 warn $itemnumberfield;
1458 warn $itemrecord->field($itemnumberfield);
1459 my $itemfield = $itemrecord->field($itemnumberfield);
1460 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1461 $record->insert_grouped_field($itemfield);
1462 # save the record into biblioitem
1463 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1464 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1465 if ( defined $sth->errstr ) {
1466 $error .= $sth->errstr;
1468 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1469 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1470 # z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1471 #zebra_create($item->{biblionumber},$record);
1472 $dbh->do('unlock tables');
1473 return ( $itemnumber, $error );
1476 =head2 REALmoditem($dbh,$Zconn,$item);
1487 my ( $dbh, $Zconn, $item ) = @_;
1488 $item->{'bibitemnum'} = 1;
1490 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1491 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1492 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1494 $item->{'barcode'}, $item->{'itemnotes'},
1495 $item->{'itemcallnumber'}, $item->{'notforloan'},
1496 $item->{'location'}, $item->{multivolumepart},
1497 $item->{multivolume}, $item->{stack},
1500 if ( $item->{'lost'} ne '' ) {
1501 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1502 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1503 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1505 $item->{'bibitemnum'}, $item->{'barcode'},
1506 $item->{'itemnotes'}, $item->{'homebranch'},
1507 $item->{'lost'}, $item->{'wthdrawn'},
1508 $item->{'itemcallnumber'}, $item->{'notforloan'},
1509 $item->{'location'}, $item->{multivolumepart},
1510 $item->{multivolume}, $item->{stack},
1513 if ($item->{homebranch}) {
1514 $query.=",homebranch=?";
1515 push @bind, $item->{homebranch};
1517 if ($item->{holdingbranch}) {
1518 $query.=",holdingbranch=?";
1519 push @bind, $item->{holdingbranch};
1522 $query.=" where itemnumber=?";
1523 push @bind,$item->{'itemnum'};
1524 if ( $item->{'replacement'} ne '' ) {
1525 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1527 my $sth = $dbh->prepare($query);
1528 $sth->execute(@bind);
1530 # item stored, now, deal with the marc part...
1531 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1532 where biblio.biblionumber=biblioitems.biblionumber and
1533 biblio.biblionumber=? and
1534 biblioitems.biblioitemnumber=?");
1535 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1536 if ( defined $sth->errstr ) {
1537 $error .= $sth->errstr;
1539 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1540 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1541 my $record = MARC::File::USMARC::decode($rawmarc);
1542 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1543 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1544 # prepare the new item record
1545 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1546 my $itemfield = $itemrecord->field($itemnumberfield);
1547 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1548 # parse all fields fields from the complete record
1549 foreach ($record->field($itemnumberfield)) {
1550 # when the previous field is found, replace by the new one
1551 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1552 $_->replace_with($itemfield);
1555 # $record->insert_grouped_field($itemfield);
1556 # save the record into biblioitem
1557 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1558 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1559 #my $Zconn = C4::Context->Zconn or die "unable to set Zconn";
1560 z3950_extended_services($Zconn,'update',set_service_options('update'),$record);
1561 # z3950_extended_services($Zconn,'commit',set_service_options('commit'));
1562 #zebra_create($item->biblionumber,$record);
1563 if ( defined $sth->errstr ) {
1564 $error .= $sth->errstr;
1566 $dbh->do('unlock tables');
1571 =head2 REALdelitem($dbh,$itemnum);
1582 my ( $dbh, $itemnum ) = @_;
1584 # my $dbh=C4Connect;
1585 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1586 $sth->execute($itemnum);
1587 my $data = $sth->fetchrow_hashref;
1589 my $query = "Insert into deleteditems set ";
1591 foreach my $temp ( keys %$data ) {
1592 $query .= "$temp = ?,";
1593 push ( @bind, $data->{$temp} );
1598 $sth = $dbh->prepare($query);
1599 $sth->execute(@bind);
1601 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1602 $sth->execute($itemnum);
1608 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1612 deletes a biblioitem
1613 NOTE : not standard sub name. Should be REALdelbiblioitem()
1619 sub REALdelbiblioitem {
1620 my ( $dbh, $biblioitemnumber ) = @_;
1622 # my $dbh = C4Connect;
1623 my $sth = $dbh->prepare( "Select * from biblioitems
1624 where biblioitemnumber = ?"
1628 $sth->execute($biblioitemnumber);
1630 if ( $results = $sth->fetchrow_hashref ) {
1634 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1635 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1636 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1640 $results->{biblioitemnumber}, $results->{biblionumber},
1641 $results->{volume}, $results->{number},
1642 $results->{classification}, $results->{itemtype},
1643 $results->{isbn}, $results->{issn},
1644 $results->{dewey}, $results->{subclass},
1645 $results->{publicationyear}, $results->{publishercode},
1646 $results->{volumedate}, $results->{volumeddesc},
1647 $results->{timestamp}, $results->{illus},
1648 $results->{pages}, $results->{notes},
1649 $results->{size}, $results->{url},
1653 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1654 $sth2->execute($biblioitemnumber);
1659 # Now delete all the items attached to the biblioitem
1660 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1661 $sth->execute($biblioitemnumber);
1663 while ( my $data = $sth->fetchrow_hashref ) {
1664 my $query = "Insert into deleteditems set ";
1666 foreach my $temp ( keys %$data ) {
1667 $query .= "$temp = ?,";
1668 push ( @bind, $data->{$temp} );
1671 my $sth2 = $dbh->prepare($query);
1672 $sth2->execute(@bind);
1675 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1676 $sth->execute($biblioitemnumber);
1680 } # sub deletebiblioitem
1682 =head2 REALdelbiblio($dbh,$biblio);
1693 my ( $dbh, $biblio ) = @_;
1694 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1695 $sth->execute($biblio);
1696 if ( my $data = $sth->fetchrow_hashref ) {
1698 my $query = "Insert into deletedbiblio set ";
1700 foreach my $temp ( keys %$data ) {
1701 $query .= "$temp = ?,";
1702 push ( @bind, $data->{$temp} );
1705 #replacing the last , by ",?)"
1707 $sth = $dbh->prepare($query);
1708 $sth->execute(@bind);
1710 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1711 $sth->execute($biblio);
1717 =head2 $number = itemcount($biblio);
1721 returns the number of items attached to a biblio
1729 my $dbh = C4::Context->dbh;
1732 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1733 $sth->execute($biblio);
1734 my $data = $sth->fetchrow_hashref;
1736 return ( $data->{'count(*)'} );
1739 =head2 $biblionumber = newbiblio($biblio);
1743 create a biblio. The parameter is a hash
1751 my $dbh = C4::Context->dbh;
1752 my $bibnum = REALnewbiblio( $dbh, $biblio );
1753 # finds new (MARC bibid
1754 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1755 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1756 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1760 =head2 $biblionumber = &modbiblio($biblio);
1764 Update a biblio record.
1766 C<$biblio> is a reference-to-hash whose keys are the fields in the
1767 biblio table in the Koha database. All fields must be present, not
1768 just the ones you wish to change.
1770 C<&modbiblio> updates the record defined by
1771 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1773 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1782 my $dbh = C4::Context->dbh;
1783 my $biblionumber=REALmodbiblio($dbh,$biblio);
1784 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1785 # finds new (MARC bibid
1786 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1787 MARCmodbiblio($dbh,$bibid,$record,"",0);
1788 return($biblionumber);
1791 =head2 &modsubtitle($biblionumber, $subtitle);
1795 Sets the subtitle of a book.
1797 C<$biblionumber> is the biblionumber of the book to modify.
1799 C<$subtitle> is the new subtitle.
1806 my ( $bibnum, $subtitle ) = @_;
1807 my $dbh = C4::Context->dbh;
1808 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1811 =head2 &modaddauthor($biblionumber, $author);
1815 Replaces all additional authors for the book with biblio number
1816 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1817 C<&modaddauthor> deletes all additional authors.
1824 my ( $bibnum, @authors ) = @_;
1825 my $dbh = C4::Context->dbh;
1826 &REALmodaddauthor( $dbh, $bibnum, @authors );
1827 } # sub modaddauthor
1829 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1833 $force - a subject to force
1834 $error - Error message, or undef if successful.
1841 my ( $bibnum, $force, @subject ) = @_;
1842 my $dbh = C4::Context->dbh;
1843 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1845 # When MARC is off, ensures that the MARC biblio table gets updated with new
1846 # subjects, of course, it deletes the biblio in marc, and then recreates.
1847 # This check is to ensure that no MARC data exists to lose.
1848 # if (C4::Context->preference("MARC") eq '0'){
1849 # warn "in modSUBJECT";
1850 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1851 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1852 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1858 =head2 modbibitem($dbh, $Zconn,$biblioitem);
1862 modify a biblioitem. The parameter is a hash
1869 my ($dbh, $Zconn, $biblioitem) = @_;
1870 #my $dbh = C4::Context->dbh;
1871 &REALmodbiblioitem( $dbh, $Zconn, $biblioitem );
1874 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1878 create a biblioitem, the parameter is a hash
1885 my ($dbh, $Zconn, $biblioitem) = @_;
1886 #my $dbh = C4::Context->dbh;
1887 # add biblio information to the hash
1888 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1889 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1890 my $bibitemnum = &REALnewbiblioitem( $dbh, $Zconn, $biblioitem );
1891 return ($bibitemnum);
1894 =head2 newsubtitle($biblionumber,$subtitle);
1898 insert a subtitle for $biblionumber biblio
1906 my ( $bibnum, $subtitle ) = @_;
1907 my $dbh = C4::Context->dbh;
1908 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1911 =head2 $errors = newitems($dbh, $Zconn, $item, @barcodes);
1915 insert items ($item is a hash)
1923 my ( $dbh, $Zconn, $item, @barcodes ) = @_;
1924 #my $dbh = C4::Context->dbh;
1928 foreach my $barcode (@barcodes) {
1929 # add items, one by one for each barcode.
1931 $oneitem->{barcode}= $barcode;
1932 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1933 $oneitem->{marc} = $MARCitem->as_usmarc;
1934 ( $itemnumber, $error ) = &REALnewitems( $dbh,$Zconn,$oneitem);
1935 # $errors .= $error;
1936 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1941 =head2 moditem($dbh,$Zconn,$item);
1945 modify an item ($item is a hash with all item informations)
1953 my ($dbh,$Zconn,$item) = @_;
1954 #my $dbh = C4::Context->dbh;
1955 &REALmoditem( $dbh, $Zconn, $item );
1957 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1959 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1960 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1963 =head2 $error = checkitems($count,@barcodes);
1967 check for each @barcode entry that the barcode is not a duplicate
1974 my ( $count, @barcodes ) = @_;
1975 my $dbh = C4::Context->dbh;
1977 my $sth = $dbh->prepare("Select * from items where barcode=?");
1978 for ( my $i = 0 ; $i < $count ; $i++ ) {
1979 $barcodes[$i] = uc $barcodes[$i];
1980 $sth->execute( $barcodes[$i] );
1981 if ( my $data = $sth->fetchrow_hashref ) {
1982 $error .= " Duplicate Barcode: $barcodes[$i]";
1989 =head2 $delitem($itemnum);
1993 delete item $itemnum being the item number to delete
2001 my $dbh = C4::Context->dbh;
2002 &REALdelitem( $dbh, $itemnum );
2005 =head2 deletebiblioitem($biblioitemnumber);
2009 delete the biblioitem $biblioitemnumber
2015 sub deletebiblioitem {
2016 my ($biblioitemnumber) = @_;
2017 my $dbh = C4::Context->dbh;
2018 &REALdelbiblioitem( $dbh, $biblioitemnumber );
2019 } # sub deletebiblioitem
2021 =head2 delbiblio($biblionumber)
2025 delete biblio $biblionumber
2033 my $dbh = C4::Context->dbh;
2034 &REALdelbiblio( $dbh, $biblio );
2035 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2036 &MARCdelbiblio( $dbh, $bibid, 0 );
2039 =head2 ($count,@results) = getbiblio($biblionumber);
2043 return an array with hash of biblios.
2045 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2052 my ($biblionumber) = @_;
2053 my $dbh = C4::Context->dbh;
2054 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2056 # || die "Cannot prepare $query\n" . $dbh->errstr;
2060 $sth->execute($biblionumber);
2062 # || die "Cannot execute $query\n" . $sth->errstr;
2063 while ( my $data = $sth->fetchrow_hashref ) {
2064 $results[$count] = $data;
2069 return ( $count, @results );
2074 $data = &bibdata($biblionumber, $type);
2076 Returns information about the book with the given biblionumber.
2078 C<$type> is ignored.
2080 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2081 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2084 In addition, C<$data-E<gt>{subject}> is the list of the book's
2085 subjects, separated by C<" , "> (space, comma, space).
2087 If there are multiple biblioitems with the given biblionumber, only
2088 the first one is considered.
2093 my ($bibnum, $type) = @_;
2094 my $dbh = C4::Context->dbh;
2095 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2097 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2098 left join bibliosubtitle on
2099 biblio.biblionumber = bibliosubtitle.biblionumber
2100 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2101 where biblio.biblionumber = ?
2103 $sth->execute($bibnum);
2105 $data = $sth->fetchrow_hashref;
2107 # handle management of repeated subtitle
2108 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2109 $sth->execute($bibnum);
2111 while (my $dat = $sth->fetchrow_hashref){
2113 $line{subtitle} = $dat->{subtitle};
2114 push @subtitles, \%line;
2116 $data->{subtitles} = \@subtitles;
2118 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2119 $sth->execute($bibnum);
2121 while (my $dat = $sth->fetchrow_hashref){
2123 $line{subject} = $dat->{'subject'};
2124 push @subjects, \%line;
2126 $data->{subjects} = \@subjects;
2128 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2129 $sth->execute($bibnum);
2130 while (my $dat = $sth->fetchrow_hashref){
2131 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2133 chop $data->{'additionalauthors'};
2134 chop $data->{'additionalauthors'};
2135 chop $data->{'additionalauthors'};
2140 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
2144 return an array with hash of biblioitemss.
2146 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2153 my ($biblioitemnum) = @_;
2154 my $dbh = C4::Context->dbh;
2155 my $sth = $dbh->prepare( "Select * from biblioitems where
2156 biblioitemnumber = ?"
2161 $sth->execute($biblioitemnum);
2163 while ( my $data = $sth->fetchrow_hashref ) {
2164 $results[$count] = $data;
2169 return ( $count, @results );
2170 } # sub getbiblioitem
2172 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2176 return an array with hash of biblioitems for the given biblionumber.
2182 sub getbiblioitembybiblionumber {
2183 my ($biblionumber) = @_;
2184 my $dbh = C4::Context->dbh;
2185 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2189 $sth->execute($biblionumber);
2191 while ( my $data = $sth->fetchrow_hashref ) {
2192 $results[$count] = $data;
2197 return ( $count, @results );
2200 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2204 returns an array with hash of items
2210 sub getitemsbybiblioitem {
2211 my ($biblioitemnum) = @_;
2212 my $dbh = C4::Context->dbh;
2213 my $sth = $dbh->prepare( "Select * from items, biblio where
2214 biblio.biblionumber = items.biblionumber and biblioitemnumber
2218 # || die "Cannot prepare $query\n" . $dbh->errstr;
2222 $sth->execute($biblioitemnum);
2224 # || die "Cannot execute $query\n" . $sth->errstr;
2225 while ( my $data = $sth->fetchrow_hashref ) {
2226 $results[$count] = $data;
2231 return ( $count, @results );
2232 } # sub getitemsbybiblioitem
2236 @results = &ItemInfo($env, $biblionumber, $type);
2238 Returns information about books with the given biblionumber.
2240 C<$type> may be either C<intra> or anything else. If it is not set to
2241 C<intra>, then the search will exclude lost, very overdue, and
2246 C<&ItemInfo> returns a list of references-to-hash. Each element
2247 contains a number of keys. Most of them are table items from the
2248 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2249 Koha database. Other keys include:
2253 =item C<$data-E<gt>{branchname}>
2255 The name (not the code) of the branch to which the book belongs.
2257 =item C<$data-E<gt>{datelastseen}>
2259 This is simply C<items.datelastseen>, except that while the date is
2260 stored in YYYY-MM-DD format in the database, here it is converted to
2261 DD/MM/YYYY format. A NULL date is returned as C<//>.
2263 =item C<$data-E<gt>{datedue}>
2265 =item C<$data-E<gt>{class}>
2267 This is the concatenation of C<biblioitems.classification>, the book's
2268 Dewey code, and C<biblioitems.subclass>.
2270 =item C<$data-E<gt>{ocount}>
2272 I think this is the number of copies of the book available.
2274 =item C<$data-E<gt>{order}>
2276 If this is set, it is set to C<One Order>.
2283 my ($env,$biblionumber,$type) = @_;
2284 my $dbh = C4::Context->dbh;
2285 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2286 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2287 WHERE items.biblionumber = ?
2288 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2289 AND biblio.biblionumber = items.biblionumber";
2290 $query .= " order by items.dateaccessioned desc";
2291 my $sth=$dbh->prepare($query);
2292 $sth->execute($biblionumber);
2295 while (my $data=$sth->fetchrow_hashref){
2297 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2298 $isth->execute($data->{'itemnumber'});
2299 if (my $idata=$isth->fetchrow_hashref){
2300 $data->{borrowernumber} = $idata->{borrowernumber};
2301 $data->{cardnumber} = $idata->{cardnumber};
2302 $datedue = format_date($idata->{'date_due'});
2304 if ($datedue eq ''){
2305 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2311 #get branch information.....
2312 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2313 $bsth->execute($data->{'holdingbranch'});
2314 if (my $bdata=$bsth->fetchrow_hashref){
2315 $data->{'branchname'} = $bdata->{'branchname'};
2317 my $date=format_date($data->{'datelastseen'});
2318 $data->{'datelastseen'}=$date;
2319 $data->{'datedue'}=$datedue;
2320 # get notforloan complete status if applicable
2321 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2322 $sthnflstatus->execute;
2323 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2324 if ($authorised_valuecode) {
2325 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2326 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2327 my ($lib) = $sthnflstatus->fetchrow;
2328 $data->{notforloan} = $lib;
2339 ($count, @results) = &bibitems($biblionumber);
2341 Given the biblionumber for a book, C<&bibitems> looks up that book's
2342 biblioitems (different publications of the same book, the audio book
2343 and film versions, etc.).
2345 C<$count> is the number of elements in C<@results>.
2347 C<@results> is an array of references-to-hash; the keys are the fields
2348 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2349 addition, C<itemlost> indicates the availability of the item: if it is
2350 "2", then all copies of the item are long overdue; if it is "1", then
2351 all copies are lost; otherwise, there is at least one copy available.
2357 my $dbh = C4::Context->dbh;
2358 my $sth = $dbh->prepare("SELECT biblioitems.*,
2360 MIN(items.itemlost) as itemlost,
2361 MIN(items.dateaccessioned) as dateaccessioned
2362 FROM biblioitems, itemtypes, items
2363 WHERE biblioitems.biblionumber = ?
2364 AND biblioitems.itemtype = itemtypes.itemtype
2365 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2366 GROUP BY items.biblioitemnumber");
2369 $sth->execute($bibnum);
2370 while (my $data = $sth->fetchrow_hashref) {
2371 $results[$count] = $data;
2375 return($count, @results);
2381 $itemdata = &bibitemdata($biblioitemnumber);
2383 Looks up the biblioitem with the given biblioitemnumber. Returns a
2384 reference-to-hash. The keys are the fields from the C<biblio>,
2385 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2386 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2392 my $dbh = C4::Context->dbh;
2393 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");
2396 $sth->execute($bibitem);
2398 $data = $sth->fetchrow_hashref;
2405 =item getbibliofromitemnumber
2407 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2409 Looks up the item with the given itemnumber.
2411 C<$env> and C<$dbh> are ignored.
2413 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2414 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2419 sub getbibliofromitemnumber {
2420 my ($env,$dbh,$itemnumber) = @_;
2421 $dbh = C4::Context->dbh;
2422 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2423 where items.itemnumber = ?
2424 and biblio.biblionumber = items.biblionumber
2425 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2427 $sth->execute($itemnumber);
2428 my $data=$sth->fetchrow_hashref;
2435 @barcodes = &barcodes($biblioitemnumber);
2437 Given a biblioitemnumber, looks up the corresponding items.
2439 Returns an array of references-to-hash; the keys are C<barcode> and
2442 The returned items include very overdue items, but not lost ones.
2447 #called from request.pl
2448 my ($biblioitemnumber)=@_;
2449 my $dbh = C4::Context->dbh;
2450 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2451 WHERE biblioitemnumber = ?
2452 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2453 $sth->execute($biblioitemnumber);
2456 while (my $data=$sth->fetchrow_hashref){
2457 $barcodes[$i]=$data;
2467 $item = &itemdata($barcode);
2469 Looks up the item with the given barcode, and returns a
2470 reference-to-hash containing information about that item. The keys of
2471 the hash are the fields from the C<items> and C<biblioitems> tables in
2476 sub get_item_from_barcode {
2478 my $dbh = C4::Context->dbh;
2479 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2480 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2481 $sth->execute($barcode);
2482 my $data=$sth->fetchrow_hashref;
2490 @issues = &itemissues($biblioitemnumber, $biblio);
2492 Looks up information about who has borrowed the bookZ<>(s) with the
2493 given biblioitemnumber.
2495 C<$biblio> is ignored.
2497 C<&itemissues> returns an array of references-to-hash. The keys
2498 include the fields from the C<items> table in the Koha database.
2499 Additional keys include:
2505 If the item is currently on loan, this gives the due date.
2507 If the item is not on loan, then this is either "Available" or
2508 "Cancelled", if the item has been withdrawn.
2512 If the item is currently on loan, this gives the card number of the
2513 patron who currently has the item.
2515 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2517 These give the timestamp for the last three times the item was
2520 =item C<card0>, C<card1>, C<card2>
2522 The card number of the last three patrons who borrowed this item.
2524 =item C<borrower0>, C<borrower1>, C<borrower2>
2526 The borrower number of the last three patrons who borrowed this item.
2533 my ($bibitem, $biblio)=@_;
2534 my $dbh = C4::Context->dbh;
2535 # FIXME - If this function die()s, the script will abort, and the
2536 # user won't get anything; depending on how far the script has
2537 # gotten, the user might get a blank page. It would be much better
2538 # to at least print an error message. The easiest way to do this
2539 # is to set $SIG{__DIE__}.
2540 my $sth = $dbh->prepare("Select * from items where
2541 items.biblioitemnumber = ?")
2542 || die $dbh->errstr;
2546 $sth->execute($bibitem)
2547 || die $sth->errstr;
2549 while (my $data = $sth->fetchrow_hashref) {
2550 # Find out who currently has this item.
2551 # FIXME - Wouldn't it be better to do this as a left join of
2552 # some sort? Currently, this code assumes that if
2553 # fetchrow_hashref() fails, then the book is on the shelf.
2554 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2555 # database server crash), not just because no items match the
2557 my $sth2 = $dbh->prepare("select * from issues,borrowers
2558 where itemnumber = ?
2559 and returndate is NULL
2560 and issues.borrowernumber = borrowers.borrowernumber");
2562 $sth2->execute($data->{'itemnumber'});
2563 if (my $data2 = $sth2->fetchrow_hashref) {
2564 $data->{'date_due'} = $data2->{'date_due'};
2565 $data->{'card'} = $data2->{'cardnumber'};
2566 $data->{'borrower'} = $data2->{'borrowernumber'};
2568 if ($data->{'wthdrawn'} eq '1') {
2569 $data->{'date_due'} = 'Cancelled';
2571 $data->{'date_due'} = 'Available';
2577 # Find the last 3 people who borrowed this item.
2578 $sth2 = $dbh->prepare("select * from issues, borrowers
2579 where itemnumber = ?
2580 and issues.borrowernumber = borrowers.borrowernumber
2581 and returndate is not NULL
2582 order by returndate desc,timestamp desc") || die $dbh->errstr;
2583 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2584 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2585 if (my $data2 = $sth2->fetchrow_hashref) {
2586 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2587 $data->{"card$i2"} = $data2->{'cardnumber'};
2588 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2593 $results[$i] = $data;
2603 ($count, $subjects) = &getsubject($biblionumber);
2605 Looks up the subjects of the book with the given biblionumber. Returns
2606 a two-element list. C<$subjects> is a reference-to-array, where each
2607 element is a subject of the book, and C<$count> is the number of
2608 elements in C<$subjects>.
2614 my $dbh = C4::Context->dbh;
2615 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2616 $sth->execute($bibnum);
2619 while (my $data=$sth->fetchrow_hashref){
2624 return($i,\@results);
2629 ($count, $authors) = &getaddauthor($biblionumber);
2631 Looks up the additional authors for the book with the given
2634 Returns a two-element list. C<$authors> is a reference-to-array, where
2635 each element is an additional author, and C<$count> is the number of
2636 elements in C<$authors>.
2642 my $dbh = C4::Context->dbh;
2643 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2644 $sth->execute($bibnum);
2647 while (my $data=$sth->fetchrow_hashref){
2652 return($i,\@results);
2658 ($count, $subtitles) = &getsubtitle($biblionumber);
2660 Looks up the subtitles for the book with the given biblionumber.
2662 Returns a two-element list. C<$subtitles> is a reference-to-array,
2663 where each element is a subtitle, and C<$count> is the number of
2664 elements in C<$subtitles>.
2670 my $dbh = C4::Context->dbh;
2671 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2672 $sth->execute($bibnum);
2675 while (my $data=$sth->fetchrow_hashref){
2680 return($i,\@results);
2686 ($count, @websites) = &getwebsites($biblionumber);
2688 Looks up the web sites pertaining to the book with the given
2691 C<$count> is the number of elements in C<@websites>.
2693 C<@websites> is an array of references-to-hash; the keys are the
2694 fields from the C<websites> table in the Koha database.
2697 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2698 #(with add / modify / delete subs)
2701 my ($biblionumber) = @_;
2702 my $dbh = C4::Context->dbh;
2703 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2707 $sth->execute($biblionumber);
2708 while (my $data = $sth->fetchrow_hashref) {
2709 # FIXME - The URL scheme shouldn't be stripped off, at least
2710 # not here, since it's part of the URL, and will be useful in
2711 # constructing a link to the site. If you don't want the user
2712 # to see the "http://" part, strip that off when building the
2714 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2716 $results[$count] = $data;
2721 return($count, @results);
2724 =item getwebbiblioitems
2726 ($count, @results) = &getwebbiblioitems($biblionumber);
2728 Given a book's biblionumber, looks up the web versions of the book
2729 (biblioitems with itemtype C<WEB>).
2731 C<$count> is the number of items in C<@results>. C<@results> is an
2732 array of references-to-hash; the keys are the items from the
2733 C<biblioitems> table of the Koha database.
2737 sub getwebbiblioitems {
2738 my ($biblionumber) = @_;
2739 my $dbh = C4::Context->dbh;
2740 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2741 and itemtype = 'WEB'");
2745 $sth->execute($biblionumber);
2746 while (my $data = $sth->fetchrow_hashref) {
2747 $data->{'url'} =~ s/^http:\/\///;
2748 $results[$count] = $data;
2753 return($count, @results);
2754 } # sub getwebbiblioitems
2757 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2758 my $NSE = '\x89'; # NSE : Non Sorting Block end
2759 # handles non sorting blocks
2763 s/[ ]{0,1}$NSE/) /gm;
2770 my $dbh = C4::Context->dbh;
2771 my $result = MARCmarc2koha($dbh,$record,'');
2773 my ($biblionumber,$bibid,$title);
2774 # search duplicate on ISBN, easy and fast...
2775 if ($result->{isbn}) {
2776 $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=?");
2777 $sth->execute($result->{'isbn'});
2778 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2779 return $biblionumber,$bibid,$title if ($biblionumber);
2781 # a more complex search : build a request for SearchMarc::catalogsearch()
2782 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2783 # search on biblio.title
2784 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2785 if ($record->field($tag)) {
2786 if ($record->field($tag)->subfields($subfield)) {
2787 push @tags, "'".$tag.$subfield."'";
2788 push @and_or, "and";
2789 push @excluding, "";
2790 push @operator, "contains";
2791 push @value, $record->field($tag)->subfield($subfield);
2792 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2795 # ... and on biblio.author
2796 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2797 if ($record->field($tag)) {
2798 if ($record->field($tag)->subfields($subfield)) {
2799 push @tags, "'".$tag.$subfield."'";
2800 push @and_or, "and";
2801 push @excluding, "";
2802 push @operator, "contains";
2803 push @value, $record->field($tag)->subfield($subfield);
2804 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2807 # ... and on publicationyear.
2808 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2809 if ($record->field($tag)) {
2810 if ($record->field($tag)->subfields($subfield)) {
2811 push @tags, "'".$tag.$subfield."'";
2812 push @and_or, "and";
2813 push @excluding, "";
2814 push @operator, "=";
2815 push @value, $record->field($tag)->subfield($subfield);
2816 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2820 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2821 if ($record->field($tag)) {
2822 if ($record->field($tag)->subfields($subfield)) {
2823 push @tags, "'".$tag.$subfield."'";
2824 push @and_or, "and";
2825 push @excluding, "";
2826 push @operator, "=";
2827 push @value, $record->field($tag)->subfield($subfield);
2828 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2831 # ... and on publisher.
2832 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2833 if ($record->field($tag)) {
2834 if ($record->field($tag)->subfields($subfield)) {
2835 push @tags, "'".$tag.$subfield."'";
2836 push @and_or, "and";
2837 push @excluding, "";
2838 push @operator, "=";
2839 push @value, $record->field($tag)->subfield($subfield);
2840 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2843 # ... and on volume.
2844 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2845 if ($record->field($tag)) {
2846 if ($record->field($tag)->subfields($subfield)) {
2847 push @tags, "'".$tag.$subfield."'";
2848 push @and_or, "and";
2849 push @excluding, "";
2850 push @operator, "=";
2851 push @value, $record->field($tag)->subfield($subfield);
2852 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2856 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2857 # there is at least 1 result => return the 1st one
2859 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2860 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2862 # no result, returns nothing
2869 if(substr($isbn, 0, 1) <=7) {
2870 $seg1 = substr($isbn, 0, 1);
2871 } elsif(substr($isbn, 0, 2) <= 94) {
2872 $seg1 = substr($isbn, 0, 2);
2873 } elsif(substr($isbn, 0, 3) <= 995) {
2874 $seg1 = substr($isbn, 0, 3);
2875 } elsif(substr($isbn, 0, 4) <= 9989) {
2876 $seg1 = substr($isbn, 0, 4);
2878 $seg1 = substr($isbn, 0, 5);
2880 my $x = substr($isbn, length($seg1));
2882 if(substr($x, 0, 2) <= 19) {
2883 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2884 $seg2 = substr($x, 0, 2);
2885 } elsif(substr($x, 0, 3) <= 699) {
2886 $seg2 = substr($x, 0, 3);
2887 } elsif(substr($x, 0, 4) <= 8399) {
2888 $seg2 = substr($x, 0, 4);
2889 } elsif(substr($x, 0, 5) <= 89999) {
2890 $seg2 = substr($x, 0, 5);
2891 } elsif(substr($x, 0, 6) <= 9499999) {
2892 $seg2 = substr($x, 0, 6);
2894 $seg2 = substr($x, 0, 7);
2896 my $seg3=substr($x,length($seg2));
2897 $seg3=substr($seg3,0,length($seg3)-1) ;
2898 my $seg4 = substr($x, -1, 1);
2899 return "$seg1-$seg2-$seg3-$seg4";
2903 END { } # module clean-up code here (global destructor)
2909 Koha Developement team <info@koha.org>
2911 Paul POULAIN paul.poulain@free.fr
2917 # Revision 1.150 2006/02/25 20:49:15 kados
2918 # Better documentation, added warning if serviceType is 'drop' since it's
2919 # not supported in Zebra.
2921 # Revision 1.149 2006/02/25 20:30:32 kados
2922 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
2923 # longer necessary. If we need to convert from MARC-8 for display, we should:
2926 # 2. do it with MARC::Charset
2928 # If you still need it, let me know and I'll put it back in.
2930 # Revision 1.148 2006/02/25 19:23:01 kados
2931 # cleaning up POD docs, deleting zebra_create as it's no longer used (
2932 # replaced by z3950_extended_services).
2934 # Revision 1.147 2006/02/25 19:09:59 kados
2935 # readding some lost subs
2937 # Revision 1.145 2006/02/22 01:02:39 kados
2938 # Replacing all calls to zebra_update with calls to
2939 # z3950_extended_services. More work coming, but it's
2942 # Revision 1.144 2006/02/20 14:22:38 kados
2945 # Revision 1.143 2006/02/20 13:26:11 kados
2946 # A new subroutine to handle Z39.50 extended services. You pass it a
2947 # connection object, service type, service options, and a record, and
2948 # it performs the service and handles any exception found.
2950 # Revision 1.142 2006/02/16 20:49:56 kados
2951 # destroy a connection after we're done -- we really should just have one
2952 # connection object and not destroy it until the whole transaction is
2953 # finished -- but this will do for now
2955 # Revision 1.141 2006/02/16 19:47:22 rangi
2956 # Trying to error trap a little more.
2958 # Revision 1.140 2006/02/14 21:36:03 kados
2959 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
2960 # also adding diagnostic error if not able to connect to Zebra
2962 # Revision 1.139 2006/02/14 19:53:25 rangi
2963 # Just a little missing my
2965 # Seems to be working great Paul, and I like what you did with zebradb
2967 # Revision 1.138 2006/02/14 11:25:22 tipaul
2968 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
2970 # Revision 1.137 2006/02/13 16:34:26 tipaul
2971 # fixing some warnings (perl -w should be quiet)
2973 # Revision 1.136 2006/01/10 17:01:29 tipaul
2974 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
2976 # Revision 1.135 2006/01/06 16:39:37 tipaul
2977 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
2978 # Seems not to break too many things, but i'm probably wrong here.
2979 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
2981 # - removing useless directories (koha-html and koha-plucene)
2983 # Revision 1.134 2006/01/04 15:54:55 tipaul
2984 # utf8 is a : go for beta test in HEAD.
2985 # some explanations :
2986 # - 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.
2987 # - *-top.inc will show the pages in utf8
2988 # - 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.
2989 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
2991 # Revision 1.133 2005/12/12 14:25:51 thd
2994 # Reverse array filled with elements from repeated subfields
2995 # to avoid last to first concatenation of elements in Koha DB.-
2997 # Revision 1.132 2005-10-26 09:12:33 tipaul
2998 # big commit, still breaking things...
3000 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3001 # * code cleaning (cleaning warnings from perl -w) continued
3003 # Revision 1.131 2005/09/22 10:01:45 tipaul
3004 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3006 # Revision 1.130 2005/09/02 14:34:14 tipaul
3007 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3008 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3009 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3011 # Revision 1.129 2005/08/12 13:50:31 tipaul
3012 # removing useless sub declarations
3014 # Revision 1.128 2005/08/11 16:12:47 tipaul
3015 # Playing with the zebra...
3017 # * go to koha cvs home directory
3018 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3019 # * put your zebra.cfg files here & create your database.
3020 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3021 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3024 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3025 # * deletion still not work
3026 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3028 # recordId: (bib1,Local-number)
3032 # elm 090 Local-number -
3033 # elm 090/? Local-number -
3034 # elm 090/?/9 Local-number !:w
3036 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3038 # Revision 1.127 2005/08/11 14:37:32 tipaul
3040 # * removing useless subs
3041 # * removing some subs that are also elsewhere
3042 # * 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)
3044 # Revision 1.126 2005/08/11 09:13:28 tipaul
3045 # just removing useless subs (a lot !!!) for code cleaning
3047 # Revision 1.125 2005/08/11 09:00:07 tipaul
3048 # Ok guys, this time, it seems that item add and modif begin working as expected...
3049 # Still a lot of bugs to fix, of course
3051 # Revision 1.124 2005/08/10 10:21:15 tipaul
3052 # continuing the road to zebra :
3053 # - the biblio add begins to work.
3054 # - the biblio modif begins to work.
3056 # (still without doing anything on zebra)
3057 # (no new change in updatedatabase)
3059 # Revision 1.123 2005/08/09 14:10:28 tipaul
3060 # 1st commit to go to zebra.
3061 # don't update your cvs if you want to have a working head...
3063 # this commit contains :
3064 # * 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...
3065 # * 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.
3066 # * other files : get rid of bibid and use biblionumber instead.
3069 # * does not do anything on zebra yet.
3070 # * if you rename marc_subfield_table, you can't search anymore.
3071 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3072 # * 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 ;-) )
3074 # 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
3075 # 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.
3077 # tipaul cutted previous commit notes