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
38 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
39 # as the old-style API and the NEW one are the only public functions.
42 &newbiblio &newbiblioitem
43 &newsubject &newsubtitle &newitems
45 &modbiblio &checkitems &modbibitem
46 &modsubtitle &modsubject &modaddauthor &moditem
48 &delitem &deletebiblioitem &delbiblio
50 &getbiblio &bibdata &bibitems &bibitemdata
51 &barcodes &ItemInfo &itemdata &itemissues &itemcount
52 &getsubject &getaddauthor &getsubtitle
53 &getwebbiblioitems &getwebsites
54 &getbiblioitembybiblionumber
55 &getbiblioitem &getitemsbybiblioitem
57 &MARCfind_marc_from_kohafield
58 &MARCfind_frameworkcode
59 &find_biblioitemnumber
62 &NEWnewbiblio &NEWnewitem
63 &NEWmodbiblio &NEWmoditem
64 &NEWdelbiblio &NEWdelitem
65 &NEWmodbiblioframework
67 &MARCkoha2marcBiblio &MARCmarc2koha
68 &MARCkoha2marcItem &MARChtml2marc
69 &MARCgetbiblio &MARCgetitem
77 MARCfind_MARCbibid_from_oldbiblionumber
82 C4::Biblio - acquisition, catalog management functions
86 ( lot of changes for Koha 3.0)
88 Koha 1.2 and previous version used a specific API to manage biblios. This API uses old-DB style parameters.
89 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, bibliosubject and bibliosubtitle where applicable)
91 In Koha 2.0, we introduced a MARC-DB.
93 In Koha 3.0 we removed this MARC-DB for search as we wanted to use Zebra as search system.
95 So in Koha 3.0, saving a record means :
96 - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items informations.
97 - storing the "decoded information" in biblio/biblioitems/items as previously.
98 - using zebra to manage search & indexing on the MARC datas.
100 In Koha, there is a systempreference saying "MARC=ON" or "MARC=OFF"
102 * MARC=ON : when MARC=ON, koha uses a MARC::Record object (in sub parameters). Saving informations in the DB means :
103 - transform the MARC record into a hash
104 - add the raw marc record into the hash
105 - store them & update zebra
107 * MARC=OFF : when MARC=OFF, koha uses a hash object (in sub parameters). Saving informations in the DB means :
108 - transform the hash into a MARC record
109 - add the raw marc record into the hash
110 - store them and update zebra
113 That's why we need 3 types of subs :
117 all I<subs beginning by REAL> does effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in zebra. REAL subs should be only for internal use (called by NEW or "something else" subs
119 =head2 NEWxxx related subs
123 all I<subs beginning by NEW> use MARC::Record as parameters. it's the API that MUST be used in MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
125 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. they sometimes requires another parameter.
129 =head2 something_elsexxx related subs
133 all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and calls REAL subs.
135 all subs requires/use $dbh as 1st parameter and a hash as 2nd parameter.
144 my ($biblionumber,$record) = @_;
145 # create the iso2709 file for zebra
146 # my $cgidir = C4::Context->intranetdir ."/cgi-bin";
147 # unless (opendir(DIR, "$cgidir")) {
148 # $cgidir = C4::Context->intranetdir."/";
151 # my $filename = $cgidir."/zebra/biblios/BIBLIO".$biblionumber."iso2709";
152 # open F,"> $filename";
153 # print F $record->as_usmarc();
155 # my $res = system("cd $cgidir/zebra;/usr/local/bin/zebraidx update biblios");
159 # warn "zebra_create : $biblionumber =".$record->as_formatted;
161 $xmlrecord=$record->as_xml();
164 warn "ERROR badly formatted marc record";
165 warn "Skipping record";
169 $Zconn = new ZOOM::Connection(C4::Context->config("zebradb"));
172 warn "Error ", $@->code(), ": ", $@->message(), "\n";
173 die "Fatal error, cant connect to z3950 server";
176 $Zconn->option(cqlfile => C4::Context->config("intranetdir")."/zebra/pqf.properties");
177 my $Zpackage = $Zconn->package();
178 $Zpackage->option(action => "specialUpdate");
179 $Zpackage->option(record => $xmlrecord);
180 $Zpackage->send("update");
185 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
189 2nd param is 1 for liblibrarian and 0 for libopac
190 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
192 returns a hash with all values for all fields and subfields for a given MARC framework :
193 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
195 ->{mandatory} = $mandatory;
196 ->{repeatable} = $repeatable;
197 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
199 ->{mandatory} = $mandatory;
200 ->{repeatable} = $repeatable;
201 ->{authorised_value} = $authorised_value;
202 ->{authtypecode} = $authtypecode;
203 ->{value_builder} = $value_builder;
204 ->{kohafield} = $kohafield;
205 ->{seealso} = $seealso;
206 ->{hidden} = $hidden;
215 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
216 $frameworkcode = "" unless $frameworkcode;
217 $forlibrarian = 1 unless $forlibrarian;
219 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
221 # check that framework exists
224 "select count(*) from marc_tag_structure where frameworkcode=?");
225 $sth->execute($frameworkcode);
226 my ($total) = $sth->fetchrow;
227 $frameworkcode = "" unless ( $total > 0 );
230 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
232 $sth->execute($frameworkcode);
233 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
235 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
236 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
237 $res->{$tag}->{tab} = ""; # XXX
238 $res->{$tag}->{mandatory} = $mandatory;
239 $res->{$tag}->{repeatable} = $repeatable;
244 "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"
246 $sth->execute($frameworkcode);
249 my $authorised_value;
259 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
260 $mandatory, $repeatable, $authorised_value, $authtypecode,
261 $value_builder, $kohafield, $seealso, $hidden,
266 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
267 $res->{$tag}->{$subfield}->{tab} = $tab;
268 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
269 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
270 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
271 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
272 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
273 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
274 $res->{$tag}->{$subfield}->{seealso} = $seealso;
275 $res->{$tag}->{$subfield}->{hidden} = $hidden;
276 $res->{$tag}->{$subfield}->{isurl} = $isurl;
277 $res->{$tag}->{$subfield}->{link} = $link;
282 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
286 finds MARC tag and subfield for a given kohafield
287 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
293 sub MARCfind_marc_from_kohafield {
294 my ( $dbh, $kohafield,$frameworkcode ) = @_;
295 return 0, 0 unless $kohafield;
296 $frameworkcode='' unless $frameworkcode;
297 my $relations = C4::Context->marcfromkohafield;
298 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
301 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
305 Returns a MARC::Record for the biblio $biblionumber.
311 # Returns MARC::Record of the biblio passed in parameter.
312 my ( $dbh, $biblionumber ) = @_;
313 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
314 $sth->execute($biblionumber);
315 my ($marc) = $sth->fetchrow;
316 my $record = MARC::Record::new_from_usmarc($marc);
320 =head2 $XML = &XMLgetbiblio($dbh,$biblionumber);
324 Returns a raw XML for the biblio $biblionumber.
330 # Returns MARC::Record of the biblio passed in parameter.
331 my ( $dbh, $biblionumber ) = @_;
332 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
333 $sth->execute($biblionumber);
334 my ($XML,$marc) = $sth->fetchrow;
335 # my $record =MARC::Record::new_from_usmarc($marc);
336 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
340 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
344 Returns a MARC::Record with all items of biblio # $biblionumber
352 my ( $dbh, $biblionumber, $itemnumber ) = @_;
353 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
354 # get the complete MARC record
355 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
356 $sth->execute($biblionumber);
357 my ($rawmarc) = $sth->fetchrow;
358 my $record = MARC::File::USMARC::decode($rawmarc);
359 # now, find the relevant itemnumber
360 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
361 # prepare the new item record
362 my $itemrecord = MARC::Record->new();
363 # parse all fields fields from the complete record
364 foreach ($record->field($itemnumberfield)) {
365 # when the item field is found, save it
366 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
367 $itemrecord->append_fields($_);
374 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
378 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
379 This sub is useless when MARC=OFF
384 sub find_biblioitemnumber {
385 my ( $dbh, $biblionumber ) = @_;
386 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
387 $sth->execute($biblionumber);
388 my ($biblioitemnumber) = $sth->fetchrow;
389 return $biblioitemnumber;
392 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
396 returns the framework of a given biblio
402 sub MARCfind_frameworkcode {
403 my ( $dbh, $biblionumber ) = @_;
404 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
405 $sth->execute($biblionumber);
406 my ($frameworkcode) = $sth->fetchrow;
407 return $frameworkcode;
410 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
414 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
415 all entries of the hash are transformed into their matching MARC field/subfield.
421 sub MARCkoha2marcBiblio {
423 # this function builds partial MARC::Record from the old koha-DB fields
424 my ( $dbh, $bibliohash ) = @_;
425 # we don't have biblio entries in the hash, so we add them first
426 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
427 $sth->execute($bibliohash->{biblionumber});
428 my $biblio = $sth->fetchrow_hashref;
429 foreach (keys %$biblio) {
430 $bibliohash->{$_}=$biblio->{$_};
432 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
433 my $record = MARC::Record->new();
434 foreach ( keys %$bibliohash ) {
435 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
436 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
439 # other fields => additional authors, subjects, subtitles
440 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
441 $sth2->execute($bibliohash->{biblionumber});
442 while ( my $row = $sth2->fetchrow_hashref ) {
443 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
445 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
446 $sth2->execute($bibliohash->{biblionumber});
447 while ( my $row = $sth2->fetchrow_hashref ) {
448 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
450 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
451 $sth2->execute($bibliohash->{biblionumber});
452 while ( my $row = $sth2->fetchrow_hashref ) {
453 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
459 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
461 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
462 all entries of the hash are transformed into their matching MARC field/subfield.
470 sub MARCkoha2marcItem {
472 # this function builds partial MARC::Record from the old koha-DB fields
473 my ( $dbh, $item ) = @_;
475 # my $dbh=&C4Connect;
476 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
477 my $record = MARC::Record->new();
479 foreach( keys %$item ) {
481 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
488 =head2 MARCkoha2marcOnefield
492 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
498 sub MARCkoha2marcOnefield {
499 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
502 $sth->execute($frameworkcode,$kohafieldname);
503 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
504 if ( $record->field($tagfield) ) {
505 my $tag = $record->field($tagfield);
507 $tag->add_subfields( $tagsubfield, $value );
508 $record->delete_field($tag);
509 $record->add_fields($tag);
513 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
519 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
523 transforms the parameters (coming from HTML form) into a MARC::Record
524 parameters with r are references to arrays.
526 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
533 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
535 my $record = MARC::Record->new();
536 # my %subfieldlist=();
537 my $prevvalue; # if tag <10
538 my $field; # if tag >=10
539 for (my $i=0; $i< @$rtags; $i++) {
540 next unless @$rvalues[$i];
541 # rebuild MARC::Record
542 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
543 if (@$rtags[$i] ne $prevtag) {
546 if ($prevtag ne '000') {
547 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
549 $record->leader($prevvalue);
554 $record->add_fields($field);
557 $indicators{@$rtags[$i]}.=' ';
558 if (@$rtags[$i] <10) {
559 $prevvalue= @$rvalues[$i];
563 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
564 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
566 $prevtag = @$rtags[$i];
568 if (@$rtags[$i] <10) {
569 $prevvalue=@$rvalues[$i];
571 if (length(@$rvalues[$i])>0) {
572 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
573 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
576 $prevtag= @$rtags[$i];
579 # the last has not been included inside the loop... do it now !
580 $record->add_fields($field) if $field;
581 # warn "HTML2MARC=".$record->as_formatted;
586 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
590 builds a hash with old-db datas from a MARC::Record
597 my ($dbh,$record,$frameworkcode) = @_;
598 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
600 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
603 while (($field)=$sth2->fetchrow) {
604 # warn "biblio.".$field;
605 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
607 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
609 while (($field)=$sth2->fetchrow) {
610 if ($field eq 'notes') { $field = 'bnotes'; }
611 # warn "biblioitems".$field;
612 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
614 $sth2=$dbh->prepare("SHOW COLUMNS from items");
616 while (($field)=$sth2->fetchrow) {
617 # warn "items".$field;
618 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
620 # additional authors : specific
621 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
622 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
623 # modify copyrightdate to keep only the 1st year found
624 my $temp = $result->{'copyrightdate'};
626 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
628 $result->{'copyrightdate'} = $1;
629 } else { # if no cYYYY, get the 1st date.
630 $temp =~ m/(\d\d\d\d)/;
631 $result->{'copyrightdate'} = $1;
634 # modify publicationyear to keep only the 1st year found
635 $temp = $result->{'publicationyear'};
636 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
638 $result->{'publicationyear'} = $1;
639 } else { # if no cYYYY, get the 1st date.
640 $temp =~ m/(\d\d\d\d)/;
641 $result->{'publicationyear'} = $1;
646 sub MARCmarc2kohaOneField {
648 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
649 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
650 # warn "kohatable / $kohafield / $result / ";
654 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
655 foreach my $field ( $record->field($tagfield) ) {
656 if ($field->tag()<10) {
657 if ($result->{$kohafield}) {
658 # Reverse array filled with elements from repeated subfields
659 # from first to last to avoid last to first concatenation of
660 # elements in Koha DB. -- thd.
661 $result->{$kohafield} .= " | ".reverse($field->data());
663 $result->{$kohafield} = $field->data();
666 if ( $field->subfields ) {
667 my @subfields = $field->subfields();
668 foreach my $subfieldcount ( 0 .. $#subfields ) {
669 if ($subfields[$subfieldcount][0] eq $subfield) {
670 if ( $result->{$kohafield} ) {
671 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
674 $result->{$kohafield} = $subfields[$subfieldcount][1];
681 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
685 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
689 creates a biblio from a MARC::Record.
696 my ( $dbh, $record, $frameworkcode ) = @_;
698 my $biblioitemnumber;
699 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
700 $olddata->{frameworkcode} = $frameworkcode;
701 $biblionumber = REALnewbiblio( $dbh, $olddata );
702 $olddata->{biblionumber} = $biblionumber;
703 # add biblionumber into the MARC record (it's the ID for zebra)
704 my ( $tagfield, $tagsubfield ) =
705 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
709 $newfield = MARC::Field->new(
710 $tagfield, $biblionumber,
713 $newfield = MARC::Field->new(
714 $tagfield, '', '', "$tagsubfield" => $biblionumber,
717 # drop old field (just in case it already exist and create new one...
718 my $old_field = $record->field($tagfield);
719 $record->delete_field($old_field);
720 $record->add_fields($newfield);
722 #create the marc entry, that stores the rax marc record in Koha 3.0
723 $olddata->{marc} = $record->as_usmarc();
724 $olddata->{marcxml} = $record->as_xml();
725 # and create biblioitem, that's all folks !
726 $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
728 # search subtiles, addiauthors and subjects
729 ( $tagfield, $tagsubfield ) =
730 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
731 my @addiauthfields = $record->field($tagfield);
732 foreach my $addiauthfield (@addiauthfields) {
733 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
734 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
735 REALmodaddauthor( $dbh, $biblionumber,
736 $addiauthsubfields[$subfieldcount] );
739 ( $tagfield, $tagsubfield ) =
740 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
741 my @subtitlefields = $record->field($tagfield);
742 foreach my $subtitlefield (@subtitlefields) {
743 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
744 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
745 REALnewsubtitle( $dbh, $biblionumber,
746 $subtitlesubfields[$subfieldcount] );
749 ( $tagfield, $tagsubfield ) =
750 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
751 my @subj = $record->field($tagfield);
753 foreach my $subject (@subj) {
754 my @subjsubfield = $subject->subfield($tagsubfield);
755 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
756 push @subjects, $subjsubfield[$subfieldcount];
759 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
760 return ( $biblionumber, $biblioitemnumber );
763 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
767 modify the framework of a biblio
773 sub NEWmodbiblioframework {
774 my ($dbh,$biblionumber,$frameworkcode) =@_;
775 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
776 $sth->execute($frameworkcode,$biblionumber);
780 =head2 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
784 modify a biblio (MARC=ON)
791 my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
792 $frameworkcode="" unless $frameworkcode;
793 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
794 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
796 $oldbiblio->{frameworkcode} = $frameworkcode;
797 #create the marc entry, that stores the rax marc record in Koha 3.0
798 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
799 $oldbiblio->{marc} = $record->as_usmarc();
800 $oldbiblio->{marcxml} = $record->as_xml();
801 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
802 REALmodbiblio($dbh,$oldbiblio);
803 REALmodbiblioitem($dbh,$oldbiblio);
804 # now, modify addi authors, subject, addititles.
805 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
806 my @addiauthfields = $record->field($tagfield);
807 foreach my $addiauthfield (@addiauthfields) {
808 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
809 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
810 foreach my $subfieldcount (0..$#addiauthsubfields) {
811 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
814 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
815 my @subtitlefields = $record->field($tagfield);
816 foreach my $subtitlefield (@subtitlefields) {
817 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
818 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
820 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
821 foreach my $subfieldcount (0..$#subtitlesubfields) {
822 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
823 REALnewsubtitle($dbh,$biblionumber,$subtit);
827 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
828 my @subj = $record->field($tagfield);
830 foreach my $subject (@subj) {
831 my @subjsubfield = $subject->subfield($tagsubfield);
832 foreach my $subfieldcount (0..$#subjsubfield) {
833 push @subjects,$subjsubfield[$subfieldcount];
836 REALmodsubject($dbh,$biblionumber,1,@subjects);
840 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
851 my ( $dbh, $bibid ) = @_;
852 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
853 &REALdelbiblio( $dbh, $biblio );
856 "select biblioitemnumber from biblioitems where biblionumber=?");
857 $sth->execute($biblio);
858 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
859 REALdelbiblioitem( $dbh, $biblioitemnumber );
861 &MARCdelbiblio( $dbh, $bibid, 0 );
864 =head2 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
868 creates an item from a MARC::Record
875 my ( $dbh, $record, $biblionumber, $biblioitemnumber ) = @_;
878 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
879 my $item = &MARCmarc2koha( $dbh, $record,$frameworkcode );
880 # needs old biblionumber and biblioitemnumber
881 $item->{'biblionumber'} = $biblionumber;
882 $item->{'biblioitemnumber'}=$biblioitemnumber;
883 $item->{marc} = $record->as_usmarc();
885 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
890 =head2 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
901 my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
903 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
904 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
906 $olditem->{marc} = $record->as_usmarc();
907 $olditem->{biblionumber} = $biblionumber;
908 $olditem->{biblioitemnumber} = $biblioitemnumber;
910 REALmoditem( $dbh, $olditem );
914 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
925 my ( $dbh, $bibid, $itemnumber ) = @_;
926 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
927 &REALdelitem( $dbh, $itemnumber );
928 &MARCdelitem( $dbh, $bibid, $itemnumber );
932 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
936 adds a record in biblio table. Datas are in the hash $biblio.
943 my ( $dbh, $biblio ) = @_;
945 $dbh->do('lock tables biblio WRITE');
946 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
948 my $data = $sth->fetchrow_arrayref;
949 my $bibnum = $$data[0] + 1;
952 if ( $biblio->{'seriestitle'} ) { $series = 1 }
955 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
956 serial=?, seriestitle=?, notes=?, abstract=?,
960 $bibnum, $biblio->{'title'},
961 $biblio->{'author'}, $biblio->{'copyrightdate'},
962 $biblio->{'serial'}, $biblio->{'seriestitle'},
963 $biblio->{'notes'}, $biblio->{'abstract'},
964 $biblio->{'unititle'}
968 $dbh->do('unlock tables');
972 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
976 modify a record in biblio table. Datas are in the hash $biblio.
983 my ( $dbh, $biblio ) = @_;
984 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
985 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
986 where biblionumber = ?"
989 $biblio->{'title'}, $biblio->{'author'},
990 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
991 $biblio->{'seriestitle'}, $biblio->{'serial'},
992 $biblio->{'unititle'}, $biblio->{'notes'},
993 $biblio->{frameworkcode},
994 $biblio->{'biblionumber'}
997 return ( $biblio->{'biblionumber'} );
1000 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
1004 modify subtitles in bibliosubtitle table.
1010 sub REALmodsubtitle {
1011 my ( $dbh, $bibnum, $subtitle ) = @_;
1014 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1015 $sth->execute( $subtitle, $bibnum );
1019 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1023 adds or modify additional authors
1024 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1030 sub REALmodaddauthor {
1031 my ( $dbh, $bibnum, @authors ) = @_;
1033 # my $dbh = C4Connect;
1035 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1037 $sth->execute($bibnum);
1039 foreach my $author (@authors) {
1040 if ( $author ne '' ) {
1043 "Insert into additionalauthors set author = ?, biblionumber = ?"
1046 $sth->execute( $author, $bibnum );
1051 } # sub modaddauthor
1053 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1057 modify/adds subjects
1062 sub REALmodsubject {
1063 my ( $dbh, $bibnum, $force, @subject ) = @_;
1065 # my $dbh = C4Connect;
1066 my $count = @subject;
1068 for ( my $i = 0 ; $i < $count ; $i++ ) {
1069 $subject[$i] =~ s/^ //g;
1070 $subject[$i] =~ s/ $//g;
1073 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1075 $sth->execute( $subject[$i] );
1077 if ( my $data = $sth->fetchrow_hashref ) {
1080 if ( $force eq $subject[$i] || $force == 1 ) {
1082 # subject not in aut, chosen to force anway
1083 # so insert into cataloguentry so its in auth file
1086 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1089 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1094 "$subject[$i]\n does not exist in the subject authority file";
1097 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1099 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1101 while ( my $data = $sth2->fetchrow_hashref ) {
1102 $error .= "<br>$data->{'catalogueentry'}";
1111 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1112 $sth->execute($bibnum);
1116 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1118 foreach $query (@subject) {
1119 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1128 =head2 REALmodbiblioitem($dbh, $biblioitem);
1137 sub REALmodbiblioitem {
1138 my ( $dbh, $biblioitem ) = @_;
1141 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1142 itemtype=?, url=?, isbn=?, issn=?,
1143 publishercode=?, publicationyear=?, classification=?, dewey=?,
1144 subclass=?, illus=?, pages=?, volumeddesc=?,
1145 notes=?, size=?, place=?, marc=?,
1147 where biblioitemnumber=?");
1148 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1149 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1150 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1151 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1152 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1153 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1154 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1155 zebra_create($biblioitem->{biblionumber}, $record);
1156 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1159 =head2 REALnewbiblioitem($dbh,$biblioitem);
1163 adds a biblioitem ($biblioitem is a hash with the values)
1169 sub REALnewbiblioitem {
1170 my ( $dbh, $biblioitem ) = @_;
1172 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1173 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1175 my $biblioitemnumber;
1178 $data = $sth->fetchrow_arrayref;
1179 $biblioitemnumber = $$data[0] + 1;
1181 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1182 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1183 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1184 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1185 my $field=$record->field($biblioitemnumberfield);
1186 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1187 $biblioitem->{marc} = $record->as_usmarc();
1188 $biblioitem->{marcxml} = $record->as_xml();
1190 $sth = $dbh->prepare( "insert into biblioitems set
1191 biblioitemnumber = ?, biblionumber = ?,
1192 volume = ?, number = ?,
1193 classification = ?, itemtype = ?,
1195 issn = ?, dewey = ?,
1196 subclass = ?, publicationyear = ?,
1197 publishercode = ?, volumedate = ?,
1198 volumeddesc = ?, illus = ?,
1199 pages = ?, notes = ?,
1201 marc = ?, place = ?,
1205 $biblioitemnumber, $biblioitem->{'biblionumber'},
1206 $biblioitem->{'volume'}, $biblioitem->{'number'},
1207 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1208 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1209 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1210 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1211 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1212 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1213 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1214 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1215 $biblioitem->{'marc'}, $biblioitem->{'place'},
1216 $biblioitem->{marcxml},
1218 $dbh->do("unlock tables");
1219 zebra_create($biblioitem->{biblionumber}, $record);
1220 return ($biblioitemnumber);
1223 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1227 create a new subtitle
1232 sub REALnewsubtitle {
1233 my ( $dbh, $bibnum, $subtitle ) = @_;
1236 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1237 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1241 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1245 create a item. $item is a hash and $barcode the barcode.
1252 my ( $dbh, $item, $barcode ) = @_;
1254 # warn "OLDNEWITEMS";
1256 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1257 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1262 $data = $sth->fetchrow_hashref;
1263 $itemnumber = $data->{'max(itemnumber)'} + 1;
1265 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1266 if ( $item->{'loan'} ) {
1267 $item->{'notforloan'} = $item->{'loan'};
1270 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1271 if ( $item->{'dateaccessioned'} ) {
1272 $sth = $dbh->prepare( "Insert into items set
1273 itemnumber = ?, biblionumber = ?,
1274 multivolumepart = ?,
1275 biblioitemnumber = ?, barcode = ?,
1276 booksellerid = ?, dateaccessioned = ?,
1277 homebranch = ?, holdingbranch = ?,
1278 price = ?, replacementprice = ?,
1279 replacementpricedate = NOW(), datelastseen = NOW(),
1280 multivolume = ?, stack = ?,
1281 itemlost = ?, wthdrawn = ?,
1282 paidfor = ?, itemnotes = ?,
1283 itemcallnumber =?, notforloan = ?,
1288 $itemnumber, $item->{'biblionumber'},
1289 $item->{'multivolumepart'},
1290 $item->{'biblioitemnumber'},$item->{barcode},
1291 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1292 $item->{'homebranch'}, $item->{'holdingbranch'},
1293 $item->{'price'}, $item->{'replacementprice'},
1294 $item->{multivolume}, $item->{stack},
1295 $item->{itemlost}, $item->{wthdrawn},
1296 $item->{paidfor}, $item->{'itemnotes'},
1297 $item->{'itemcallnumber'}, $item->{'notforloan'},
1300 if ( defined $sth->errstr ) {
1301 $error .= $sth->errstr;
1305 $sth = $dbh->prepare( "Insert into items set
1306 itemnumber = ?, biblionumber = ?,
1307 multivolumepart = ?,
1308 biblioitemnumber = ?, barcode = ?,
1309 booksellerid = ?, dateaccessioned = NOW(),
1310 homebranch = ?, holdingbranch = ?,
1311 price = ?, replacementprice = ?,
1312 replacementpricedate = NOW(), datelastseen = NOW(),
1313 multivolume = ?, stack = ?,
1314 itemlost = ?, wthdrawn = ?,
1315 paidfor = ?, itemnotes = ?,
1316 itemcallnumber =?, notforloan = ?,
1321 $itemnumber, $item->{'biblionumber'},
1322 $item->{'multivolumepart'},
1323 $item->{'biblioitemnumber'},$item->{barcode},
1324 $item->{'booksellerid'},
1325 $item->{'homebranch'}, $item->{'holdingbranch'},
1326 $item->{'price'}, $item->{'replacementprice'},
1327 $item->{multivolume}, $item->{stack},
1328 $item->{itemlost}, $item->{wthdrawn},
1329 $item->{paidfor}, $item->{'itemnotes'},
1330 $item->{'itemcallnumber'}, $item->{'notforloan'},
1333 if ( defined $sth->errstr ) {
1334 $error .= $sth->errstr;
1337 # item stored, now, deal with the marc part...
1338 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1339 where biblio.biblionumber=biblioitems.biblionumber and
1340 biblio.biblionumber=?");
1341 $sth->execute($item->{biblionumber});
1342 if ( defined $sth->errstr ) {
1343 $error .= $sth->errstr;
1345 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1346 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1347 my $record = MARC::File::USMARC::decode($rawmarc);
1348 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1349 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1350 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1352 warn $itemnumberfield;
1353 warn $itemrecord->field($itemnumberfield);
1354 my $itemfield = $itemrecord->field($itemnumberfield);
1355 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1356 $record->insert_grouped_field($itemfield);
1357 # save the record into biblioitem
1358 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1359 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1360 if ( defined $sth->errstr ) {
1361 $error .= $sth->errstr;
1363 zebra_create($item->{biblionumber},$record);
1364 $dbh->do('unlock tables');
1365 return ( $itemnumber, $error );
1368 =head2 REALmoditem($dbh,$item);
1379 my ( $dbh, $item ) = @_;
1381 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1382 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1383 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1385 $item->{'barcode'}, $item->{'itemnotes'},
1386 $item->{'itemcallnumber'}, $item->{'notforloan'},
1387 $item->{'location'}, $item->{multivolumepart},
1388 $item->{multivolume}, $item->{stack},
1391 if ( $item->{'lost'} ne '' ) {
1392 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1393 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1394 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1396 $item->{'bibitemnum'}, $item->{'barcode'},
1397 $item->{'itemnotes'}, $item->{'homebranch'},
1398 $item->{'lost'}, $item->{'wthdrawn'},
1399 $item->{'itemcallnumber'}, $item->{'notforloan'},
1400 $item->{'location'}, $item->{multivolumepart},
1401 $item->{multivolume}, $item->{stack},
1404 if ($item->{homebranch}) {
1405 $query.=",homebranch=?";
1406 push @bind, $item->{homebranch};
1408 if ($item->{holdingbranch}) {
1409 $query.=",holdingbranch=?";
1410 push @bind, $item->{holdingbranch};
1413 $query.=" where itemnumber=?";
1414 push @bind,$item->{'itemnum'};
1415 if ( $item->{'replacement'} ne '' ) {
1416 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1418 my $sth = $dbh->prepare($query);
1419 $sth->execute(@bind);
1421 # item stored, now, deal with the marc part...
1422 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1423 where biblio.biblionumber=biblioitems.biblionumber and
1424 biblio.biblionumber=? and
1425 biblioitems.biblioitemnumber=?");
1426 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1427 if ( defined $sth->errstr ) {
1428 $error .= $sth->errstr;
1430 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1431 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1432 my $record = MARC::File::USMARC::decode($rawmarc);
1433 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1434 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1435 # prepare the new item record
1436 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1437 my $itemfield = $itemrecord->field($itemnumberfield);
1438 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1439 # parse all fields fields from the complete record
1440 foreach ($record->field($itemnumberfield)) {
1441 # when the previous field is found, replace by the new one
1442 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1443 $_->replace_with($itemfield);
1446 # $record->insert_grouped_field($itemfield);
1447 # save the record into biblioitem
1448 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1449 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1450 zebra_create($item->biblionumber,$record);
1451 if ( defined $sth->errstr ) {
1452 $error .= $sth->errstr;
1454 $dbh->do('unlock tables');
1459 =head2 REALdelitem($dbh,$itemnum);
1470 my ( $dbh, $itemnum ) = @_;
1472 # my $dbh=C4Connect;
1473 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1474 $sth->execute($itemnum);
1475 my $data = $sth->fetchrow_hashref;
1477 my $query = "Insert into deleteditems set ";
1479 foreach my $temp ( keys %$data ) {
1480 $query .= "$temp = ?,";
1481 push ( @bind, $data->{$temp} );
1486 $sth = $dbh->prepare($query);
1487 $sth->execute(@bind);
1489 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1490 $sth->execute($itemnum);
1496 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1500 deletes a biblioitem
1501 NOTE : not standard sub name. Should be REALdelbiblioitem()
1507 sub REALdelbiblioitem {
1508 my ( $dbh, $biblioitemnumber ) = @_;
1510 # my $dbh = C4Connect;
1511 my $sth = $dbh->prepare( "Select * from biblioitems
1512 where biblioitemnumber = ?"
1516 $sth->execute($biblioitemnumber);
1518 if ( $results = $sth->fetchrow_hashref ) {
1522 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1523 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1524 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1528 $results->{biblioitemnumber}, $results->{biblionumber},
1529 $results->{volume}, $results->{number},
1530 $results->{classification}, $results->{itemtype},
1531 $results->{isbn}, $results->{issn},
1532 $results->{dewey}, $results->{subclass},
1533 $results->{publicationyear}, $results->{publishercode},
1534 $results->{volumedate}, $results->{volumeddesc},
1535 $results->{timestamp}, $results->{illus},
1536 $results->{pages}, $results->{notes},
1537 $results->{size}, $results->{url},
1541 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1542 $sth2->execute($biblioitemnumber);
1547 # Now delete all the items attached to the biblioitem
1548 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1549 $sth->execute($biblioitemnumber);
1551 while ( my $data = $sth->fetchrow_hashref ) {
1552 my $query = "Insert into deleteditems set ";
1554 foreach my $temp ( keys %$data ) {
1555 $query .= "$temp = ?,";
1556 push ( @bind, $data->{$temp} );
1559 my $sth2 = $dbh->prepare($query);
1560 $sth2->execute(@bind);
1563 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1564 $sth->execute($biblioitemnumber);
1568 } # sub deletebiblioitem
1570 =head2 REALdelbiblio($dbh,$biblio);
1581 my ( $dbh, $biblio ) = @_;
1582 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1583 $sth->execute($biblio);
1584 if ( my $data = $sth->fetchrow_hashref ) {
1586 my $query = "Insert into deletedbiblio set ";
1588 foreach my $temp ( keys %$data ) {
1589 $query .= "$temp = ?,";
1590 push ( @bind, $data->{$temp} );
1593 #replacing the last , by ",?)"
1595 $sth = $dbh->prepare($query);
1596 $sth->execute(@bind);
1598 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1599 $sth->execute($biblio);
1605 =head2 $number = itemcount($biblio);
1609 returns the number of items attached to a biblio
1617 my $dbh = C4::Context->dbh;
1620 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1621 $sth->execute($biblio);
1622 my $data = $sth->fetchrow_hashref;
1624 return ( $data->{'count(*)'} );
1627 =head2 $biblionumber = newbiblio($biblio);
1631 create a biblio. The parameter is a hash
1639 my $dbh = C4::Context->dbh;
1640 my $bibnum = REALnewbiblio( $dbh, $biblio );
1641 # finds new (MARC bibid
1642 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1643 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1644 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1648 =head2 $biblionumber = &modbiblio($biblio);
1652 Update a biblio record.
1654 C<$biblio> is a reference-to-hash whose keys are the fields in the
1655 biblio table in the Koha database. All fields must be present, not
1656 just the ones you wish to change.
1658 C<&modbiblio> updates the record defined by
1659 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1661 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1670 my $dbh = C4::Context->dbh;
1671 my $biblionumber=REALmodbiblio($dbh,$biblio);
1672 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1673 # finds new (MARC bibid
1674 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1675 MARCmodbiblio($dbh,$bibid,$record,"",0);
1676 return($biblionumber);
1679 =head2 &modsubtitle($biblionumber, $subtitle);
1683 Sets the subtitle of a book.
1685 C<$biblionumber> is the biblionumber of the book to modify.
1687 C<$subtitle> is the new subtitle.
1694 my ( $bibnum, $subtitle ) = @_;
1695 my $dbh = C4::Context->dbh;
1696 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1699 =head2 &modaddauthor($biblionumber, $author);
1703 Replaces all additional authors for the book with biblio number
1704 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1705 C<&modaddauthor> deletes all additional authors.
1712 my ( $bibnum, @authors ) = @_;
1713 my $dbh = C4::Context->dbh;
1714 &REALmodaddauthor( $dbh, $bibnum, @authors );
1715 } # sub modaddauthor
1717 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1721 $force - a subject to force
1722 $error - Error message, or undef if successful.
1729 my ( $bibnum, $force, @subject ) = @_;
1730 my $dbh = C4::Context->dbh;
1731 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1733 # When MARC is off, ensures that the MARC biblio table gets updated with new
1734 # subjects, of course, it deletes the biblio in marc, and then recreates.
1735 # This check is to ensure that no MARC data exists to lose.
1736 # if (C4::Context->preference("MARC") eq '0'){
1737 # warn "in modSUBJECT";
1738 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1739 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1740 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1746 =head2 modbibitem($biblioitem);
1750 modify a biblioitem. The parameter is a hash
1757 my ($biblioitem) = @_;
1758 my $dbh = C4::Context->dbh;
1759 &REALmodbiblioitem( $dbh, $biblioitem );
1762 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1766 create a biblioitem, the parameter is a hash
1773 my ($biblioitem) = @_;
1774 my $dbh = C4::Context->dbh;
1775 # add biblio information to the hash
1776 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1777 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1778 my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1779 return ($bibitemnum);
1782 =head2 newsubtitle($biblionumber,$subtitle);
1786 insert a subtitle for $biblionumber biblio
1794 my ( $bibnum, $subtitle ) = @_;
1795 my $dbh = C4::Context->dbh;
1796 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1799 =head2 $errors = newitems($item, @barcodes);
1803 insert items ($item is a hash)
1811 my ( $item, @barcodes ) = @_;
1812 my $dbh = C4::Context->dbh;
1816 foreach my $barcode (@barcodes) {
1817 # add items, one by one for each barcode.
1819 $oneitem->{barcode}= $barcode;
1820 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1821 $oneitem->{marc} = $MARCitem->as_usmarc;
1822 ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
1823 # $errors .= $error;
1824 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1829 =head2 moditem($item);
1833 modify an item ($item is a hash with all item informations)
1842 my $dbh = C4::Context->dbh;
1843 &REALmoditem( $dbh, $item );
1845 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1847 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1848 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1851 =head2 $error = checkitems($count,@barcodes);
1855 check for each @barcode entry that the barcode is not a duplicate
1862 my ( $count, @barcodes ) = @_;
1863 my $dbh = C4::Context->dbh;
1865 my $sth = $dbh->prepare("Select * from items where barcode=?");
1866 for ( my $i = 0 ; $i < $count ; $i++ ) {
1867 $barcodes[$i] = uc $barcodes[$i];
1868 $sth->execute( $barcodes[$i] );
1869 if ( my $data = $sth->fetchrow_hashref ) {
1870 $error .= " Duplicate Barcode: $barcodes[$i]";
1877 =head2 $delitem($itemnum);
1881 delete item $itemnum being the item number to delete
1889 my $dbh = C4::Context->dbh;
1890 &REALdelitem( $dbh, $itemnum );
1893 =head2 deletebiblioitem($biblioitemnumber);
1897 delete the biblioitem $biblioitemnumber
1903 sub deletebiblioitem {
1904 my ($biblioitemnumber) = @_;
1905 my $dbh = C4::Context->dbh;
1906 &REALdelbiblioitem( $dbh, $biblioitemnumber );
1907 } # sub deletebiblioitem
1909 =head2 delbiblio($biblionumber)
1913 delete biblio $biblionumber
1921 my $dbh = C4::Context->dbh;
1922 &REALdelbiblio( $dbh, $biblio );
1923 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
1924 &MARCdelbiblio( $dbh, $bibid, 0 );
1927 =head2 ($count,@results) = getbiblio($biblionumber);
1931 return an array with hash of biblios.
1933 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
1940 my ($biblionumber) = @_;
1941 my $dbh = C4::Context->dbh;
1942 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
1944 # || die "Cannot prepare $query\n" . $dbh->errstr;
1948 $sth->execute($biblionumber);
1950 # || die "Cannot execute $query\n" . $sth->errstr;
1951 while ( my $data = $sth->fetchrow_hashref ) {
1952 $results[$count] = $data;
1957 return ( $count, @results );
1962 $data = &bibdata($biblionumber, $type);
1964 Returns information about the book with the given biblionumber.
1966 C<$type> is ignored.
1968 C<&bibdata> returns a reference-to-hash. The keys are the fields in
1969 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
1972 In addition, C<$data-E<gt>{subject}> is the list of the book's
1973 subjects, separated by C<" , "> (space, comma, space).
1975 If there are multiple biblioitems with the given biblionumber, only
1976 the first one is considered.
1981 my ($bibnum, $type) = @_;
1982 my $dbh = C4::Context->dbh;
1983 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
1985 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
1986 left join bibliosubtitle on
1987 biblio.biblionumber = bibliosubtitle.biblionumber
1988 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
1989 where biblio.biblionumber = ?
1991 $sth->execute($bibnum);
1993 $data = $sth->fetchrow_hashref;
1995 # handle management of repeated subtitle
1996 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
1997 $sth->execute($bibnum);
1999 while (my $dat = $sth->fetchrow_hashref){
2001 $line{subtitle} = $dat->{subtitle};
2002 push @subtitles, \%line;
2004 $data->{subtitles} = \@subtitles;
2006 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2007 $sth->execute($bibnum);
2009 while (my $dat = $sth->fetchrow_hashref){
2011 $line{subject} = $dat->{'subject'};
2012 push @subjects, \%line;
2014 $data->{subjects} = \@subjects;
2016 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2017 $sth->execute($bibnum);
2018 while (my $dat = $sth->fetchrow_hashref){
2019 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2021 chop $data->{'additionalauthors'};
2022 chop $data->{'additionalauthors'};
2023 chop $data->{'additionalauthors'};
2028 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
2032 return an array with hash of biblioitemss.
2034 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2041 my ($biblioitemnum) = @_;
2042 my $dbh = C4::Context->dbh;
2043 my $sth = $dbh->prepare( "Select * from biblioitems where
2044 biblioitemnumber = ?"
2049 $sth->execute($biblioitemnum);
2051 while ( my $data = $sth->fetchrow_hashref ) {
2052 $results[$count] = $data;
2057 return ( $count, @results );
2058 } # sub getbiblioitem
2060 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2064 return an array with hash of biblioitems for the given biblionumber.
2070 sub getbiblioitembybiblionumber {
2071 my ($biblionumber) = @_;
2072 my $dbh = C4::Context->dbh;
2073 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2077 $sth->execute($biblionumber);
2079 while ( my $data = $sth->fetchrow_hashref ) {
2080 $results[$count] = $data;
2085 return ( $count, @results );
2088 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2092 returns an array with hash of items
2098 sub getitemsbybiblioitem {
2099 my ($biblioitemnum) = @_;
2100 my $dbh = C4::Context->dbh;
2101 my $sth = $dbh->prepare( "Select * from items, biblio where
2102 biblio.biblionumber = items.biblionumber and biblioitemnumber
2106 # || die "Cannot prepare $query\n" . $dbh->errstr;
2110 $sth->execute($biblioitemnum);
2112 # || die "Cannot execute $query\n" . $sth->errstr;
2113 while ( my $data = $sth->fetchrow_hashref ) {
2114 $results[$count] = $data;
2119 return ( $count, @results );
2120 } # sub getitemsbybiblioitem
2124 @results = &ItemInfo($env, $biblionumber, $type);
2126 Returns information about books with the given biblionumber.
2128 C<$type> may be either C<intra> or anything else. If it is not set to
2129 C<intra>, then the search will exclude lost, very overdue, and
2134 C<&ItemInfo> returns a list of references-to-hash. Each element
2135 contains a number of keys. Most of them are table items from the
2136 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2137 Koha database. Other keys include:
2141 =item C<$data-E<gt>{branchname}>
2143 The name (not the code) of the branch to which the book belongs.
2145 =item C<$data-E<gt>{datelastseen}>
2147 This is simply C<items.datelastseen>, except that while the date is
2148 stored in YYYY-MM-DD format in the database, here it is converted to
2149 DD/MM/YYYY format. A NULL date is returned as C<//>.
2151 =item C<$data-E<gt>{datedue}>
2153 =item C<$data-E<gt>{class}>
2155 This is the concatenation of C<biblioitems.classification>, the book's
2156 Dewey code, and C<biblioitems.subclass>.
2158 =item C<$data-E<gt>{ocount}>
2160 I think this is the number of copies of the book available.
2162 =item C<$data-E<gt>{order}>
2164 If this is set, it is set to C<One Order>.
2171 my ($env,$biblionumber,$type) = @_;
2172 my $dbh = C4::Context->dbh;
2173 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2174 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2175 WHERE items.biblionumber = ?
2176 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2177 AND biblio.biblionumber = items.biblionumber";
2178 $query .= " order by items.dateaccessioned desc";
2179 my $sth=$dbh->prepare($query);
2180 $sth->execute($biblionumber);
2183 while (my $data=$sth->fetchrow_hashref){
2185 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2186 $isth->execute($data->{'itemnumber'});
2187 if (my $idata=$isth->fetchrow_hashref){
2188 $data->{borrowernumber} = $idata->{borrowernumber};
2189 $data->{cardnumber} = $idata->{cardnumber};
2190 $datedue = format_date($idata->{'date_due'});
2192 if ($datedue eq ''){
2193 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2199 #get branch information.....
2200 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2201 $bsth->execute($data->{'holdingbranch'});
2202 if (my $bdata=$bsth->fetchrow_hashref){
2203 $data->{'branchname'} = $bdata->{'branchname'};
2205 my $date=format_date($data->{'datelastseen'});
2206 $data->{'datelastseen'}=$date;
2207 $data->{'datedue'}=$datedue;
2208 # get notforloan complete status if applicable
2209 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2210 $sthnflstatus->execute;
2211 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2212 if ($authorised_valuecode) {
2213 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2214 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2215 my ($lib) = $sthnflstatus->fetchrow;
2216 $data->{notforloan} = $lib;
2227 ($count, @results) = &bibitems($biblionumber);
2229 Given the biblionumber for a book, C<&bibitems> looks up that book's
2230 biblioitems (different publications of the same book, the audio book
2231 and film versions, etc.).
2233 C<$count> is the number of elements in C<@results>.
2235 C<@results> is an array of references-to-hash; the keys are the fields
2236 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2237 addition, C<itemlost> indicates the availability of the item: if it is
2238 "2", then all copies of the item are long overdue; if it is "1", then
2239 all copies are lost; otherwise, there is at least one copy available.
2245 my $dbh = C4::Context->dbh;
2246 my $sth = $dbh->prepare("SELECT biblioitems.*,
2248 MIN(items.itemlost) as itemlost,
2249 MIN(items.dateaccessioned) as dateaccessioned
2250 FROM biblioitems, itemtypes, items
2251 WHERE biblioitems.biblionumber = ?
2252 AND biblioitems.itemtype = itemtypes.itemtype
2253 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2254 GROUP BY items.biblioitemnumber");
2257 $sth->execute($bibnum);
2258 while (my $data = $sth->fetchrow_hashref) {
2259 $results[$count] = $data;
2263 return($count, @results);
2269 $itemdata = &bibitemdata($biblioitemnumber);
2271 Looks up the biblioitem with the given biblioitemnumber. Returns a
2272 reference-to-hash. The keys are the fields from the C<biblio>,
2273 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2274 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2280 my $dbh = C4::Context->dbh;
2281 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");
2284 $sth->execute($bibitem);
2286 $data = $sth->fetchrow_hashref;
2293 =item getbibliofromitemnumber
2295 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2297 Looks up the item with the given itemnumber.
2299 C<$env> and C<$dbh> are ignored.
2301 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2302 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2307 sub getbibliofromitemnumber {
2308 my ($env,$dbh,$itemnumber) = @_;
2309 $dbh = C4::Context->dbh;
2310 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2311 where items.itemnumber = ?
2312 and biblio.biblionumber = items.biblionumber
2313 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2315 $sth->execute($itemnumber);
2316 my $data=$sth->fetchrow_hashref;
2323 @barcodes = &barcodes($biblioitemnumber);
2325 Given a biblioitemnumber, looks up the corresponding items.
2327 Returns an array of references-to-hash; the keys are C<barcode> and
2330 The returned items include very overdue items, but not lost ones.
2335 #called from request.pl
2336 my ($biblioitemnumber)=@_;
2337 my $dbh = C4::Context->dbh;
2338 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2339 WHERE biblioitemnumber = ?
2340 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2341 $sth->execute($biblioitemnumber);
2344 while (my $data=$sth->fetchrow_hashref){
2345 $barcodes[$i]=$data;
2355 $item = &itemdata($barcode);
2357 Looks up the item with the given barcode, and returns a
2358 reference-to-hash containing information about that item. The keys of
2359 the hash are the fields from the C<items> and C<biblioitems> tables in
2364 sub get_item_from_barcode {
2366 my $dbh = C4::Context->dbh;
2367 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2368 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2369 $sth->execute($barcode);
2370 my $data=$sth->fetchrow_hashref;
2378 @issues = &itemissues($biblioitemnumber, $biblio);
2380 Looks up information about who has borrowed the bookZ<>(s) with the
2381 given biblioitemnumber.
2383 C<$biblio> is ignored.
2385 C<&itemissues> returns an array of references-to-hash. The keys
2386 include the fields from the C<items> table in the Koha database.
2387 Additional keys include:
2393 If the item is currently on loan, this gives the due date.
2395 If the item is not on loan, then this is either "Available" or
2396 "Cancelled", if the item has been withdrawn.
2400 If the item is currently on loan, this gives the card number of the
2401 patron who currently has the item.
2403 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2405 These give the timestamp for the last three times the item was
2408 =item C<card0>, C<card1>, C<card2>
2410 The card number of the last three patrons who borrowed this item.
2412 =item C<borrower0>, C<borrower1>, C<borrower2>
2414 The borrower number of the last three patrons who borrowed this item.
2421 my ($bibitem, $biblio)=@_;
2422 my $dbh = C4::Context->dbh;
2423 # FIXME - If this function die()s, the script will abort, and the
2424 # user won't get anything; depending on how far the script has
2425 # gotten, the user might get a blank page. It would be much better
2426 # to at least print an error message. The easiest way to do this
2427 # is to set $SIG{__DIE__}.
2428 my $sth = $dbh->prepare("Select * from items where
2429 items.biblioitemnumber = ?")
2430 || die $dbh->errstr;
2434 $sth->execute($bibitem)
2435 || die $sth->errstr;
2437 while (my $data = $sth->fetchrow_hashref) {
2438 # Find out who currently has this item.
2439 # FIXME - Wouldn't it be better to do this as a left join of
2440 # some sort? Currently, this code assumes that if
2441 # fetchrow_hashref() fails, then the book is on the shelf.
2442 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2443 # database server crash), not just because no items match the
2445 my $sth2 = $dbh->prepare("select * from issues,borrowers
2446 where itemnumber = ?
2447 and returndate is NULL
2448 and issues.borrowernumber = borrowers.borrowernumber");
2450 $sth2->execute($data->{'itemnumber'});
2451 if (my $data2 = $sth2->fetchrow_hashref) {
2452 $data->{'date_due'} = $data2->{'date_due'};
2453 $data->{'card'} = $data2->{'cardnumber'};
2454 $data->{'borrower'} = $data2->{'borrowernumber'};
2456 if ($data->{'wthdrawn'} eq '1') {
2457 $data->{'date_due'} = 'Cancelled';
2459 $data->{'date_due'} = 'Available';
2465 # Find the last 3 people who borrowed this item.
2466 $sth2 = $dbh->prepare("select * from issues, borrowers
2467 where itemnumber = ?
2468 and issues.borrowernumber = borrowers.borrowernumber
2469 and returndate is not NULL
2470 order by returndate desc,timestamp desc") || die $dbh->errstr;
2471 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2472 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2473 if (my $data2 = $sth2->fetchrow_hashref) {
2474 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2475 $data->{"card$i2"} = $data2->{'cardnumber'};
2476 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2481 $results[$i] = $data;
2491 ($count, $subjects) = &getsubject($biblionumber);
2493 Looks up the subjects of the book with the given biblionumber. Returns
2494 a two-element list. C<$subjects> is a reference-to-array, where each
2495 element is a subject of the book, and C<$count> is the number of
2496 elements in C<$subjects>.
2502 my $dbh = C4::Context->dbh;
2503 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2504 $sth->execute($bibnum);
2507 while (my $data=$sth->fetchrow_hashref){
2512 return($i,\@results);
2517 ($count, $authors) = &getaddauthor($biblionumber);
2519 Looks up the additional authors for the book with the given
2522 Returns a two-element list. C<$authors> is a reference-to-array, where
2523 each element is an additional author, and C<$count> is the number of
2524 elements in C<$authors>.
2530 my $dbh = C4::Context->dbh;
2531 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2532 $sth->execute($bibnum);
2535 while (my $data=$sth->fetchrow_hashref){
2540 return($i,\@results);
2546 ($count, $subtitles) = &getsubtitle($biblionumber);
2548 Looks up the subtitles for the book with the given biblionumber.
2550 Returns a two-element list. C<$subtitles> is a reference-to-array,
2551 where each element is a subtitle, and C<$count> is the number of
2552 elements in C<$subtitles>.
2558 my $dbh = C4::Context->dbh;
2559 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2560 $sth->execute($bibnum);
2563 while (my $data=$sth->fetchrow_hashref){
2568 return($i,\@results);
2574 ($count, @websites) = &getwebsites($biblionumber);
2576 Looks up the web sites pertaining to the book with the given
2579 C<$count> is the number of elements in C<@websites>.
2581 C<@websites> is an array of references-to-hash; the keys are the
2582 fields from the C<websites> table in the Koha database.
2585 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2586 #(with add / modify / delete subs)
2589 my ($biblionumber) = @_;
2590 my $dbh = C4::Context->dbh;
2591 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2595 $sth->execute($biblionumber);
2596 while (my $data = $sth->fetchrow_hashref) {
2597 # FIXME - The URL scheme shouldn't be stripped off, at least
2598 # not here, since it's part of the URL, and will be useful in
2599 # constructing a link to the site. If you don't want the user
2600 # to see the "http://" part, strip that off when building the
2602 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2604 $results[$count] = $data;
2609 return($count, @results);
2612 =item getwebbiblioitems
2614 ($count, @results) = &getwebbiblioitems($biblionumber);
2616 Given a book's biblionumber, looks up the web versions of the book
2617 (biblioitems with itemtype C<WEB>).
2619 C<$count> is the number of items in C<@results>. C<@results> is an
2620 array of references-to-hash; the keys are the items from the
2621 C<biblioitems> table of the Koha database.
2625 sub getwebbiblioitems {
2626 my ($biblionumber) = @_;
2627 my $dbh = C4::Context->dbh;
2628 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2629 and itemtype = 'WEB'");
2633 $sth->execute($biblionumber);
2634 while (my $data = $sth->fetchrow_hashref) {
2635 $data->{'url'} =~ s/^http:\/\///;
2636 $results[$count] = $data;
2641 return($count, @results);
2642 } # sub getwebbiblioitems
2646 # converts ISO 5426 coded string to ISO 8859-1
2647 # sloppy code : should be improved in next issue
2648 my ( $string, $encoding ) = @_;
2651 # $encoding = C4::Context->preference("marcflavour") unless $encoding;
2652 if ( $encoding eq "UNIMARC" ) {
2721 # this handles non-sorting blocks (if implementation requires this)
2722 $string = nsb_clean($_);
2724 elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
2725 if (/[\xc1-\xff]/) {
2778 # this handles non-sorting blocks (if implementation requires this)
2779 $string = nsb_clean($_);
2786 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2787 my $NSE = '\x89'; # NSE : Non Sorting Block end
2788 # handles non sorting blocks
2792 s/[ ]{0,1}$NSE/) /gm;
2799 my $dbh = C4::Context->dbh;
2800 my $result = MARCmarc2koha($dbh,$record,'');
2802 my ($biblionumber,$bibid,$title);
2803 # search duplicate on ISBN, easy and fast...
2804 if ($result->{isbn}) {
2805 $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=?");
2806 $sth->execute($result->{'isbn'});
2807 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2808 return $biblionumber,$bibid,$title if ($biblionumber);
2810 # a more complex search : build a request for SearchMarc::catalogsearch()
2811 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2812 # search on biblio.title
2813 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2814 if ($record->field($tag)) {
2815 if ($record->field($tag)->subfields($subfield)) {
2816 push @tags, "'".$tag.$subfield."'";
2817 push @and_or, "and";
2818 push @excluding, "";
2819 push @operator, "contains";
2820 push @value, $record->field($tag)->subfield($subfield);
2821 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2824 # ... and on biblio.author
2825 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2826 if ($record->field($tag)) {
2827 if ($record->field($tag)->subfields($subfield)) {
2828 push @tags, "'".$tag.$subfield."'";
2829 push @and_or, "and";
2830 push @excluding, "";
2831 push @operator, "contains";
2832 push @value, $record->field($tag)->subfield($subfield);
2833 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2836 # ... and on publicationyear.
2837 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2838 if ($record->field($tag)) {
2839 if ($record->field($tag)->subfields($subfield)) {
2840 push @tags, "'".$tag.$subfield."'";
2841 push @and_or, "and";
2842 push @excluding, "";
2843 push @operator, "=";
2844 push @value, $record->field($tag)->subfield($subfield);
2845 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2849 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2850 if ($record->field($tag)) {
2851 if ($record->field($tag)->subfields($subfield)) {
2852 push @tags, "'".$tag.$subfield."'";
2853 push @and_or, "and";
2854 push @excluding, "";
2855 push @operator, "=";
2856 push @value, $record->field($tag)->subfield($subfield);
2857 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2860 # ... and on publisher.
2861 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2862 if ($record->field($tag)) {
2863 if ($record->field($tag)->subfields($subfield)) {
2864 push @tags, "'".$tag.$subfield."'";
2865 push @and_or, "and";
2866 push @excluding, "";
2867 push @operator, "=";
2868 push @value, $record->field($tag)->subfield($subfield);
2869 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2872 # ... and on volume.
2873 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2874 if ($record->field($tag)) {
2875 if ($record->field($tag)->subfields($subfield)) {
2876 push @tags, "'".$tag.$subfield."'";
2877 push @and_or, "and";
2878 push @excluding, "";
2879 push @operator, "=";
2880 push @value, $record->field($tag)->subfield($subfield);
2881 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2885 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2886 # there is at least 1 result => return the 1st one
2888 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2889 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2891 # no result, returns nothing
2898 if(substr($isbn, 0, 1) <=7) {
2899 $seg1 = substr($isbn, 0, 1);
2900 } elsif(substr($isbn, 0, 2) <= 94) {
2901 $seg1 = substr($isbn, 0, 2);
2902 } elsif(substr($isbn, 0, 3) <= 995) {
2903 $seg1 = substr($isbn, 0, 3);
2904 } elsif(substr($isbn, 0, 4) <= 9989) {
2905 $seg1 = substr($isbn, 0, 4);
2907 $seg1 = substr($isbn, 0, 5);
2909 my $x = substr($isbn, length($seg1));
2911 if(substr($x, 0, 2) <= 19) {
2912 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2913 $seg2 = substr($x, 0, 2);
2914 } elsif(substr($x, 0, 3) <= 699) {
2915 $seg2 = substr($x, 0, 3);
2916 } elsif(substr($x, 0, 4) <= 8399) {
2917 $seg2 = substr($x, 0, 4);
2918 } elsif(substr($x, 0, 5) <= 89999) {
2919 $seg2 = substr($x, 0, 5);
2920 } elsif(substr($x, 0, 6) <= 9499999) {
2921 $seg2 = substr($x, 0, 6);
2923 $seg2 = substr($x, 0, 7);
2925 my $seg3=substr($x,length($seg2));
2926 $seg3=substr($seg3,0,length($seg3)-1) ;
2927 my $seg4 = substr($x, -1, 1);
2928 return "$seg1-$seg2-$seg3-$seg4";
2932 END { } # module clean-up code here (global destructor)
2938 Koha Developement team <info@koha.org>
2940 Paul POULAIN paul.poulain@free.fr
2946 # Revision 1.142 2006/02/16 20:49:56 kados
2947 # destroy a connection after we're done -- we really should just have one
2948 # connection object and not destroy it until the whole transaction is
2949 # finished -- but this will do for now
2951 # Revision 1.141 2006/02/16 19:47:22 rangi
2952 # Trying to error trap a little more.
2954 # Revision 1.140 2006/02/14 21:36:03 kados
2955 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
2956 # also adding diagnostic error if not able to connect to Zebra
2958 # Revision 1.139 2006/02/14 19:53:25 rangi
2959 # Just a little missing my
2961 # Seems to be working great Paul, and I like what you did with zebradb
2963 # Revision 1.138 2006/02/14 11:25:22 tipaul
2964 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
2966 # Revision 1.137 2006/02/13 16:34:26 tipaul
2967 # fixing some warnings (perl -w should be quiet)
2969 # Revision 1.136 2006/01/10 17:01:29 tipaul
2970 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
2972 # Revision 1.135 2006/01/06 16:39:37 tipaul
2973 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
2974 # Seems not to break too many things, but i'm probably wrong here.
2975 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
2977 # - removing useless directories (koha-html and koha-plucene)
2979 # Revision 1.134 2006/01/04 15:54:55 tipaul
2980 # utf8 is a : go for beta test in HEAD.
2981 # some explanations :
2982 # - 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.
2983 # - *-top.inc will show the pages in utf8
2984 # - 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.
2985 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
2987 # Revision 1.133 2005/12/12 14:25:51 thd
2990 # Reverse array filled with elements from repeated subfields
2991 # to avoid last to first concatenation of elements in Koha DB.-
2993 # Revision 1.132 2005-10-26 09:12:33 tipaul
2994 # big commit, still breaking things...
2996 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
2997 # * code cleaning (cleaning warnings from perl -w) continued
2999 # Revision 1.131 2005/09/22 10:01:45 tipaul
3000 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3002 # Revision 1.130 2005/09/02 14:34:14 tipaul
3003 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3004 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3005 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3007 # Revision 1.129 2005/08/12 13:50:31 tipaul
3008 # removing useless sub declarations
3010 # Revision 1.128 2005/08/11 16:12:47 tipaul
3011 # Playing with the zebra...
3013 # * go to koha cvs home directory
3014 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3015 # * put your zebra.cfg files here & create your database.
3016 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3017 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3020 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3021 # * deletion still not work
3022 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3024 # recordId: (bib1,Local-number)
3028 # elm 090 Local-number -
3029 # elm 090/? Local-number -
3030 # elm 090/?/9 Local-number !:w
3032 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3034 # Revision 1.127 2005/08/11 14:37:32 tipaul
3036 # * removing useless subs
3037 # * removing some subs that are also elsewhere
3038 # * 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)
3040 # Revision 1.126 2005/08/11 09:13:28 tipaul
3041 # just removing useless subs (a lot !!!) for code cleaning
3043 # Revision 1.125 2005/08/11 09:00:07 tipaul
3044 # Ok guys, this time, it seems that item add and modif begin working as expected...
3045 # Still a lot of bugs to fix, of course
3047 # Revision 1.124 2005/08/10 10:21:15 tipaul
3048 # continuing the road to zebra :
3049 # - the biblio add begins to work.
3050 # - the biblio modif begins to work.
3052 # (still without doing anything on zebra)
3053 # (no new change in updatedatabase)
3055 # Revision 1.123 2005/08/09 14:10:28 tipaul
3056 # 1st commit to go to zebra.
3057 # don't update your cvs if you want to have a working head...
3059 # this commit contains :
3060 # * 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...
3061 # * 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.
3062 # * other files : get rid of bibid and use biblionumber instead.
3065 # * does not do anything on zebra yet.
3066 # * if you rename marc_subfield_table, you can't search anymore.
3067 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3068 # * 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 ;-) )
3070 # 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
3071 # 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.
3073 # tipaul cutted previous commit notes