3 # Copyright 2000-2002 Katipo Communications
5 # This file is part of Koha.
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License along with
17 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
18 # Suite 330, Boston, MA 02111-1307 USA
26 use MARC::File::USMARC;
29 use vars qw($VERSION @ISA @EXPORT);
31 # set the version for version checking
37 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
38 # as the old-style API and the NEW one are the only public functions.
41 &newbiblio &newbiblioitem
42 &newsubject &newsubtitle &newitems
44 &modbiblio &checkitems &modbibitem
45 &modsubtitle &modsubject &modaddauthor &moditem
47 &delitem &deletebiblioitem &delbiblio
49 &getbiblio &bibdata &bibitems &bibitemdata
50 &barcodes &ItemInfo &itemdata &itemissues &itemcount
51 &getsubject &getaddauthor &getsubtitle
52 &getwebbiblioitems &getwebsites
53 &getbiblioitembybiblionumber
54 &getbiblioitem &getitemsbybiblioitem
56 &MARCfind_marc_from_kohafield
57 &MARCfind_frameworkcode
58 &find_biblioitemnumber
61 &NEWnewbiblio &NEWnewitem
62 &NEWmodbiblio &NEWmoditem
63 &NEWdelbiblio &NEWdelitem
64 &NEWmodbiblioframework
66 &MARCkoha2marcBiblio &MARCmarc2koha
67 &MARCkoha2marcItem &MARChtml2marc
68 &MARCgetbiblio &MARCgetitem
78 C4::Biblio - acquisition, catalog management functions
82 ( lot of changes for Koha 3.0)
84 Koha 1.2 and previous version used a specific API to manage biblios. This API uses old-DB style parameters.
85 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors, bibliosubject and bibliosubtitle where applicable)
87 In Koha 2.0, we introduced a MARC-DB.
89 In Koha 3.0 we removed this MARC-DB for search as we wanted to use Zebra as search system.
91 So in Koha 3.0, saving a record means :
92 - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items informations.
93 - storing the "decoded information" in biblio/biblioitems/items as previously.
94 - using zebra to manage search & indexing on the MARC datas.
96 In Koha, there is a systempreference saying "MARC=ON" or "MARC=OFF"
98 * MARC=ON : when MARC=ON, koha uses a MARC::Record object (in sub parameters). Saving informations in the DB means :
99 - transform the MARC record into a hash
100 - add the raw marc record into the hash
101 - store them & update zebra
103 * MARC=OFF : when MARC=OFF, koha uses a hash object (in sub parameters). Saving informations in the DB means :
104 - transform the hash into a MARC record
105 - add the raw marc record into the hash
106 - store them and update zebra
109 That's why we need 3 types of subs :
113 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
115 =head2 NEWxxx related subs
119 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.
121 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. they sometimes requires another parameter.
125 =head2 something_elsexxx related subs
129 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.
131 all subs requires/use $dbh as 1st parameter and a hash as 2nd parameter.
140 my ($biblionumber,$record) = @_;
141 # create the iso2709 file for zebra
142 # my $cgidir = C4::Context->intranetdir ."/cgi-bin";
143 # unless (opendir(DIR, "$cgidir")) {
144 # $cgidir = C4::Context->intranetdir."/";
147 # my $filename = $cgidir."/zebra/biblios/BIBLIO".$biblionumber."iso2709";
148 # open F,"> $filename";
149 # print F $record->as_usmarc();
151 # my $res = system("cd $cgidir/zebra;/usr/local/bin/zebraidx update biblios");
153 warn "zebra_create : $biblionumber =".$record->as_formatted;
155 $Zconn = new ZOOM::Connection(C4::Context->config("zebradb"));
157 $Zconn->option(cqlfile => C4::Context->config("intranetdir")."/zebra/pqf.properties");
158 # my $record = XMLgetbiblio($dbh,$biblionumber);
159 my $Zpackage = $Zconn->package();
160 $Zpackage->option(action => "specialUpdate");
161 $Zpackage->option(record => $record->as_xml());
162 $Zpackage->send("update");
165 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
169 2nd param is 1 for liblibrarian and 0 for libopac
170 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
172 returns a hash with all values for all fields and subfields for a given MARC framework :
173 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
175 ->{mandatory} = $mandatory;
176 ->{repeatable} = $repeatable;
177 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
179 ->{mandatory} = $mandatory;
180 ->{repeatable} = $repeatable;
181 ->{authorised_value} = $authorised_value;
182 ->{authtypecode} = $authtypecode;
183 ->{value_builder} = $value_builder;
184 ->{kohafield} = $kohafield;
185 ->{seealso} = $seealso;
186 ->{hidden} = $hidden;
195 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
196 $frameworkcode = "" unless $frameworkcode;
197 $forlibrarian = 1 unless $forlibrarian;
199 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
201 # check that framework exists
204 "select count(*) from marc_tag_structure where frameworkcode=?");
205 $sth->execute($frameworkcode);
206 my ($total) = $sth->fetchrow;
207 $frameworkcode = "" unless ( $total > 0 );
210 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
212 $sth->execute($frameworkcode);
213 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
215 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
216 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
217 $res->{$tag}->{tab} = ""; # XXX
218 $res->{$tag}->{mandatory} = $mandatory;
219 $res->{$tag}->{repeatable} = $repeatable;
224 "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"
226 $sth->execute($frameworkcode);
229 my $authorised_value;
239 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
240 $mandatory, $repeatable, $authorised_value, $authtypecode,
241 $value_builder, $kohafield, $seealso, $hidden,
246 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
247 $res->{$tag}->{$subfield}->{tab} = $tab;
248 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
249 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
250 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
251 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
252 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
253 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
254 $res->{$tag}->{$subfield}->{seealso} = $seealso;
255 $res->{$tag}->{$subfield}->{hidden} = $hidden;
256 $res->{$tag}->{$subfield}->{isurl} = $isurl;
257 $res->{$tag}->{$subfield}->{link} = $link;
262 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
266 finds MARC tag and subfield for a given kohafield
267 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
273 sub MARCfind_marc_from_kohafield {
274 my ( $dbh, $kohafield,$frameworkcode ) = @_;
275 return 0, 0 unless $kohafield;
276 $frameworkcode='' unless $frameworkcode;
277 my $relations = C4::Context->marcfromkohafield;
278 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
281 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
285 Returns a MARC::Record for the biblio $biblionumber.
291 # Returns MARC::Record of the biblio passed in parameter.
292 my ( $dbh, $biblionumber ) = @_;
293 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
294 $sth->execute($biblionumber);
295 my ($marc) = $sth->fetchrow;
296 my $record = MARC::Record::new_from_usmarc($marc);
300 =head2 $XML = &XMLgetbiblio($dbh,$biblionumber);
304 Returns a raw XML for the biblio $biblionumber.
310 # Returns MARC::Record of the biblio passed in parameter.
311 my ( $dbh, $biblionumber ) = @_;
312 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
313 $sth->execute($biblionumber);
314 my ($XML,$marc) = $sth->fetchrow;
315 # my $record =MARC::Record::new_from_usmarc($marc);
316 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
320 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
324 Returns a MARC::Record with all items of biblio # $biblionumber
332 my ( $dbh, $biblionumber, $itemnumber ) = @_;
333 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
334 # get the complete MARC record
335 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
336 $sth->execute($biblionumber);
337 my ($rawmarc) = $sth->fetchrow;
338 my $record = MARC::File::USMARC::decode($rawmarc);
339 # now, find the relevant itemnumber
340 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
341 # prepare the new item record
342 my $itemrecord = MARC::Record->new();
343 # parse all fields fields from the complete record
344 foreach ($record->field($itemnumberfield)) {
345 # when the item field is found, save it
346 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
347 $itemrecord->append_fields($_);
354 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
358 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
359 This sub is useless when MARC=OFF
364 sub find_biblioitemnumber {
365 my ( $dbh, $biblionumber ) = @_;
366 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
367 $sth->execute($biblionumber);
368 my ($biblioitemnumber) = $sth->fetchrow;
369 return $biblioitemnumber;
372 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
376 returns the framework of a given biblio
382 sub MARCfind_frameworkcode {
383 my ( $dbh, $biblionumber ) = @_;
384 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
385 $sth->execute($biblionumber);
386 my ($frameworkcode) = $sth->fetchrow;
387 return $frameworkcode;
390 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
394 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
395 all entries of the hash are transformed into their matching MARC field/subfield.
401 sub MARCkoha2marcBiblio {
403 # this function builds partial MARC::Record from the old koha-DB fields
404 my ( $dbh, $bibliohash ) = @_;
405 # we don't have biblio entries in the hash, so we add them first
406 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
407 $sth->execute($bibliohash->{biblionumber});
408 my $biblio = $sth->fetchrow_hashref;
409 foreach (keys %$biblio) {
410 $bibliohash->{$_}=$biblio->{$_};
412 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
413 my $record = MARC::Record->new();
414 foreach ( keys %$bibliohash ) {
415 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
416 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
419 # other fields => additional authors, subjects, subtitles
420 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
421 $sth2->execute($bibliohash->{biblionumber});
422 while ( my $row = $sth2->fetchrow_hashref ) {
423 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
425 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
426 $sth2->execute($bibliohash->{biblionumber});
427 while ( my $row = $sth2->fetchrow_hashref ) {
428 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
430 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
431 $sth2->execute($bibliohash->{biblionumber});
432 while ( my $row = $sth2->fetchrow_hashref ) {
433 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
439 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
441 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
442 all entries of the hash are transformed into their matching MARC field/subfield.
450 sub MARCkoha2marcItem {
452 # this function builds partial MARC::Record from the old koha-DB fields
453 my ( $dbh, $item ) = @_;
455 # my $dbh=&C4Connect;
456 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
457 my $record = MARC::Record->new();
459 foreach( keys %$item ) {
461 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
468 =head2 MARCkoha2marcOnefield
472 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
478 sub MARCkoha2marcOnefield {
479 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
482 $sth->execute($frameworkcode,$kohafieldname);
483 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
484 if ( $record->field($tagfield) ) {
485 my $tag = $record->field($tagfield);
487 $tag->add_subfields( $tagsubfield, $value );
488 $record->delete_field($tag);
489 $record->add_fields($tag);
493 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
499 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
503 transforms the parameters (coming from HTML form) into a MARC::Record
504 parameters with r are references to arrays.
506 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
513 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
515 my $record = MARC::Record->new();
516 # my %subfieldlist=();
517 my $prevvalue; # if tag <10
518 my $field; # if tag >=10
519 for (my $i=0; $i< @$rtags; $i++) {
520 next unless @$rvalues[$i];
521 # rebuild MARC::Record
522 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
523 if (@$rtags[$i] ne $prevtag) {
526 if ($prevtag ne '000') {
527 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
529 $record->leader($prevvalue);
534 $record->add_fields($field);
537 $indicators{@$rtags[$i]}.=' ';
538 if (@$rtags[$i] <10) {
539 $prevvalue= @$rvalues[$i];
543 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
544 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
546 $prevtag = @$rtags[$i];
548 if (@$rtags[$i] <10) {
549 $prevvalue=@$rvalues[$i];
551 if (length(@$rvalues[$i])>0) {
552 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
553 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
556 $prevtag= @$rtags[$i];
559 # the last has not been included inside the loop... do it now !
560 $record->add_fields($field) if $field;
561 # warn "HTML2MARC=".$record->as_formatted;
566 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
570 builds a hash with old-db datas from a MARC::Record
577 my ($dbh,$record,$frameworkcode) = @_;
578 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
580 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
583 while (($field)=$sth2->fetchrow) {
584 # warn "biblio.".$field;
585 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
587 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
589 while (($field)=$sth2->fetchrow) {
590 if ($field eq 'notes') { $field = 'bnotes'; }
591 # warn "biblioitems".$field;
592 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
594 $sth2=$dbh->prepare("SHOW COLUMNS from items");
596 while (($field)=$sth2->fetchrow) {
597 # warn "items".$field;
598 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
600 # additional authors : specific
601 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
602 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
603 # modify copyrightdate to keep only the 1st year found
604 my $temp = $result->{'copyrightdate'};
606 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
608 $result->{'copyrightdate'} = $1;
609 } else { # if no cYYYY, get the 1st date.
610 $temp =~ m/(\d\d\d\d)/;
611 $result->{'copyrightdate'} = $1;
614 # modify publicationyear to keep only the 1st year found
615 $temp = $result->{'publicationyear'};
616 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
618 $result->{'publicationyear'} = $1;
619 } else { # if no cYYYY, get the 1st date.
620 $temp =~ m/(\d\d\d\d)/;
621 $result->{'publicationyear'} = $1;
626 sub MARCmarc2kohaOneField {
628 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
629 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
630 # warn "kohatable / $kohafield / $result / ";
634 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
635 foreach my $field ( $record->field($tagfield) ) {
636 if ($field->tag()<10) {
637 if ($result->{$kohafield}) {
638 # Reverse array filled with elements from repeated subfields
639 # from first to last to avoid last to first concatenation of
640 # elements in Koha DB. -- thd.
641 $result->{$kohafield} .= " | ".reverse($field->data());
643 $result->{$kohafield} = $field->data();
646 if ( $field->subfields ) {
647 my @subfields = $field->subfields();
648 foreach my $subfieldcount ( 0 .. $#subfields ) {
649 if ($subfields[$subfieldcount][0] eq $subfield) {
650 if ( $result->{$kohafield} ) {
651 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
654 $result->{$kohafield} = $subfields[$subfieldcount][1];
661 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
665 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
669 creates a biblio from a MARC::Record.
676 my ( $dbh, $record, $frameworkcode ) = @_;
678 my $biblioitemnumber;
679 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
680 $olddata->{frameworkcode} = $frameworkcode;
681 $biblionumber = REALnewbiblio( $dbh, $olddata );
682 $olddata->{biblionumber} = $biblionumber;
683 # add biblionumber into the MARC record (it's the ID for zebra)
684 my ( $tagfield, $tagsubfield ) =
685 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
689 $newfield = MARC::Field->new(
690 $tagfield, $biblionumber,
693 $newfield = MARC::Field->new(
694 $tagfield, '', '', "$tagsubfield" => $biblionumber,
697 # drop old field (just in case it already exist and create new one...
698 my $old_field = $record->field($tagfield);
699 $record->delete_field($old_field);
700 $record->add_fields($newfield);
702 #create the marc entry, that stores the rax marc record in Koha 3.0
703 $olddata->{marc} = $record->as_usmarc();
704 $olddata->{marcxml} = $record->as_xml();
705 # and create biblioitem, that's all folks !
706 $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
708 # search subtiles, addiauthors and subjects
709 ( $tagfield, $tagsubfield ) =
710 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
711 my @addiauthfields = $record->field($tagfield);
712 foreach my $addiauthfield (@addiauthfields) {
713 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
714 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
715 REALmodaddauthor( $dbh, $biblionumber,
716 $addiauthsubfields[$subfieldcount] );
719 ( $tagfield, $tagsubfield ) =
720 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
721 my @subtitlefields = $record->field($tagfield);
722 foreach my $subtitlefield (@subtitlefields) {
723 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
724 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
725 REALnewsubtitle( $dbh, $biblionumber,
726 $subtitlesubfields[$subfieldcount] );
729 ( $tagfield, $tagsubfield ) =
730 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
731 my @subj = $record->field($tagfield);
733 foreach my $subject (@subj) {
734 my @subjsubfield = $subject->subfield($tagsubfield);
735 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
736 push @subjects, $subjsubfield[$subfieldcount];
739 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
740 return ( $biblionumber, $biblioitemnumber );
743 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
747 modify the framework of a biblio
753 sub NEWmodbiblioframework {
754 my ($dbh,$biblionumber,$frameworkcode) =@_;
755 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
756 $sth->execute($frameworkcode,$biblionumber);
760 =head2 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
764 modify a biblio (MARC=ON)
771 my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
772 $frameworkcode="" unless $frameworkcode;
773 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
774 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
776 $oldbiblio->{frameworkcode} = $frameworkcode;
777 #create the marc entry, that stores the rax marc record in Koha 3.0
778 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
779 $oldbiblio->{marc} = $record->as_usmarc();
780 $oldbiblio->{marcxml} = $record->as_xml();
781 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
782 REALmodbiblio($dbh,$oldbiblio);
783 REALmodbiblioitem($dbh,$oldbiblio);
784 # now, modify addi authors, subject, addititles.
785 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
786 my @addiauthfields = $record->field($tagfield);
787 foreach my $addiauthfield (@addiauthfields) {
788 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
789 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
790 foreach my $subfieldcount (0..$#addiauthsubfields) {
791 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
794 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
795 my @subtitlefields = $record->field($tagfield);
796 foreach my $subtitlefield (@subtitlefields) {
797 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
798 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
800 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
801 foreach my $subfieldcount (0..$#subtitlesubfields) {
802 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
803 REALnewsubtitle($dbh,$biblionumber,$subtit);
807 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
808 my @subj = $record->field($tagfield);
810 foreach my $subject (@subj) {
811 my @subjsubfield = $subject->subfield($tagsubfield);
812 foreach my $subfieldcount (0..$#subjsubfield) {
813 push @subjects,$subjsubfield[$subfieldcount];
816 REALmodsubject($dbh,$biblionumber,1,@subjects);
820 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
831 my ( $dbh, $bibid ) = @_;
832 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
833 &REALdelbiblio( $dbh, $biblio );
836 "select biblioitemnumber from biblioitems where biblionumber=?");
837 $sth->execute($biblio);
838 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
839 REALdelbiblioitem( $dbh, $biblioitemnumber );
841 &MARCdelbiblio( $dbh, $bibid, 0 );
844 =head2 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
848 creates an item from a MARC::Record
855 my ( $dbh, $record, $biblionumber, $biblioitemnumber ) = @_;
858 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
859 my $item = &MARCmarc2koha( $dbh, $record,$frameworkcode );
860 # needs old biblionumber and biblioitemnumber
861 $item->{'biblionumber'} = $biblionumber;
862 $item->{'biblioitemnumber'}=$biblioitemnumber;
863 $item->{marc} = $record->as_usmarc();
864 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
869 =head2 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
880 my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
882 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
883 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
885 $olditem->{marc} = $record->as_usmarc();
886 $olditem->{biblionumber} = $biblionumber;
887 $olditem->{biblioitemnumber} = $biblioitemnumber;
889 REALmoditem( $dbh, $olditem );
893 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
904 my ( $dbh, $bibid, $itemnumber ) = @_;
905 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
906 &REALdelitem( $dbh, $itemnumber );
907 &MARCdelitem( $dbh, $bibid, $itemnumber );
911 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
915 adds a record in biblio table. Datas are in the hash $biblio.
922 my ( $dbh, $biblio ) = @_;
924 $dbh->do('lock tables biblio WRITE');
925 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
927 my $data = $sth->fetchrow_arrayref;
928 my $bibnum = $$data[0] + 1;
931 if ( $biblio->{'seriestitle'} ) { $series = 1 }
934 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
935 serial=?, seriestitle=?, notes=?, abstract=?,
939 $bibnum, $biblio->{'title'},
940 $biblio->{'author'}, $biblio->{'copyrightdate'},
941 $biblio->{'serial'}, $biblio->{'seriestitle'},
942 $biblio->{'notes'}, $biblio->{'abstract'},
943 $biblio->{'unititle'}
947 $dbh->do('unlock tables');
951 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
955 modify a record in biblio table. Datas are in the hash $biblio.
962 my ( $dbh, $biblio ) = @_;
963 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
964 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
965 where biblionumber = ?"
968 $biblio->{'title'}, $biblio->{'author'},
969 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
970 $biblio->{'seriestitle'}, $biblio->{'serial'},
971 $biblio->{'unititle'}, $biblio->{'notes'},
972 $biblio->{frameworkcode},
973 $biblio->{'biblionumber'}
976 return ( $biblio->{'biblionumber'} );
979 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
983 modify subtitles in bibliosubtitle table.
989 sub REALmodsubtitle {
990 my ( $dbh, $bibnum, $subtitle ) = @_;
993 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
994 $sth->execute( $subtitle, $bibnum );
998 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1002 adds or modify additional authors
1003 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1009 sub REALmodaddauthor {
1010 my ( $dbh, $bibnum, @authors ) = @_;
1012 # my $dbh = C4Connect;
1014 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1016 $sth->execute($bibnum);
1018 foreach my $author (@authors) {
1019 if ( $author ne '' ) {
1022 "Insert into additionalauthors set author = ?, biblionumber = ?"
1025 $sth->execute( $author, $bibnum );
1030 } # sub modaddauthor
1032 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1036 modify/adds subjects
1041 sub REALmodsubject {
1042 my ( $dbh, $bibnum, $force, @subject ) = @_;
1044 # my $dbh = C4Connect;
1045 my $count = @subject;
1047 for ( my $i = 0 ; $i < $count ; $i++ ) {
1048 $subject[$i] =~ s/^ //g;
1049 $subject[$i] =~ s/ $//g;
1052 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1054 $sth->execute( $subject[$i] );
1056 if ( my $data = $sth->fetchrow_hashref ) {
1059 if ( $force eq $subject[$i] || $force == 1 ) {
1061 # subject not in aut, chosen to force anway
1062 # so insert into cataloguentry so its in auth file
1065 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1068 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1073 "$subject[$i]\n does not exist in the subject authority file";
1076 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1078 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1080 while ( my $data = $sth2->fetchrow_hashref ) {
1081 $error .= "<br>$data->{'catalogueentry'}";
1090 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1091 $sth->execute($bibnum);
1095 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1097 foreach $query (@subject) {
1098 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1107 =head2 REALmodbiblioitem($dbh, $biblioitem);
1116 sub REALmodbiblioitem {
1117 my ( $dbh, $biblioitem ) = @_;
1120 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1121 itemtype=?, url=?, isbn=?, issn=?,
1122 publishercode=?, publicationyear=?, classification=?, dewey=?,
1123 subclass=?, illus=?, pages=?, volumeddesc=?,
1124 notes=?, size=?, place=?, marc=?,
1126 where biblioitemnumber=?");
1127 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1128 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1129 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1130 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1131 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1132 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1133 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1134 zebra_create($biblioitem->{biblionumber}, $record);
1135 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1138 =head2 REALnewbiblioitem($dbh,$biblioitem);
1142 adds a biblioitem ($biblioitem is a hash with the values)
1148 sub REALnewbiblioitem {
1149 my ( $dbh, $biblioitem ) = @_;
1151 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1152 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1154 my $biblioitemnumber;
1157 $data = $sth->fetchrow_arrayref;
1158 $biblioitemnumber = $$data[0] + 1;
1160 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1161 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1162 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1163 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1164 my $field=$record->field($biblioitemnumberfield);
1165 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1166 $biblioitem->{marc} = $record->as_usmarc();
1167 $biblioitem->{marcxml} = $record->as_xml();
1169 $sth = $dbh->prepare( "insert into biblioitems set
1170 biblioitemnumber = ?, biblionumber = ?,
1171 volume = ?, number = ?,
1172 classification = ?, itemtype = ?,
1174 issn = ?, dewey = ?,
1175 subclass = ?, publicationyear = ?,
1176 publishercode = ?, volumedate = ?,
1177 volumeddesc = ?, illus = ?,
1178 pages = ?, notes = ?,
1180 marc = ?, place = ?,
1184 $biblioitemnumber, $biblioitem->{'biblionumber'},
1185 $biblioitem->{'volume'}, $biblioitem->{'number'},
1186 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1187 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1188 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1189 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1190 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1191 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1192 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1193 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1194 $biblioitem->{'marc'}, $biblioitem->{'place'},
1195 $biblioitem->{marcxml},
1197 $dbh->do("unlock tables");
1198 zebra_create($biblioitem->{biblionumber}, $record);
1199 return ($biblioitemnumber);
1202 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1206 create a new subtitle
1211 sub REALnewsubtitle {
1212 my ( $dbh, $bibnum, $subtitle ) = @_;
1215 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1216 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1220 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1224 create a item. $item is a hash and $barcode the barcode.
1231 my ( $dbh, $item, $barcode ) = @_;
1233 # warn "OLDNEWITEMS";
1235 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1236 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1241 $data = $sth->fetchrow_hashref;
1242 $itemnumber = $data->{'max(itemnumber)'} + 1;
1244 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1245 if ( $item->{'loan'} ) {
1246 $item->{'notforloan'} = $item->{'loan'};
1249 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1250 if ( $item->{'dateaccessioned'} ) {
1251 $sth = $dbh->prepare( "Insert into items set
1252 itemnumber = ?, biblionumber = ?,
1253 multivolumepart = ?,
1254 biblioitemnumber = ?, barcode = ?,
1255 booksellerid = ?, dateaccessioned = ?,
1256 homebranch = ?, holdingbranch = ?,
1257 price = ?, replacementprice = ?,
1258 replacementpricedate = NOW(), datelastseen = NOW(),
1259 multivolume = ?, stack = ?,
1260 itemlost = ?, wthdrawn = ?,
1261 paidfor = ?, itemnotes = ?,
1262 itemcallnumber =?, notforloan = ?,
1267 $itemnumber, $item->{'biblionumber'},
1268 $item->{'multivolumepart'},
1269 $item->{'biblioitemnumber'},$item->{barcode},
1270 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1271 $item->{'homebranch'}, $item->{'holdingbranch'},
1272 $item->{'price'}, $item->{'replacementprice'},
1273 $item->{multivolume}, $item->{stack},
1274 $item->{itemlost}, $item->{wthdrawn},
1275 $item->{paidfor}, $item->{'itemnotes'},
1276 $item->{'itemcallnumber'}, $item->{'notforloan'},
1279 if ( defined $sth->errstr ) {
1280 $error .= $sth->errstr;
1284 $sth = $dbh->prepare( "Insert into items set
1285 itemnumber = ?, biblionumber = ?,
1286 multivolumepart = ?,
1287 biblioitemnumber = ?, barcode = ?,
1288 booksellerid = ?, dateaccessioned = NOW(),
1289 homebranch = ?, holdingbranch = ?,
1290 price = ?, replacementprice = ?,
1291 replacementpricedate = NOW(), datelastseen = NOW(),
1292 multivolume = ?, stack = ?,
1293 itemlost = ?, wthdrawn = ?,
1294 paidfor = ?, itemnotes = ?,
1295 itemcallnumber =?, notforloan = ?,
1300 $itemnumber, $item->{'biblionumber'},
1301 $item->{'multivolumepart'},
1302 $item->{'biblioitemnumber'},$item->{barcode},
1303 $item->{'booksellerid'},
1304 $item->{'homebranch'}, $item->{'holdingbranch'},
1305 $item->{'price'}, $item->{'replacementprice'},
1306 $item->{multivolume}, $item->{stack},
1307 $item->{itemlost}, $item->{wthdrawn},
1308 $item->{paidfor}, $item->{'itemnotes'},
1309 $item->{'itemcallnumber'}, $item->{'notforloan'},
1312 if ( defined $sth->errstr ) {
1313 $error .= $sth->errstr;
1316 # item stored, now, deal with the marc part...
1317 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1318 where biblio.biblionumber=biblioitems.biblionumber and
1319 biblio.biblionumber=?");
1320 $sth->execute($item->{biblionumber});
1321 if ( defined $sth->errstr ) {
1322 $error .= $sth->errstr;
1324 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1325 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1326 my $record = MARC::File::USMARC::decode($rawmarc);
1327 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1328 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1329 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1330 my $itemfield = $itemrecord->field($itemnumberfield);
1331 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1332 $record->insert_grouped_field($itemfield);
1333 # save the record into biblioitem
1334 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1335 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1336 if ( defined $sth->errstr ) {
1337 $error .= $sth->errstr;
1339 zebra_create($item->{biblionumber},$record);
1340 $dbh->do('unlock tables');
1341 return ( $itemnumber, $error );
1344 =head2 REALmoditem($dbh,$item);
1355 my ( $dbh, $item ) = @_;
1357 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1358 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1359 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1361 $item->{'barcode'}, $item->{'itemnotes'},
1362 $item->{'itemcallnumber'}, $item->{'notforloan'},
1363 $item->{'location'}, $item->{multivolumepart},
1364 $item->{multivolume}, $item->{stack},
1367 if ( $item->{'lost'} ne '' ) {
1368 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1369 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1370 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1372 $item->{'bibitemnum'}, $item->{'barcode'},
1373 $item->{'itemnotes'}, $item->{'homebranch'},
1374 $item->{'lost'}, $item->{'wthdrawn'},
1375 $item->{'itemcallnumber'}, $item->{'notforloan'},
1376 $item->{'location'}, $item->{multivolumepart},
1377 $item->{multivolume}, $item->{stack},
1380 if ($item->{homebranch}) {
1381 $query.=",homebranch=?";
1382 push @bind, $item->{homebranch};
1384 if ($item->{holdingbranch}) {
1385 $query.=",holdingbranch=?";
1386 push @bind, $item->{holdingbranch};
1389 $query.=" where itemnumber=?";
1390 push @bind,$item->{'itemnum'};
1391 if ( $item->{'replacement'} ne '' ) {
1392 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1394 my $sth = $dbh->prepare($query);
1395 $sth->execute(@bind);
1397 # item stored, now, deal with the marc part...
1398 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1399 where biblio.biblionumber=biblioitems.biblionumber and
1400 biblio.biblionumber=? and
1401 biblioitems.biblioitemnumber=?");
1402 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1403 if ( defined $sth->errstr ) {
1404 $error .= $sth->errstr;
1406 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1407 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1408 my $record = MARC::File::USMARC::decode($rawmarc);
1409 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1410 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1411 # prepare the new item record
1412 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1413 my $itemfield = $itemrecord->field($itemnumberfield);
1414 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1415 # parse all fields fields from the complete record
1416 foreach ($record->field($itemnumberfield)) {
1417 # when the previous field is found, replace by the new one
1418 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1419 $_->replace_with($itemfield);
1422 # $record->insert_grouped_field($itemfield);
1423 # save the record into biblioitem
1424 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1425 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1426 zebra_create($item->biblionumber,$record);
1427 if ( defined $sth->errstr ) {
1428 $error .= $sth->errstr;
1430 $dbh->do('unlock tables');
1435 =head2 REALdelitem($dbh,$itemnum);
1446 my ( $dbh, $itemnum ) = @_;
1448 # my $dbh=C4Connect;
1449 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1450 $sth->execute($itemnum);
1451 my $data = $sth->fetchrow_hashref;
1453 my $query = "Insert into deleteditems set ";
1455 foreach my $temp ( keys %$data ) {
1456 $query .= "$temp = ?,";
1457 push ( @bind, $data->{$temp} );
1462 $sth = $dbh->prepare($query);
1463 $sth->execute(@bind);
1465 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1466 $sth->execute($itemnum);
1472 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1476 deletes a biblioitem
1477 NOTE : not standard sub name. Should be REALdelbiblioitem()
1483 sub REALdelbiblioitem {
1484 my ( $dbh, $biblioitemnumber ) = @_;
1486 # my $dbh = C4Connect;
1487 my $sth = $dbh->prepare( "Select * from biblioitems
1488 where biblioitemnumber = ?"
1492 $sth->execute($biblioitemnumber);
1494 if ( $results = $sth->fetchrow_hashref ) {
1498 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1499 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1500 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1504 $results->{biblioitemnumber}, $results->{biblionumber},
1505 $results->{volume}, $results->{number},
1506 $results->{classification}, $results->{itemtype},
1507 $results->{isbn}, $results->{issn},
1508 $results->{dewey}, $results->{subclass},
1509 $results->{publicationyear}, $results->{publishercode},
1510 $results->{volumedate}, $results->{volumeddesc},
1511 $results->{timestamp}, $results->{illus},
1512 $results->{pages}, $results->{notes},
1513 $results->{size}, $results->{url},
1517 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1518 $sth2->execute($biblioitemnumber);
1523 # Now delete all the items attached to the biblioitem
1524 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1525 $sth->execute($biblioitemnumber);
1527 while ( my $data = $sth->fetchrow_hashref ) {
1528 my $query = "Insert into deleteditems set ";
1530 foreach my $temp ( keys %$data ) {
1531 $query .= "$temp = ?,";
1532 push ( @bind, $data->{$temp} );
1535 my $sth2 = $dbh->prepare($query);
1536 $sth2->execute(@bind);
1539 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1540 $sth->execute($biblioitemnumber);
1544 } # sub deletebiblioitem
1546 =head2 REALdelbiblio($dbh,$biblio);
1557 my ( $dbh, $biblio ) = @_;
1558 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1559 $sth->execute($biblio);
1560 if ( my $data = $sth->fetchrow_hashref ) {
1562 my $query = "Insert into deletedbiblio set ";
1564 foreach my $temp ( keys %$data ) {
1565 $query .= "$temp = ?,";
1566 push ( @bind, $data->{$temp} );
1569 #replacing the last , by ",?)"
1571 $sth = $dbh->prepare($query);
1572 $sth->execute(@bind);
1574 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1575 $sth->execute($biblio);
1581 =head2 $number = itemcount($biblio);
1585 returns the number of items attached to a biblio
1593 my $dbh = C4::Context->dbh;
1596 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1597 $sth->execute($biblio);
1598 my $data = $sth->fetchrow_hashref;
1600 return ( $data->{'count(*)'} );
1603 =head2 $biblionumber = newbiblio($biblio);
1607 create a biblio. The parameter is a hash
1615 my $dbh = C4::Context->dbh;
1616 my $bibnum = REALnewbiblio( $dbh, $biblio );
1617 # finds new (MARC bibid
1618 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1619 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1620 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1624 =head2 $biblionumber = &modbiblio($biblio);
1628 Update a biblio record.
1630 C<$biblio> is a reference-to-hash whose keys are the fields in the
1631 biblio table in the Koha database. All fields must be present, not
1632 just the ones you wish to change.
1634 C<&modbiblio> updates the record defined by
1635 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1637 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1646 my $dbh = C4::Context->dbh;
1647 my $biblionumber=REALmodbiblio($dbh,$biblio);
1648 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1649 # finds new (MARC bibid
1650 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1651 MARCmodbiblio($dbh,$bibid,$record,"",0);
1652 return($biblionumber);
1655 =head2 &modsubtitle($biblionumber, $subtitle);
1659 Sets the subtitle of a book.
1661 C<$biblionumber> is the biblionumber of the book to modify.
1663 C<$subtitle> is the new subtitle.
1670 my ( $bibnum, $subtitle ) = @_;
1671 my $dbh = C4::Context->dbh;
1672 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1675 =head2 &modaddauthor($biblionumber, $author);
1679 Replaces all additional authors for the book with biblio number
1680 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1681 C<&modaddauthor> deletes all additional authors.
1688 my ( $bibnum, @authors ) = @_;
1689 my $dbh = C4::Context->dbh;
1690 &REALmodaddauthor( $dbh, $bibnum, @authors );
1691 } # sub modaddauthor
1693 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1697 $force - a subject to force
1698 $error - Error message, or undef if successful.
1705 my ( $bibnum, $force, @subject ) = @_;
1706 my $dbh = C4::Context->dbh;
1707 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1709 # When MARC is off, ensures that the MARC biblio table gets updated with new
1710 # subjects, of course, it deletes the biblio in marc, and then recreates.
1711 # This check is to ensure that no MARC data exists to lose.
1712 # if (C4::Context->preference("MARC") eq '0'){
1713 # warn "in modSUBJECT";
1714 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1715 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1716 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1722 =head2 modbibitem($biblioitem);
1726 modify a biblioitem. The parameter is a hash
1733 my ($biblioitem) = @_;
1734 my $dbh = C4::Context->dbh;
1735 &REALmodbiblioitem( $dbh, $biblioitem );
1738 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1742 create a biblioitem, the parameter is a hash
1749 my ($biblioitem) = @_;
1750 my $dbh = C4::Context->dbh;
1751 # add biblio information to the hash
1752 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1753 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1754 my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1755 return ($bibitemnum);
1758 =head2 newsubtitle($biblionumber,$subtitle);
1762 insert a subtitle for $biblionumber biblio
1770 my ( $bibnum, $subtitle ) = @_;
1771 my $dbh = C4::Context->dbh;
1772 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1775 =head2 $errors = newitems($item, @barcodes);
1779 insert items ($item is a hash)
1787 my ( $item, @barcodes ) = @_;
1788 my $dbh = C4::Context->dbh;
1792 foreach my $barcode (@barcodes) {
1793 # add items, one by one for each barcode.
1795 $oneitem->{barcode}= $barcode;
1796 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1797 $oneitem->{marc} = $MARCitem->as_usmarc;
1798 ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
1799 # $errors .= $error;
1800 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1805 =head2 moditem($item);
1809 modify an item ($item is a hash with all item informations)
1818 my $dbh = C4::Context->dbh;
1819 &REALmoditem( $dbh, $item );
1821 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1823 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1824 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1827 =head2 $error = checkitems($count,@barcodes);
1831 check for each @barcode entry that the barcode is not a duplicate
1838 my ( $count, @barcodes ) = @_;
1839 my $dbh = C4::Context->dbh;
1841 my $sth = $dbh->prepare("Select * from items where barcode=?");
1842 for ( my $i = 0 ; $i < $count ; $i++ ) {
1843 $barcodes[$i] = uc $barcodes[$i];
1844 $sth->execute( $barcodes[$i] );
1845 if ( my $data = $sth->fetchrow_hashref ) {
1846 $error .= " Duplicate Barcode: $barcodes[$i]";
1853 =head2 $delitem($itemnum);
1857 delete item $itemnum being the item number to delete
1865 my $dbh = C4::Context->dbh;
1866 &REALdelitem( $dbh, $itemnum );
1869 =head2 deletebiblioitem($biblioitemnumber);
1873 delete the biblioitem $biblioitemnumber
1879 sub deletebiblioitem {
1880 my ($biblioitemnumber) = @_;
1881 my $dbh = C4::Context->dbh;
1882 &REALdelbiblioitem( $dbh, $biblioitemnumber );
1883 } # sub deletebiblioitem
1885 =head2 delbiblio($biblionumber)
1889 delete biblio $biblionumber
1897 my $dbh = C4::Context->dbh;
1898 &REALdelbiblio( $dbh, $biblio );
1899 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
1900 &MARCdelbiblio( $dbh, $bibid, 0 );
1903 =head2 ($count,@results) = getbiblio($biblionumber);
1907 return an array with hash of biblios.
1909 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
1916 my ($biblionumber) = @_;
1917 my $dbh = C4::Context->dbh;
1918 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
1920 # || die "Cannot prepare $query\n" . $dbh->errstr;
1924 $sth->execute($biblionumber);
1926 # || die "Cannot execute $query\n" . $sth->errstr;
1927 while ( my $data = $sth->fetchrow_hashref ) {
1928 $results[$count] = $data;
1933 return ( $count, @results );
1938 $data = &bibdata($biblionumber, $type);
1940 Returns information about the book with the given biblionumber.
1942 C<$type> is ignored.
1944 C<&bibdata> returns a reference-to-hash. The keys are the fields in
1945 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
1948 In addition, C<$data-E<gt>{subject}> is the list of the book's
1949 subjects, separated by C<" , "> (space, comma, space).
1951 If there are multiple biblioitems with the given biblionumber, only
1952 the first one is considered.
1957 my ($bibnum, $type) = @_;
1958 my $dbh = C4::Context->dbh;
1959 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
1961 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
1962 left join bibliosubtitle on
1963 biblio.biblionumber = bibliosubtitle.biblionumber
1964 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
1965 where biblio.biblionumber = ?
1967 $sth->execute($bibnum);
1969 $data = $sth->fetchrow_hashref;
1971 # handle management of repeated subtitle
1972 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
1973 $sth->execute($bibnum);
1975 while (my $dat = $sth->fetchrow_hashref){
1977 $line{subtitle} = $dat->{subtitle};
1978 push @subtitles, \%line;
1980 $data->{subtitles} = \@subtitles;
1982 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
1983 $sth->execute($bibnum);
1985 while (my $dat = $sth->fetchrow_hashref){
1987 $line{subject} = $dat->{'subject'};
1988 push @subjects, \%line;
1990 $data->{subjects} = \@subjects;
1992 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
1993 $sth->execute($bibnum);
1994 while (my $dat = $sth->fetchrow_hashref){
1995 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
1997 chop $data->{'additionalauthors'};
1998 chop $data->{'additionalauthors'};
1999 chop $data->{'additionalauthors'};
2004 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
2008 return an array with hash of biblioitemss.
2010 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2017 my ($biblioitemnum) = @_;
2018 my $dbh = C4::Context->dbh;
2019 my $sth = $dbh->prepare( "Select * from biblioitems where
2020 biblioitemnumber = ?"
2025 $sth->execute($biblioitemnum);
2027 while ( my $data = $sth->fetchrow_hashref ) {
2028 $results[$count] = $data;
2033 return ( $count, @results );
2034 } # sub getbiblioitem
2036 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2040 return an array with hash of biblioitems for the given biblionumber.
2046 sub getbiblioitembybiblionumber {
2047 my ($biblionumber) = @_;
2048 my $dbh = C4::Context->dbh;
2049 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2053 $sth->execute($biblionumber);
2055 while ( my $data = $sth->fetchrow_hashref ) {
2056 $results[$count] = $data;
2061 return ( $count, @results );
2064 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2068 returns an array with hash of items
2074 sub getitemsbybiblioitem {
2075 my ($biblioitemnum) = @_;
2076 my $dbh = C4::Context->dbh;
2077 my $sth = $dbh->prepare( "Select * from items, biblio where
2078 biblio.biblionumber = items.biblionumber and biblioitemnumber
2082 # || die "Cannot prepare $query\n" . $dbh->errstr;
2086 $sth->execute($biblioitemnum);
2088 # || die "Cannot execute $query\n" . $sth->errstr;
2089 while ( my $data = $sth->fetchrow_hashref ) {
2090 $results[$count] = $data;
2095 return ( $count, @results );
2096 } # sub getitemsbybiblioitem
2100 @results = &ItemInfo($env, $biblionumber, $type);
2102 Returns information about books with the given biblionumber.
2104 C<$type> may be either C<intra> or anything else. If it is not set to
2105 C<intra>, then the search will exclude lost, very overdue, and
2110 C<&ItemInfo> returns a list of references-to-hash. Each element
2111 contains a number of keys. Most of them are table items from the
2112 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2113 Koha database. Other keys include:
2117 =item C<$data-E<gt>{branchname}>
2119 The name (not the code) of the branch to which the book belongs.
2121 =item C<$data-E<gt>{datelastseen}>
2123 This is simply C<items.datelastseen>, except that while the date is
2124 stored in YYYY-MM-DD format in the database, here it is converted to
2125 DD/MM/YYYY format. A NULL date is returned as C<//>.
2127 =item C<$data-E<gt>{datedue}>
2129 =item C<$data-E<gt>{class}>
2131 This is the concatenation of C<biblioitems.classification>, the book's
2132 Dewey code, and C<biblioitems.subclass>.
2134 =item C<$data-E<gt>{ocount}>
2136 I think this is the number of copies of the book available.
2138 =item C<$data-E<gt>{order}>
2140 If this is set, it is set to C<One Order>.
2147 my ($env,$biblionumber,$type) = @_;
2148 my $dbh = C4::Context->dbh;
2149 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2150 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2151 WHERE items.biblionumber = ?
2152 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2153 AND biblio.biblionumber = items.biblionumber";
2154 $query .= " order by items.dateaccessioned desc";
2155 my $sth=$dbh->prepare($query);
2156 $sth->execute($biblionumber);
2159 while (my $data=$sth->fetchrow_hashref){
2161 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2162 $isth->execute($data->{'itemnumber'});
2163 if (my $idata=$isth->fetchrow_hashref){
2164 $data->{borrowernumber} = $idata->{borrowernumber};
2165 $data->{cardnumber} = $idata->{cardnumber};
2166 $datedue = format_date($idata->{'date_due'});
2168 if ($datedue eq ''){
2169 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2175 #get branch information.....
2176 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2177 $bsth->execute($data->{'holdingbranch'});
2178 if (my $bdata=$bsth->fetchrow_hashref){
2179 $data->{'branchname'} = $bdata->{'branchname'};
2181 my $date=format_date($data->{'datelastseen'});
2182 $data->{'datelastseen'}=$date;
2183 $data->{'datedue'}=$datedue;
2184 # get notforloan complete status if applicable
2185 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2186 $sthnflstatus->execute;
2187 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2188 if ($authorised_valuecode) {
2189 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2190 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2191 my ($lib) = $sthnflstatus->fetchrow;
2192 $data->{notforloan} = $lib;
2203 ($count, @results) = &bibitems($biblionumber);
2205 Given the biblionumber for a book, C<&bibitems> looks up that book's
2206 biblioitems (different publications of the same book, the audio book
2207 and film versions, etc.).
2209 C<$count> is the number of elements in C<@results>.
2211 C<@results> is an array of references-to-hash; the keys are the fields
2212 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2213 addition, C<itemlost> indicates the availability of the item: if it is
2214 "2", then all copies of the item are long overdue; if it is "1", then
2215 all copies are lost; otherwise, there is at least one copy available.
2221 my $dbh = C4::Context->dbh;
2222 my $sth = $dbh->prepare("SELECT biblioitems.*,
2224 MIN(items.itemlost) as itemlost,
2225 MIN(items.dateaccessioned) as dateaccessioned
2226 FROM biblioitems, itemtypes, items
2227 WHERE biblioitems.biblionumber = ?
2228 AND biblioitems.itemtype = itemtypes.itemtype
2229 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2230 GROUP BY items.biblioitemnumber");
2233 $sth->execute($bibnum);
2234 while (my $data = $sth->fetchrow_hashref) {
2235 $results[$count] = $data;
2239 return($count, @results);
2245 $itemdata = &bibitemdata($biblioitemnumber);
2247 Looks up the biblioitem with the given biblioitemnumber. Returns a
2248 reference-to-hash. The keys are the fields from the C<biblio>,
2249 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2250 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2256 my $dbh = C4::Context->dbh;
2257 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");
2260 $sth->execute($bibitem);
2262 $data = $sth->fetchrow_hashref;
2269 =item getbibliofromitemnumber
2271 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2273 Looks up the item with the given itemnumber.
2275 C<$env> and C<$dbh> are ignored.
2277 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2278 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2283 sub getbibliofromitemnumber {
2284 my ($env,$dbh,$itemnumber) = @_;
2285 $dbh = C4::Context->dbh;
2286 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2287 where items.itemnumber = ?
2288 and biblio.biblionumber = items.biblionumber
2289 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2291 $sth->execute($itemnumber);
2292 my $data=$sth->fetchrow_hashref;
2299 @barcodes = &barcodes($biblioitemnumber);
2301 Given a biblioitemnumber, looks up the corresponding items.
2303 Returns an array of references-to-hash; the keys are C<barcode> and
2306 The returned items include very overdue items, but not lost ones.
2311 #called from request.pl
2312 my ($biblioitemnumber)=@_;
2313 my $dbh = C4::Context->dbh;
2314 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2315 WHERE biblioitemnumber = ?
2316 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2317 $sth->execute($biblioitemnumber);
2320 while (my $data=$sth->fetchrow_hashref){
2321 $barcodes[$i]=$data;
2331 $item = &itemdata($barcode);
2333 Looks up the item with the given barcode, and returns a
2334 reference-to-hash containing information about that item. The keys of
2335 the hash are the fields from the C<items> and C<biblioitems> tables in
2340 sub get_item_from_barcode {
2342 my $dbh = C4::Context->dbh;
2343 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2344 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2345 $sth->execute($barcode);
2346 my $data=$sth->fetchrow_hashref;
2354 @issues = &itemissues($biblioitemnumber, $biblio);
2356 Looks up information about who has borrowed the bookZ<>(s) with the
2357 given biblioitemnumber.
2359 C<$biblio> is ignored.
2361 C<&itemissues> returns an array of references-to-hash. The keys
2362 include the fields from the C<items> table in the Koha database.
2363 Additional keys include:
2369 If the item is currently on loan, this gives the due date.
2371 If the item is not on loan, then this is either "Available" or
2372 "Cancelled", if the item has been withdrawn.
2376 If the item is currently on loan, this gives the card number of the
2377 patron who currently has the item.
2379 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2381 These give the timestamp for the last three times the item was
2384 =item C<card0>, C<card1>, C<card2>
2386 The card number of the last three patrons who borrowed this item.
2388 =item C<borrower0>, C<borrower1>, C<borrower2>
2390 The borrower number of the last three patrons who borrowed this item.
2397 my ($bibitem, $biblio)=@_;
2398 my $dbh = C4::Context->dbh;
2399 # FIXME - If this function die()s, the script will abort, and the
2400 # user won't get anything; depending on how far the script has
2401 # gotten, the user might get a blank page. It would be much better
2402 # to at least print an error message. The easiest way to do this
2403 # is to set $SIG{__DIE__}.
2404 my $sth = $dbh->prepare("Select * from items where
2405 items.biblioitemnumber = ?")
2406 || die $dbh->errstr;
2410 $sth->execute($bibitem)
2411 || die $sth->errstr;
2413 while (my $data = $sth->fetchrow_hashref) {
2414 # Find out who currently has this item.
2415 # FIXME - Wouldn't it be better to do this as a left join of
2416 # some sort? Currently, this code assumes that if
2417 # fetchrow_hashref() fails, then the book is on the shelf.
2418 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2419 # database server crash), not just because no items match the
2421 my $sth2 = $dbh->prepare("select * from issues,borrowers
2422 where itemnumber = ?
2423 and returndate is NULL
2424 and issues.borrowernumber = borrowers.borrowernumber");
2426 $sth2->execute($data->{'itemnumber'});
2427 if (my $data2 = $sth2->fetchrow_hashref) {
2428 $data->{'date_due'} = $data2->{'date_due'};
2429 $data->{'card'} = $data2->{'cardnumber'};
2430 $data->{'borrower'} = $data2->{'borrowernumber'};
2432 if ($data->{'wthdrawn'} eq '1') {
2433 $data->{'date_due'} = 'Cancelled';
2435 $data->{'date_due'} = 'Available';
2441 # Find the last 3 people who borrowed this item.
2442 $sth2 = $dbh->prepare("select * from issues, borrowers
2443 where itemnumber = ?
2444 and issues.borrowernumber = borrowers.borrowernumber
2445 and returndate is not NULL
2446 order by returndate desc,timestamp desc") || die $dbh->errstr;
2447 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2448 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2449 if (my $data2 = $sth2->fetchrow_hashref) {
2450 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2451 $data->{"card$i2"} = $data2->{'cardnumber'};
2452 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2457 $results[$i] = $data;
2467 ($count, $subjects) = &getsubject($biblionumber);
2469 Looks up the subjects of the book with the given biblionumber. Returns
2470 a two-element list. C<$subjects> is a reference-to-array, where each
2471 element is a subject of the book, and C<$count> is the number of
2472 elements in C<$subjects>.
2478 my $dbh = C4::Context->dbh;
2479 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2480 $sth->execute($bibnum);
2483 while (my $data=$sth->fetchrow_hashref){
2488 return($i,\@results);
2493 ($count, $authors) = &getaddauthor($biblionumber);
2495 Looks up the additional authors for the book with the given
2498 Returns a two-element list. C<$authors> is a reference-to-array, where
2499 each element is an additional author, and C<$count> is the number of
2500 elements in C<$authors>.
2506 my $dbh = C4::Context->dbh;
2507 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2508 $sth->execute($bibnum);
2511 while (my $data=$sth->fetchrow_hashref){
2516 return($i,\@results);
2522 ($count, $subtitles) = &getsubtitle($biblionumber);
2524 Looks up the subtitles for the book with the given biblionumber.
2526 Returns a two-element list. C<$subtitles> is a reference-to-array,
2527 where each element is a subtitle, and C<$count> is the number of
2528 elements in C<$subtitles>.
2534 my $dbh = C4::Context->dbh;
2535 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2536 $sth->execute($bibnum);
2539 while (my $data=$sth->fetchrow_hashref){
2544 return($i,\@results);
2550 ($count, @websites) = &getwebsites($biblionumber);
2552 Looks up the web sites pertaining to the book with the given
2555 C<$count> is the number of elements in C<@websites>.
2557 C<@websites> is an array of references-to-hash; the keys are the
2558 fields from the C<websites> table in the Koha database.
2561 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2562 #(with add / modify / delete subs)
2565 my ($biblionumber) = @_;
2566 my $dbh = C4::Context->dbh;
2567 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2571 $sth->execute($biblionumber);
2572 while (my $data = $sth->fetchrow_hashref) {
2573 # FIXME - The URL scheme shouldn't be stripped off, at least
2574 # not here, since it's part of the URL, and will be useful in
2575 # constructing a link to the site. If you don't want the user
2576 # to see the "http://" part, strip that off when building the
2578 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2580 $results[$count] = $data;
2585 return($count, @results);
2588 =item getwebbiblioitems
2590 ($count, @results) = &getwebbiblioitems($biblionumber);
2592 Given a book's biblionumber, looks up the web versions of the book
2593 (biblioitems with itemtype C<WEB>).
2595 C<$count> is the number of items in C<@results>. C<@results> is an
2596 array of references-to-hash; the keys are the items from the
2597 C<biblioitems> table of the Koha database.
2601 sub getwebbiblioitems {
2602 my ($biblionumber) = @_;
2603 my $dbh = C4::Context->dbh;
2604 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2605 and itemtype = 'WEB'");
2609 $sth->execute($biblionumber);
2610 while (my $data = $sth->fetchrow_hashref) {
2611 $data->{'url'} =~ s/^http:\/\///;
2612 $results[$count] = $data;
2617 return($count, @results);
2618 } # sub getwebbiblioitems
2622 # converts ISO 5426 coded string to ISO 8859-1
2623 # sloppy code : should be improved in next issue
2624 my ( $string, $encoding ) = @_;
2627 # $encoding = C4::Context->preference("marcflavour") unless $encoding;
2628 if ( $encoding eq "UNIMARC" ) {
2697 # this handles non-sorting blocks (if implementation requires this)
2698 $string = nsb_clean($_);
2700 elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
2701 if (/[\xc1-\xff]/) {
2754 # this handles non-sorting blocks (if implementation requires this)
2755 $string = nsb_clean($_);
2762 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2763 my $NSE = '\x89'; # NSE : Non Sorting Block end
2764 # handles non sorting blocks
2768 s/[ ]{0,1}$NSE/) /gm;
2775 my $dbh = C4::Context->dbh;
2776 my $result = MARCmarc2koha($dbh,$record,'');
2778 my ($biblionumber,$bibid,$title);
2779 # search duplicate on ISBN, easy and fast...
2780 if ($result->{isbn}) {
2781 $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=?");
2782 $sth->execute($result->{'isbn'});
2783 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2784 return $biblionumber,$bibid,$title if ($biblionumber);
2786 # a more complex search : build a request for SearchMarc::catalogsearch()
2787 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2788 # search on biblio.title
2789 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2790 if ($record->field($tag)) {
2791 if ($record->field($tag)->subfields($subfield)) {
2792 push @tags, "'".$tag.$subfield."'";
2793 push @and_or, "and";
2794 push @excluding, "";
2795 push @operator, "contains";
2796 push @value, $record->field($tag)->subfield($subfield);
2797 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2800 # ... and on biblio.author
2801 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2802 if ($record->field($tag)) {
2803 if ($record->field($tag)->subfields($subfield)) {
2804 push @tags, "'".$tag.$subfield."'";
2805 push @and_or, "and";
2806 push @excluding, "";
2807 push @operator, "contains";
2808 push @value, $record->field($tag)->subfield($subfield);
2809 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2812 # ... and on publicationyear.
2813 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
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, "=";
2820 push @value, $record->field($tag)->subfield($subfield);
2821 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2825 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
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, "=";
2832 push @value, $record->field($tag)->subfield($subfield);
2833 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2836 # ... and on publisher.
2837 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
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 publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2848 # ... and on volume.
2849 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
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 volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2861 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2862 # there is at least 1 result => return the 1st one
2864 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2865 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2867 # no result, returns nothing
2874 if(substr($isbn, 0, 1) <=7) {
2875 $seg1 = substr($isbn, 0, 1);
2876 } elsif(substr($isbn, 0, 2) <= 94) {
2877 $seg1 = substr($isbn, 0, 2);
2878 } elsif(substr($isbn, 0, 3) <= 995) {
2879 $seg1 = substr($isbn, 0, 3);
2880 } elsif(substr($isbn, 0, 4) <= 9989) {
2881 $seg1 = substr($isbn, 0, 4);
2883 $seg1 = substr($isbn, 0, 5);
2885 my $x = substr($isbn, length($seg1));
2887 if(substr($x, 0, 2) <= 19) {
2888 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2889 $seg2 = substr($x, 0, 2);
2890 } elsif(substr($x, 0, 3) <= 699) {
2891 $seg2 = substr($x, 0, 3);
2892 } elsif(substr($x, 0, 4) <= 8399) {
2893 $seg2 = substr($x, 0, 4);
2894 } elsif(substr($x, 0, 5) <= 89999) {
2895 $seg2 = substr($x, 0, 5);
2896 } elsif(substr($x, 0, 6) <= 9499999) {
2897 $seg2 = substr($x, 0, 6);
2899 $seg2 = substr($x, 0, 7);
2901 my $seg3=substr($x,length($seg2));
2902 $seg3=substr($seg3,0,length($seg3)-1) ;
2903 my $seg4 = substr($x, -1, 1);
2904 return "$seg1-$seg2-$seg3-$seg4";
2908 END { } # module clean-up code here (global destructor)
2914 Koha Developement team <info@koha.org>
2916 Paul POULAIN paul.poulain@free.fr
2922 # Revision 1.138 2006/02/14 11:25:22 tipaul
2923 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
2925 # Revision 1.137 2006/02/13 16:34:26 tipaul
2926 # fixing some warnings (perl -w should be quiet)
2928 # Revision 1.136 2006/01/10 17:01:29 tipaul
2929 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
2931 # Revision 1.135 2006/01/06 16:39:37 tipaul
2932 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
2933 # Seems not to break too many things, but i'm probably wrong here.
2934 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
2936 # - removing useless directories (koha-html and koha-plucene)
2938 # Revision 1.134 2006/01/04 15:54:55 tipaul
2939 # utf8 is a : go for beta test in HEAD.
2940 # some explanations :
2941 # - 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.
2942 # - *-top.inc will show the pages in utf8
2943 # - 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.
2944 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
2946 # Revision 1.133 2005/12/12 14:25:51 thd
2949 # Reverse array filled with elements from repeated subfields
2950 # to avoid last to first concatenation of elements in Koha DB.-
2952 # Revision 1.132 2005-10-26 09:12:33 tipaul
2953 # big commit, still breaking things...
2955 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
2956 # * code cleaning (cleaning warnings from perl -w) continued
2958 # Revision 1.131 2005/09/22 10:01:45 tipaul
2959 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
2961 # Revision 1.130 2005/09/02 14:34:14 tipaul
2962 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
2963 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
2964 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
2966 # Revision 1.129 2005/08/12 13:50:31 tipaul
2967 # removing useless sub declarations
2969 # Revision 1.128 2005/08/11 16:12:47 tipaul
2970 # Playing with the zebra...
2972 # * go to koha cvs home directory
2973 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
2974 # * put your zebra.cfg files here & create your database.
2975 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
2976 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
2979 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
2980 # * deletion still not work
2981 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
2983 # recordId: (bib1,Local-number)
2987 # elm 090 Local-number -
2988 # elm 090/? Local-number -
2989 # elm 090/?/9 Local-number !:w
2991 # (090$9 being the field mapped to biblio.biblionumber in Koha)
2993 # Revision 1.127 2005/08/11 14:37:32 tipaul
2995 # * removing useless subs
2996 # * removing some subs that are also elsewhere
2997 # * 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)
2999 # Revision 1.126 2005/08/11 09:13:28 tipaul
3000 # just removing useless subs (a lot !!!) for code cleaning
3002 # Revision 1.125 2005/08/11 09:00:07 tipaul
3003 # Ok guys, this time, it seems that item add and modif begin working as expected...
3004 # Still a lot of bugs to fix, of course
3006 # Revision 1.124 2005/08/10 10:21:15 tipaul
3007 # continuing the road to zebra :
3008 # - the biblio add begins to work.
3009 # - the biblio modif begins to work.
3011 # (still without doing anything on zebra)
3012 # (no new change in updatedatabase)
3014 # Revision 1.123 2005/08/09 14:10:28 tipaul
3015 # 1st commit to go to zebra.
3016 # don't update your cvs if you want to have a working head...
3018 # this commit contains :
3019 # * 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...
3020 # * 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.
3021 # * other files : get rid of bibid and use biblionumber instead.
3024 # * does not do anything on zebra yet.
3025 # * if you rename marc_subfield_table, you can't search anymore.
3026 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3027 # * 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 ;-) )
3029 # 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
3030 # 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.
3032 # tipaul cutted previous commit notes