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");
187 z3950_extended_services can handle any interaction with Zebra's extended serices package.
189 $Zconn contains the server connection object (which is set before calling this s
192 $service type is one of:
193 itemorder,create,drop,commit,update,xmlupdate
195 $service_options is a hash of key/value pairs. For instance,
196 if service_type is 'update', $service_options should contain:
198 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
199 (recordidOpaque => Opaque Record ID (user supplied)
203 recordidNumber => Record ID number (system number))
204 record => the record itself
208 syntax => the record syntax (transfer syntax)
209 databaseName = Database from connection object
212 sub z3950_extended_services {
213 my ($Zconn,$serviceType,$serviceOptions,$record) = @_;
215 # create a new package object
216 my $Zpackage = $Zconn->package();
219 $Zpackage->option(action => $serviceOptions->{'action'});
221 if ($serviceOptions->{'databaseName'}) {
222 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
224 if ($serviceOptions->{'recordIdNumber'}) {
225 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
227 if ($serviceOptions->{'recordIdOpaque'}) {
228 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
231 # this is an ILL request (Zebra doesn't support it)
232 if ($serviceType eq 'itemorder') {
233 $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
234 $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
235 $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
236 $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
240 $Zpackage->option(record => $record);
241 if ($serviceOptions->{'syntax'}) {
242 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
246 # send the request, handle any exception encountered
247 eval { $Zpackage->send($serviceType) };
248 if ($@ && $@->isa("ZOOM::Exception")) {
249 print "Oops! ", $@->message(), "\n";
252 # free up package resources
253 $Zpackage->destroy();
256 =head2 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
260 2nd param is 1 for liblibrarian and 0 for libopac
261 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
263 returns a hash with all values for all fields and subfields for a given MARC framework :
264 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
266 ->{mandatory} = $mandatory;
267 ->{repeatable} = $repeatable;
268 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
270 ->{mandatory} = $mandatory;
271 ->{repeatable} = $repeatable;
272 ->{authorised_value} = $authorised_value;
273 ->{authtypecode} = $authtypecode;
274 ->{value_builder} = $value_builder;
275 ->{kohafield} = $kohafield;
276 ->{seealso} = $seealso;
277 ->{hidden} = $hidden;
286 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
287 $frameworkcode = "" unless $frameworkcode;
288 $forlibrarian = 1 unless $forlibrarian;
290 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
292 # check that framework exists
295 "select count(*) from marc_tag_structure where frameworkcode=?");
296 $sth->execute($frameworkcode);
297 my ($total) = $sth->fetchrow;
298 $frameworkcode = "" unless ( $total > 0 );
301 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
303 $sth->execute($frameworkcode);
304 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
306 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
307 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
308 $res->{$tag}->{tab} = ""; # XXX
309 $res->{$tag}->{mandatory} = $mandatory;
310 $res->{$tag}->{repeatable} = $repeatable;
315 "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"
317 $sth->execute($frameworkcode);
320 my $authorised_value;
330 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
331 $mandatory, $repeatable, $authorised_value, $authtypecode,
332 $value_builder, $kohafield, $seealso, $hidden,
337 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
338 $res->{$tag}->{$subfield}->{tab} = $tab;
339 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
340 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
341 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
342 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
343 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
344 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
345 $res->{$tag}->{$subfield}->{seealso} = $seealso;
346 $res->{$tag}->{$subfield}->{hidden} = $hidden;
347 $res->{$tag}->{$subfield}->{isurl} = $isurl;
348 $res->{$tag}->{$subfield}->{link} = $link;
353 =head2 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
357 finds MARC tag and subfield for a given kohafield
358 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
364 sub MARCfind_marc_from_kohafield {
365 my ( $dbh, $kohafield,$frameworkcode ) = @_;
366 return 0, 0 unless $kohafield;
367 $frameworkcode='' unless $frameworkcode;
368 my $relations = C4::Context->marcfromkohafield;
369 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
372 =head2 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
376 Returns a MARC::Record for the biblio $biblionumber.
382 # Returns MARC::Record of the biblio passed in parameter.
383 my ( $dbh, $biblionumber ) = @_;
384 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
385 $sth->execute($biblionumber);
386 my ($marc) = $sth->fetchrow;
387 my $record = MARC::Record::new_from_usmarc($marc);
391 =head2 $XML = &XMLgetbiblio($dbh,$biblionumber);
395 Returns a raw XML for the biblio $biblionumber.
401 # Returns MARC::Record of the biblio passed in parameter.
402 my ( $dbh, $biblionumber ) = @_;
403 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
404 $sth->execute($biblionumber);
405 my ($XML,$marc) = $sth->fetchrow;
406 # my $record =MARC::Record::new_from_usmarc($marc);
407 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
411 =head2 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
415 Returns a MARC::Record with all items of biblio # $biblionumber
423 my ( $dbh, $biblionumber, $itemnumber ) = @_;
424 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
425 # get the complete MARC record
426 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
427 $sth->execute($biblionumber);
428 my ($rawmarc) = $sth->fetchrow;
429 my $record = MARC::File::USMARC::decode($rawmarc);
430 # now, find the relevant itemnumber
431 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
432 # prepare the new item record
433 my $itemrecord = MARC::Record->new();
434 # parse all fields fields from the complete record
435 foreach ($record->field($itemnumberfield)) {
436 # when the item field is found, save it
437 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
438 $itemrecord->append_fields($_);
445 =head2 sub find_biblioitemnumber($dbh,$biblionumber);
449 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
450 This sub is useless when MARC=OFF
455 sub find_biblioitemnumber {
456 my ( $dbh, $biblionumber ) = @_;
457 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
458 $sth->execute($biblionumber);
459 my ($biblioitemnumber) = $sth->fetchrow;
460 return $biblioitemnumber;
463 =head2 $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
467 returns the framework of a given biblio
473 sub MARCfind_frameworkcode {
474 my ( $dbh, $biblionumber ) = @_;
475 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
476 $sth->execute($biblionumber);
477 my ($frameworkcode) = $sth->fetchrow;
478 return $frameworkcode;
481 =head2 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
485 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
486 all entries of the hash are transformed into their matching MARC field/subfield.
492 sub MARCkoha2marcBiblio {
494 # this function builds partial MARC::Record from the old koha-DB fields
495 my ( $dbh, $bibliohash ) = @_;
496 # we don't have biblio entries in the hash, so we add them first
497 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
498 $sth->execute($bibliohash->{biblionumber});
499 my $biblio = $sth->fetchrow_hashref;
500 foreach (keys %$biblio) {
501 $bibliohash->{$_}=$biblio->{$_};
503 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
504 my $record = MARC::Record->new();
505 foreach ( keys %$bibliohash ) {
506 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
507 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
510 # other fields => additional authors, subjects, subtitles
511 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
512 $sth2->execute($bibliohash->{biblionumber});
513 while ( my $row = $sth2->fetchrow_hashref ) {
514 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
516 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
517 $sth2->execute($bibliohash->{biblionumber});
518 while ( my $row = $sth2->fetchrow_hashref ) {
519 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
521 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
522 $sth2->execute($bibliohash->{biblionumber});
523 while ( my $row = $sth2->fetchrow_hashref ) {
524 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
530 =head2 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
532 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
533 all entries of the hash are transformed into their matching MARC field/subfield.
541 sub MARCkoha2marcItem {
543 # this function builds partial MARC::Record from the old koha-DB fields
544 my ( $dbh, $item ) = @_;
546 # my $dbh=&C4Connect;
547 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
548 my $record = MARC::Record->new();
550 foreach( keys %$item ) {
552 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
559 =head2 MARCkoha2marcOnefield
563 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
569 sub MARCkoha2marcOnefield {
570 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
573 $sth->execute($frameworkcode,$kohafieldname);
574 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
575 if ( $record->field($tagfield) ) {
576 my $tag = $record->field($tagfield);
578 $tag->add_subfields( $tagsubfield, $value );
579 $record->delete_field($tag);
580 $record->add_fields($tag);
584 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
590 =head2 $MARCrecord = MARChtml2marc($dbh,$rtags,$rsubfields,$rvalues,%indicators);
594 transforms the parameters (coming from HTML form) into a MARC::Record
595 parameters with r are references to arrays.
597 FIXME : should be improved for 3.0, to avoid having 4 differents arrays
604 my ($dbh,$rtags,$rsubfields,$rvalues,%indicators) = @_;
606 my $record = MARC::Record->new();
607 # my %subfieldlist=();
608 my $prevvalue; # if tag <10
609 my $field; # if tag >=10
610 for (my $i=0; $i< @$rtags; $i++) {
611 next unless @$rvalues[$i];
612 # rebuild MARC::Record
613 # warn "0=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ";
614 if (@$rtags[$i] ne $prevtag) {
617 if ($prevtag ne '000') {
618 $record->add_fields((sprintf "%03s",$prevtag),$prevvalue);
620 $record->leader($prevvalue);
625 $record->add_fields($field);
628 $indicators{@$rtags[$i]}.=' ';
629 if (@$rtags[$i] <10) {
630 $prevvalue= @$rvalues[$i];
634 $field = MARC::Field->new( (sprintf "%03s",@$rtags[$i]), substr($indicators{@$rtags[$i]},0,1),substr($indicators{@$rtags[$i]},1,1), @$rsubfields[$i] => @$rvalues[$i]);
635 # warn "1=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
637 $prevtag = @$rtags[$i];
639 if (@$rtags[$i] <10) {
640 $prevvalue=@$rvalues[$i];
642 if (length(@$rvalues[$i])>0) {
643 $field->add_subfields(@$rsubfields[$i] => @$rvalues[$i]);
644 # warn "2=>".@$rtags[$i].@$rsubfields[$i]." = ".@$rvalues[$i].": ".$field->as_formatted;
647 $prevtag= @$rtags[$i];
650 # the last has not been included inside the loop... do it now !
651 $record->add_fields($field) if $field;
652 # warn "HTML2MARC=".$record->as_formatted;
657 =head2 $hash = &MARCmarc2koha($dbh,$MARCRecord);
661 builds a hash with old-db datas from a MARC::Record
668 my ($dbh,$record,$frameworkcode) = @_;
669 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
671 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
674 while (($field)=$sth2->fetchrow) {
675 # warn "biblio.".$field;
676 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
678 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
680 while (($field)=$sth2->fetchrow) {
681 if ($field eq 'notes') { $field = 'bnotes'; }
682 # warn "biblioitems".$field;
683 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
685 $sth2=$dbh->prepare("SHOW COLUMNS from items");
687 while (($field)=$sth2->fetchrow) {
688 # warn "items".$field;
689 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
691 # additional authors : specific
692 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
693 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
694 # modify copyrightdate to keep only the 1st year found
695 my $temp = $result->{'copyrightdate'};
697 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
699 $result->{'copyrightdate'} = $1;
700 } else { # if no cYYYY, get the 1st date.
701 $temp =~ m/(\d\d\d\d)/;
702 $result->{'copyrightdate'} = $1;
705 # modify publicationyear to keep only the 1st year found
706 $temp = $result->{'publicationyear'};
707 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
709 $result->{'publicationyear'} = $1;
710 } else { # if no cYYYY, get the 1st date.
711 $temp =~ m/(\d\d\d\d)/;
712 $result->{'publicationyear'} = $1;
717 sub MARCmarc2kohaOneField {
719 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
720 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
721 # warn "kohatable / $kohafield / $result / ";
725 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
726 foreach my $field ( $record->field($tagfield) ) {
727 if ($field->tag()<10) {
728 if ($result->{$kohafield}) {
729 # Reverse array filled with elements from repeated subfields
730 # from first to last to avoid last to first concatenation of
731 # elements in Koha DB. -- thd.
732 $result->{$kohafield} .= " | ".reverse($field->data());
734 $result->{$kohafield} = $field->data();
737 if ( $field->subfields ) {
738 my @subfields = $field->subfields();
739 foreach my $subfieldcount ( 0 .. $#subfields ) {
740 if ($subfields[$subfieldcount][0] eq $subfield) {
741 if ( $result->{$kohafield} ) {
742 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
745 $result->{$kohafield} = $subfields[$subfieldcount][1];
752 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
756 =head2 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
760 creates a biblio from a MARC::Record.
767 my ( $dbh, $record, $frameworkcode ) = @_;
769 my $biblioitemnumber;
770 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
771 $olddata->{frameworkcode} = $frameworkcode;
772 $biblionumber = REALnewbiblio( $dbh, $olddata );
773 $olddata->{biblionumber} = $biblionumber;
774 # add biblionumber into the MARC record (it's the ID for zebra)
775 my ( $tagfield, $tagsubfield ) =
776 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
780 $newfield = MARC::Field->new(
781 $tagfield, $biblionumber,
784 $newfield = MARC::Field->new(
785 $tagfield, '', '', "$tagsubfield" => $biblionumber,
788 # drop old field (just in case it already exist and create new one...
789 my $old_field = $record->field($tagfield);
790 $record->delete_field($old_field);
791 $record->add_fields($newfield);
793 #create the marc entry, that stores the rax marc record in Koha 3.0
794 $olddata->{marc} = $record->as_usmarc();
795 $olddata->{marcxml} = $record->as_xml();
796 # and create biblioitem, that's all folks !
797 $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
799 # search subtiles, addiauthors and subjects
800 ( $tagfield, $tagsubfield ) =
801 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
802 my @addiauthfields = $record->field($tagfield);
803 foreach my $addiauthfield (@addiauthfields) {
804 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
805 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
806 REALmodaddauthor( $dbh, $biblionumber,
807 $addiauthsubfields[$subfieldcount] );
810 ( $tagfield, $tagsubfield ) =
811 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
812 my @subtitlefields = $record->field($tagfield);
813 foreach my $subtitlefield (@subtitlefields) {
814 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
815 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
816 REALnewsubtitle( $dbh, $biblionumber,
817 $subtitlesubfields[$subfieldcount] );
820 ( $tagfield, $tagsubfield ) =
821 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
822 my @subj = $record->field($tagfield);
824 foreach my $subject (@subj) {
825 my @subjsubfield = $subject->subfield($tagsubfield);
826 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
827 push @subjects, $subjsubfield[$subfieldcount];
830 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
831 return ( $biblionumber, $biblioitemnumber );
834 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
838 modify the framework of a biblio
844 sub NEWmodbiblioframework {
845 my ($dbh,$biblionumber,$frameworkcode) =@_;
846 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
847 $sth->execute($frameworkcode,$biblionumber);
851 =head2 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
855 modify a biblio (MARC=ON)
862 my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
863 $frameworkcode="" unless $frameworkcode;
864 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
865 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
867 $oldbiblio->{frameworkcode} = $frameworkcode;
868 #create the marc entry, that stores the rax marc record in Koha 3.0
869 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
870 $oldbiblio->{marc} = $record->as_usmarc();
871 $oldbiblio->{marcxml} = $record->as_xml();
872 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
873 REALmodbiblio($dbh,$oldbiblio);
874 REALmodbiblioitem($dbh,$oldbiblio);
875 # now, modify addi authors, subject, addititles.
876 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
877 my @addiauthfields = $record->field($tagfield);
878 foreach my $addiauthfield (@addiauthfields) {
879 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
880 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
881 foreach my $subfieldcount (0..$#addiauthsubfields) {
882 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
885 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
886 my @subtitlefields = $record->field($tagfield);
887 foreach my $subtitlefield (@subtitlefields) {
888 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
889 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
891 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
892 foreach my $subfieldcount (0..$#subtitlesubfields) {
893 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
894 REALnewsubtitle($dbh,$biblionumber,$subtit);
898 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
899 my @subj = $record->field($tagfield);
901 foreach my $subject (@subj) {
902 my @subjsubfield = $subject->subfield($tagsubfield);
903 foreach my $subfieldcount (0..$#subjsubfield) {
904 push @subjects,$subjsubfield[$subfieldcount];
907 REALmodsubject($dbh,$biblionumber,1,@subjects);
911 =head2 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
922 my ( $dbh, $bibid ) = @_;
923 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
924 &REALdelbiblio( $dbh, $biblio );
927 "select biblioitemnumber from biblioitems where biblionumber=?");
928 $sth->execute($biblio);
929 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
930 REALdelbiblioitem( $dbh, $biblioitemnumber );
932 &MARCdelbiblio( $dbh, $bibid, 0 );
935 =head2 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
939 creates an item from a MARC::Record
946 my ( $dbh, $record, $biblionumber, $biblioitemnumber ) = @_;
949 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
950 my $item = &MARCmarc2koha( $dbh, $record,$frameworkcode );
951 # needs old biblionumber and biblioitemnumber
952 $item->{'biblionumber'} = $biblionumber;
953 $item->{'biblioitemnumber'}=$biblioitemnumber;
954 $item->{marc} = $record->as_usmarc();
956 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
961 =head2 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
972 my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
974 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
975 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
977 $olditem->{marc} = $record->as_usmarc();
978 $olditem->{biblionumber} = $biblionumber;
979 $olditem->{biblioitemnumber} = $biblioitemnumber;
981 REALmoditem( $dbh, $olditem );
985 =head2 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
996 my ( $dbh, $bibid, $itemnumber ) = @_;
997 my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
998 &REALdelitem( $dbh, $itemnumber );
999 &MARCdelitem( $dbh, $bibid, $itemnumber );
1003 =head2 $biblionumber = REALnewbiblio($dbh,$biblio);
1007 adds a record in biblio table. Datas are in the hash $biblio.
1014 my ( $dbh, $biblio ) = @_;
1016 $dbh->do('lock tables biblio WRITE');
1017 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1019 my $data = $sth->fetchrow_arrayref;
1020 my $bibnum = $$data[0] + 1;
1023 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1026 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1027 serial=?, seriestitle=?, notes=?, abstract=?,
1031 $bibnum, $biblio->{'title'},
1032 $biblio->{'author'}, $biblio->{'copyrightdate'},
1033 $biblio->{'serial'}, $biblio->{'seriestitle'},
1034 $biblio->{'notes'}, $biblio->{'abstract'},
1035 $biblio->{'unititle'}
1039 $dbh->do('unlock tables');
1043 =head2 $biblionumber = REALmodbiblio($dbh,$biblio);
1047 modify a record in biblio table. Datas are in the hash $biblio.
1054 my ( $dbh, $biblio ) = @_;
1055 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1056 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1057 where biblionumber = ?"
1060 $biblio->{'title'}, $biblio->{'author'},
1061 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1062 $biblio->{'seriestitle'}, $biblio->{'serial'},
1063 $biblio->{'unititle'}, $biblio->{'notes'},
1064 $biblio->{frameworkcode},
1065 $biblio->{'biblionumber'}
1068 return ( $biblio->{'biblionumber'} );
1071 =head2 REALmodsubtitle($dbh,$bibnum,$subtitle);
1075 modify subtitles in bibliosubtitle table.
1081 sub REALmodsubtitle {
1082 my ( $dbh, $bibnum, $subtitle ) = @_;
1085 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1086 $sth->execute( $subtitle, $bibnum );
1090 =head2 REALmodaddauthor($dbh,$bibnum,$author);
1094 adds or modify additional authors
1095 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1101 sub REALmodaddauthor {
1102 my ( $dbh, $bibnum, @authors ) = @_;
1104 # my $dbh = C4Connect;
1106 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1108 $sth->execute($bibnum);
1110 foreach my $author (@authors) {
1111 if ( $author ne '' ) {
1114 "Insert into additionalauthors set author = ?, biblionumber = ?"
1117 $sth->execute( $author, $bibnum );
1122 } # sub modaddauthor
1124 =head2 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1128 modify/adds subjects
1133 sub REALmodsubject {
1134 my ( $dbh, $bibnum, $force, @subject ) = @_;
1136 # my $dbh = C4Connect;
1137 my $count = @subject;
1139 for ( my $i = 0 ; $i < $count ; $i++ ) {
1140 $subject[$i] =~ s/^ //g;
1141 $subject[$i] =~ s/ $//g;
1144 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1146 $sth->execute( $subject[$i] );
1148 if ( my $data = $sth->fetchrow_hashref ) {
1151 if ( $force eq $subject[$i] || $force == 1 ) {
1153 # subject not in aut, chosen to force anway
1154 # so insert into cataloguentry so its in auth file
1157 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1160 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1165 "$subject[$i]\n does not exist in the subject authority file";
1168 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1170 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1172 while ( my $data = $sth2->fetchrow_hashref ) {
1173 $error .= "<br>$data->{'catalogueentry'}";
1182 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1183 $sth->execute($bibnum);
1187 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1189 foreach $query (@subject) {
1190 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1199 =head2 REALmodbiblioitem($dbh, $biblioitem);
1208 sub REALmodbiblioitem {
1209 my ( $dbh, $biblioitem ) = @_;
1212 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1213 itemtype=?, url=?, isbn=?, issn=?,
1214 publishercode=?, publicationyear=?, classification=?, dewey=?,
1215 subclass=?, illus=?, pages=?, volumeddesc=?,
1216 notes=?, size=?, place=?, marc=?,
1218 where biblioitemnumber=?");
1219 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1220 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1221 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1222 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1223 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1224 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1225 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1226 zebra_create($biblioitem->{biblionumber}, $record);
1227 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1230 =head2 REALnewbiblioitem($dbh,$biblioitem);
1234 adds a biblioitem ($biblioitem is a hash with the values)
1240 sub REALnewbiblioitem {
1241 my ( $dbh, $biblioitem ) = @_;
1243 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1244 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1246 my $biblioitemnumber;
1249 $data = $sth->fetchrow_arrayref;
1250 $biblioitemnumber = $$data[0] + 1;
1252 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1253 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1254 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1255 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1256 my $field=$record->field($biblioitemnumberfield);
1257 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1258 $biblioitem->{marc} = $record->as_usmarc();
1259 $biblioitem->{marcxml} = $record->as_xml();
1261 $sth = $dbh->prepare( "insert into biblioitems set
1262 biblioitemnumber = ?, biblionumber = ?,
1263 volume = ?, number = ?,
1264 classification = ?, itemtype = ?,
1266 issn = ?, dewey = ?,
1267 subclass = ?, publicationyear = ?,
1268 publishercode = ?, volumedate = ?,
1269 volumeddesc = ?, illus = ?,
1270 pages = ?, notes = ?,
1272 marc = ?, place = ?,
1276 $biblioitemnumber, $biblioitem->{'biblionumber'},
1277 $biblioitem->{'volume'}, $biblioitem->{'number'},
1278 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1279 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1280 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1281 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1282 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1283 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1284 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1285 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1286 $biblioitem->{'marc'}, $biblioitem->{'place'},
1287 $biblioitem->{marcxml},
1289 $dbh->do("unlock tables");
1290 zebra_create($biblioitem->{biblionumber}, $record);
1291 return ($biblioitemnumber);
1294 =head2 REALnewsubtitle($dbh,$bibnum,$subtitle);
1298 create a new subtitle
1303 sub REALnewsubtitle {
1304 my ( $dbh, $bibnum, $subtitle ) = @_;
1307 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1308 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1312 =head2 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1316 create a item. $item is a hash and $barcode the barcode.
1323 my ( $dbh, $item, $barcode ) = @_;
1325 # warn "OLDNEWITEMS";
1327 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1328 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1333 $data = $sth->fetchrow_hashref;
1334 $itemnumber = $data->{'max(itemnumber)'} + 1;
1336 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1337 if ( $item->{'loan'} ) {
1338 $item->{'notforloan'} = $item->{'loan'};
1341 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1342 if ( $item->{'dateaccessioned'} ) {
1343 $sth = $dbh->prepare( "Insert into items set
1344 itemnumber = ?, biblionumber = ?,
1345 multivolumepart = ?,
1346 biblioitemnumber = ?, barcode = ?,
1347 booksellerid = ?, dateaccessioned = ?,
1348 homebranch = ?, holdingbranch = ?,
1349 price = ?, replacementprice = ?,
1350 replacementpricedate = NOW(), datelastseen = NOW(),
1351 multivolume = ?, stack = ?,
1352 itemlost = ?, wthdrawn = ?,
1353 paidfor = ?, itemnotes = ?,
1354 itemcallnumber =?, notforloan = ?,
1359 $itemnumber, $item->{'biblionumber'},
1360 $item->{'multivolumepart'},
1361 $item->{'biblioitemnumber'},$item->{barcode},
1362 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1363 $item->{'homebranch'}, $item->{'holdingbranch'},
1364 $item->{'price'}, $item->{'replacementprice'},
1365 $item->{multivolume}, $item->{stack},
1366 $item->{itemlost}, $item->{wthdrawn},
1367 $item->{paidfor}, $item->{'itemnotes'},
1368 $item->{'itemcallnumber'}, $item->{'notforloan'},
1371 if ( defined $sth->errstr ) {
1372 $error .= $sth->errstr;
1376 $sth = $dbh->prepare( "Insert into items set
1377 itemnumber = ?, biblionumber = ?,
1378 multivolumepart = ?,
1379 biblioitemnumber = ?, barcode = ?,
1380 booksellerid = ?, dateaccessioned = NOW(),
1381 homebranch = ?, holdingbranch = ?,
1382 price = ?, replacementprice = ?,
1383 replacementpricedate = NOW(), datelastseen = NOW(),
1384 multivolume = ?, stack = ?,
1385 itemlost = ?, wthdrawn = ?,
1386 paidfor = ?, itemnotes = ?,
1387 itemcallnumber =?, notforloan = ?,
1392 $itemnumber, $item->{'biblionumber'},
1393 $item->{'multivolumepart'},
1394 $item->{'biblioitemnumber'},$item->{barcode},
1395 $item->{'booksellerid'},
1396 $item->{'homebranch'}, $item->{'holdingbranch'},
1397 $item->{'price'}, $item->{'replacementprice'},
1398 $item->{multivolume}, $item->{stack},
1399 $item->{itemlost}, $item->{wthdrawn},
1400 $item->{paidfor}, $item->{'itemnotes'},
1401 $item->{'itemcallnumber'}, $item->{'notforloan'},
1404 if ( defined $sth->errstr ) {
1405 $error .= $sth->errstr;
1408 # item stored, now, deal with the marc part...
1409 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1410 where biblio.biblionumber=biblioitems.biblionumber and
1411 biblio.biblionumber=?");
1412 $sth->execute($item->{biblionumber});
1413 if ( defined $sth->errstr ) {
1414 $error .= $sth->errstr;
1416 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1417 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1418 my $record = MARC::File::USMARC::decode($rawmarc);
1419 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1420 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1421 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1423 warn $itemnumberfield;
1424 warn $itemrecord->field($itemnumberfield);
1425 my $itemfield = $itemrecord->field($itemnumberfield);
1426 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1427 $record->insert_grouped_field($itemfield);
1428 # save the record into biblioitem
1429 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1430 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber});
1431 if ( defined $sth->errstr ) {
1432 $error .= $sth->errstr;
1434 zebra_create($item->{biblionumber},$record);
1435 $dbh->do('unlock tables');
1436 return ( $itemnumber, $error );
1439 =head2 REALmoditem($dbh,$item);
1450 my ( $dbh, $item ) = @_;
1452 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1453 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1454 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1456 $item->{'barcode'}, $item->{'itemnotes'},
1457 $item->{'itemcallnumber'}, $item->{'notforloan'},
1458 $item->{'location'}, $item->{multivolumepart},
1459 $item->{multivolume}, $item->{stack},
1462 if ( $item->{'lost'} ne '' ) {
1463 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1464 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1465 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1467 $item->{'bibitemnum'}, $item->{'barcode'},
1468 $item->{'itemnotes'}, $item->{'homebranch'},
1469 $item->{'lost'}, $item->{'wthdrawn'},
1470 $item->{'itemcallnumber'}, $item->{'notforloan'},
1471 $item->{'location'}, $item->{multivolumepart},
1472 $item->{multivolume}, $item->{stack},
1475 if ($item->{homebranch}) {
1476 $query.=",homebranch=?";
1477 push @bind, $item->{homebranch};
1479 if ($item->{holdingbranch}) {
1480 $query.=",holdingbranch=?";
1481 push @bind, $item->{holdingbranch};
1484 $query.=" where itemnumber=?";
1485 push @bind,$item->{'itemnum'};
1486 if ( $item->{'replacement'} ne '' ) {
1487 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1489 my $sth = $dbh->prepare($query);
1490 $sth->execute(@bind);
1492 # item stored, now, deal with the marc part...
1493 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1494 where biblio.biblionumber=biblioitems.biblionumber and
1495 biblio.biblionumber=? and
1496 biblioitems.biblioitemnumber=?");
1497 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1498 if ( defined $sth->errstr ) {
1499 $error .= $sth->errstr;
1501 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1502 warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1503 my $record = MARC::File::USMARC::decode($rawmarc);
1504 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1505 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1506 # prepare the new item record
1507 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1508 my $itemfield = $itemrecord->field($itemnumberfield);
1509 $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1510 # parse all fields fields from the complete record
1511 foreach ($record->field($itemnumberfield)) {
1512 # when the previous field is found, replace by the new one
1513 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1514 $_->replace_with($itemfield);
1517 # $record->insert_grouped_field($itemfield);
1518 # save the record into biblioitem
1519 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1520 $sth->execute($record->as_usmarc(),$record->as_xml(),$item->{biblionumber},$item->{biblioitemnumber});
1521 zebra_create($item->biblionumber,$record);
1522 if ( defined $sth->errstr ) {
1523 $error .= $sth->errstr;
1525 $dbh->do('unlock tables');
1530 =head2 REALdelitem($dbh,$itemnum);
1541 my ( $dbh, $itemnum ) = @_;
1543 # my $dbh=C4Connect;
1544 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1545 $sth->execute($itemnum);
1546 my $data = $sth->fetchrow_hashref;
1548 my $query = "Insert into deleteditems set ";
1550 foreach my $temp ( keys %$data ) {
1551 $query .= "$temp = ?,";
1552 push ( @bind, $data->{$temp} );
1557 $sth = $dbh->prepare($query);
1558 $sth->execute(@bind);
1560 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1561 $sth->execute($itemnum);
1567 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1571 deletes a biblioitem
1572 NOTE : not standard sub name. Should be REALdelbiblioitem()
1578 sub REALdelbiblioitem {
1579 my ( $dbh, $biblioitemnumber ) = @_;
1581 # my $dbh = C4Connect;
1582 my $sth = $dbh->prepare( "Select * from biblioitems
1583 where biblioitemnumber = ?"
1587 $sth->execute($biblioitemnumber);
1589 if ( $results = $sth->fetchrow_hashref ) {
1593 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1594 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1595 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1599 $results->{biblioitemnumber}, $results->{biblionumber},
1600 $results->{volume}, $results->{number},
1601 $results->{classification}, $results->{itemtype},
1602 $results->{isbn}, $results->{issn},
1603 $results->{dewey}, $results->{subclass},
1604 $results->{publicationyear}, $results->{publishercode},
1605 $results->{volumedate}, $results->{volumeddesc},
1606 $results->{timestamp}, $results->{illus},
1607 $results->{pages}, $results->{notes},
1608 $results->{size}, $results->{url},
1612 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1613 $sth2->execute($biblioitemnumber);
1618 # Now delete all the items attached to the biblioitem
1619 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1620 $sth->execute($biblioitemnumber);
1622 while ( my $data = $sth->fetchrow_hashref ) {
1623 my $query = "Insert into deleteditems set ";
1625 foreach my $temp ( keys %$data ) {
1626 $query .= "$temp = ?,";
1627 push ( @bind, $data->{$temp} );
1630 my $sth2 = $dbh->prepare($query);
1631 $sth2->execute(@bind);
1634 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1635 $sth->execute($biblioitemnumber);
1639 } # sub deletebiblioitem
1641 =head2 REALdelbiblio($dbh,$biblio);
1652 my ( $dbh, $biblio ) = @_;
1653 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1654 $sth->execute($biblio);
1655 if ( my $data = $sth->fetchrow_hashref ) {
1657 my $query = "Insert into deletedbiblio set ";
1659 foreach my $temp ( keys %$data ) {
1660 $query .= "$temp = ?,";
1661 push ( @bind, $data->{$temp} );
1664 #replacing the last , by ",?)"
1666 $sth = $dbh->prepare($query);
1667 $sth->execute(@bind);
1669 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1670 $sth->execute($biblio);
1676 =head2 $number = itemcount($biblio);
1680 returns the number of items attached to a biblio
1688 my $dbh = C4::Context->dbh;
1691 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1692 $sth->execute($biblio);
1693 my $data = $sth->fetchrow_hashref;
1695 return ( $data->{'count(*)'} );
1698 =head2 $biblionumber = newbiblio($biblio);
1702 create a biblio. The parameter is a hash
1710 my $dbh = C4::Context->dbh;
1711 my $bibnum = REALnewbiblio( $dbh, $biblio );
1712 # finds new (MARC bibid
1713 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1714 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1715 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1719 =head2 $biblionumber = &modbiblio($biblio);
1723 Update a biblio record.
1725 C<$biblio> is a reference-to-hash whose keys are the fields in the
1726 biblio table in the Koha database. All fields must be present, not
1727 just the ones you wish to change.
1729 C<&modbiblio> updates the record defined by
1730 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1732 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1741 my $dbh = C4::Context->dbh;
1742 my $biblionumber=REALmodbiblio($dbh,$biblio);
1743 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1744 # finds new (MARC bibid
1745 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1746 MARCmodbiblio($dbh,$bibid,$record,"",0);
1747 return($biblionumber);
1750 =head2 &modsubtitle($biblionumber, $subtitle);
1754 Sets the subtitle of a book.
1756 C<$biblionumber> is the biblionumber of the book to modify.
1758 C<$subtitle> is the new subtitle.
1765 my ( $bibnum, $subtitle ) = @_;
1766 my $dbh = C4::Context->dbh;
1767 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1770 =head2 &modaddauthor($biblionumber, $author);
1774 Replaces all additional authors for the book with biblio number
1775 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1776 C<&modaddauthor> deletes all additional authors.
1783 my ( $bibnum, @authors ) = @_;
1784 my $dbh = C4::Context->dbh;
1785 &REALmodaddauthor( $dbh, $bibnum, @authors );
1786 } # sub modaddauthor
1788 =head2 $error = &modsubject($biblionumber, $force, @subjects);
1792 $force - a subject to force
1793 $error - Error message, or undef if successful.
1800 my ( $bibnum, $force, @subject ) = @_;
1801 my $dbh = C4::Context->dbh;
1802 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1804 # When MARC is off, ensures that the MARC biblio table gets updated with new
1805 # subjects, of course, it deletes the biblio in marc, and then recreates.
1806 # This check is to ensure that no MARC data exists to lose.
1807 # if (C4::Context->preference("MARC") eq '0'){
1808 # warn "in modSUBJECT";
1809 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1810 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1811 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
1817 =head2 modbibitem($biblioitem);
1821 modify a biblioitem. The parameter is a hash
1828 my ($biblioitem) = @_;
1829 my $dbh = C4::Context->dbh;
1830 &REALmodbiblioitem( $dbh, $biblioitem );
1833 =head2 $biblioitemnumber = newbiblioitem($biblioitem)
1837 create a biblioitem, the parameter is a hash
1844 my ($biblioitem) = @_;
1845 my $dbh = C4::Context->dbh;
1846 # add biblio information to the hash
1847 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
1848 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
1849 my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
1850 return ($bibitemnum);
1853 =head2 newsubtitle($biblionumber,$subtitle);
1857 insert a subtitle for $biblionumber biblio
1865 my ( $bibnum, $subtitle ) = @_;
1866 my $dbh = C4::Context->dbh;
1867 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
1870 =head2 $errors = newitems($item, @barcodes);
1874 insert items ($item is a hash)
1882 my ( $item, @barcodes ) = @_;
1883 my $dbh = C4::Context->dbh;
1887 foreach my $barcode (@barcodes) {
1888 # add items, one by one for each barcode.
1890 $oneitem->{barcode}= $barcode;
1891 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
1892 $oneitem->{marc} = $MARCitem->as_usmarc;
1893 ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
1894 # $errors .= $error;
1895 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
1900 =head2 moditem($item);
1904 modify an item ($item is a hash with all item informations)
1913 my $dbh = C4::Context->dbh;
1914 &REALmoditem( $dbh, $item );
1916 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
1918 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
1919 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
1922 =head2 $error = checkitems($count,@barcodes);
1926 check for each @barcode entry that the barcode is not a duplicate
1933 my ( $count, @barcodes ) = @_;
1934 my $dbh = C4::Context->dbh;
1936 my $sth = $dbh->prepare("Select * from items where barcode=?");
1937 for ( my $i = 0 ; $i < $count ; $i++ ) {
1938 $barcodes[$i] = uc $barcodes[$i];
1939 $sth->execute( $barcodes[$i] );
1940 if ( my $data = $sth->fetchrow_hashref ) {
1941 $error .= " Duplicate Barcode: $barcodes[$i]";
1948 =head2 $delitem($itemnum);
1952 delete item $itemnum being the item number to delete
1960 my $dbh = C4::Context->dbh;
1961 &REALdelitem( $dbh, $itemnum );
1964 =head2 deletebiblioitem($biblioitemnumber);
1968 delete the biblioitem $biblioitemnumber
1974 sub deletebiblioitem {
1975 my ($biblioitemnumber) = @_;
1976 my $dbh = C4::Context->dbh;
1977 &REALdelbiblioitem( $dbh, $biblioitemnumber );
1978 } # sub deletebiblioitem
1980 =head2 delbiblio($biblionumber)
1984 delete biblio $biblionumber
1992 my $dbh = C4::Context->dbh;
1993 &REALdelbiblio( $dbh, $biblio );
1994 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
1995 &MARCdelbiblio( $dbh, $bibid, 0 );
1998 =head2 ($count,@results) = getbiblio($biblionumber);
2002 return an array with hash of biblios.
2004 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2011 my ($biblionumber) = @_;
2012 my $dbh = C4::Context->dbh;
2013 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2015 # || die "Cannot prepare $query\n" . $dbh->errstr;
2019 $sth->execute($biblionumber);
2021 # || die "Cannot execute $query\n" . $sth->errstr;
2022 while ( my $data = $sth->fetchrow_hashref ) {
2023 $results[$count] = $data;
2028 return ( $count, @results );
2033 $data = &bibdata($biblionumber, $type);
2035 Returns information about the book with the given biblionumber.
2037 C<$type> is ignored.
2039 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2040 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2043 In addition, C<$data-E<gt>{subject}> is the list of the book's
2044 subjects, separated by C<" , "> (space, comma, space).
2046 If there are multiple biblioitems with the given biblionumber, only
2047 the first one is considered.
2052 my ($bibnum, $type) = @_;
2053 my $dbh = C4::Context->dbh;
2054 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2056 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2057 left join bibliosubtitle on
2058 biblio.biblionumber = bibliosubtitle.biblionumber
2059 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2060 where biblio.biblionumber = ?
2062 $sth->execute($bibnum);
2064 $data = $sth->fetchrow_hashref;
2066 # handle management of repeated subtitle
2067 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2068 $sth->execute($bibnum);
2070 while (my $dat = $sth->fetchrow_hashref){
2072 $line{subtitle} = $dat->{subtitle};
2073 push @subtitles, \%line;
2075 $data->{subtitles} = \@subtitles;
2077 $sth = $dbh->prepare("Select * from bibliosubject where biblionumber = ?");
2078 $sth->execute($bibnum);
2080 while (my $dat = $sth->fetchrow_hashref){
2082 $line{subject} = $dat->{'subject'};
2083 push @subjects, \%line;
2085 $data->{subjects} = \@subjects;
2087 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2088 $sth->execute($bibnum);
2089 while (my $dat = $sth->fetchrow_hashref){
2090 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2092 chop $data->{'additionalauthors'};
2093 chop $data->{'additionalauthors'};
2094 chop $data->{'additionalauthors'};
2099 =head2 ($count,@results) = getbiblioitem($biblioitemnumber);
2103 return an array with hash of biblioitemss.
2105 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2112 my ($biblioitemnum) = @_;
2113 my $dbh = C4::Context->dbh;
2114 my $sth = $dbh->prepare( "Select * from biblioitems where
2115 biblioitemnumber = ?"
2120 $sth->execute($biblioitemnum);
2122 while ( my $data = $sth->fetchrow_hashref ) {
2123 $results[$count] = $data;
2128 return ( $count, @results );
2129 } # sub getbiblioitem
2131 =head2 ($count,@results) = getbiblioitembybiblionumber($biblionumber);
2135 return an array with hash of biblioitems for the given biblionumber.
2141 sub getbiblioitembybiblionumber {
2142 my ($biblionumber) = @_;
2143 my $dbh = C4::Context->dbh;
2144 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2148 $sth->execute($biblionumber);
2150 while ( my $data = $sth->fetchrow_hashref ) {
2151 $results[$count] = $data;
2156 return ( $count, @results );
2159 =head2 ($count,@results) = getitemsbybiblioitem($biblionumber);
2163 returns an array with hash of items
2169 sub getitemsbybiblioitem {
2170 my ($biblioitemnum) = @_;
2171 my $dbh = C4::Context->dbh;
2172 my $sth = $dbh->prepare( "Select * from items, biblio where
2173 biblio.biblionumber = items.biblionumber and biblioitemnumber
2177 # || die "Cannot prepare $query\n" . $dbh->errstr;
2181 $sth->execute($biblioitemnum);
2183 # || die "Cannot execute $query\n" . $sth->errstr;
2184 while ( my $data = $sth->fetchrow_hashref ) {
2185 $results[$count] = $data;
2190 return ( $count, @results );
2191 } # sub getitemsbybiblioitem
2195 @results = &ItemInfo($env, $biblionumber, $type);
2197 Returns information about books with the given biblionumber.
2199 C<$type> may be either C<intra> or anything else. If it is not set to
2200 C<intra>, then the search will exclude lost, very overdue, and
2205 C<&ItemInfo> returns a list of references-to-hash. Each element
2206 contains a number of keys. Most of them are table items from the
2207 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2208 Koha database. Other keys include:
2212 =item C<$data-E<gt>{branchname}>
2214 The name (not the code) of the branch to which the book belongs.
2216 =item C<$data-E<gt>{datelastseen}>
2218 This is simply C<items.datelastseen>, except that while the date is
2219 stored in YYYY-MM-DD format in the database, here it is converted to
2220 DD/MM/YYYY format. A NULL date is returned as C<//>.
2222 =item C<$data-E<gt>{datedue}>
2224 =item C<$data-E<gt>{class}>
2226 This is the concatenation of C<biblioitems.classification>, the book's
2227 Dewey code, and C<biblioitems.subclass>.
2229 =item C<$data-E<gt>{ocount}>
2231 I think this is the number of copies of the book available.
2233 =item C<$data-E<gt>{order}>
2235 If this is set, it is set to C<One Order>.
2242 my ($env,$biblionumber,$type) = @_;
2243 my $dbh = C4::Context->dbh;
2244 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2245 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2246 WHERE items.biblionumber = ?
2247 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2248 AND biblio.biblionumber = items.biblionumber";
2249 $query .= " order by items.dateaccessioned desc";
2250 my $sth=$dbh->prepare($query);
2251 $sth->execute($biblionumber);
2254 while (my $data=$sth->fetchrow_hashref){
2256 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2257 $isth->execute($data->{'itemnumber'});
2258 if (my $idata=$isth->fetchrow_hashref){
2259 $data->{borrowernumber} = $idata->{borrowernumber};
2260 $data->{cardnumber} = $idata->{cardnumber};
2261 $datedue = format_date($idata->{'date_due'});
2263 if ($datedue eq ''){
2264 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2270 #get branch information.....
2271 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2272 $bsth->execute($data->{'holdingbranch'});
2273 if (my $bdata=$bsth->fetchrow_hashref){
2274 $data->{'branchname'} = $bdata->{'branchname'};
2276 my $date=format_date($data->{'datelastseen'});
2277 $data->{'datelastseen'}=$date;
2278 $data->{'datedue'}=$datedue;
2279 # get notforloan complete status if applicable
2280 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2281 $sthnflstatus->execute;
2282 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2283 if ($authorised_valuecode) {
2284 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2285 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2286 my ($lib) = $sthnflstatus->fetchrow;
2287 $data->{notforloan} = $lib;
2298 ($count, @results) = &bibitems($biblionumber);
2300 Given the biblionumber for a book, C<&bibitems> looks up that book's
2301 biblioitems (different publications of the same book, the audio book
2302 and film versions, etc.).
2304 C<$count> is the number of elements in C<@results>.
2306 C<@results> is an array of references-to-hash; the keys are the fields
2307 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2308 addition, C<itemlost> indicates the availability of the item: if it is
2309 "2", then all copies of the item are long overdue; if it is "1", then
2310 all copies are lost; otherwise, there is at least one copy available.
2316 my $dbh = C4::Context->dbh;
2317 my $sth = $dbh->prepare("SELECT biblioitems.*,
2319 MIN(items.itemlost) as itemlost,
2320 MIN(items.dateaccessioned) as dateaccessioned
2321 FROM biblioitems, itemtypes, items
2322 WHERE biblioitems.biblionumber = ?
2323 AND biblioitems.itemtype = itemtypes.itemtype
2324 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2325 GROUP BY items.biblioitemnumber");
2328 $sth->execute($bibnum);
2329 while (my $data = $sth->fetchrow_hashref) {
2330 $results[$count] = $data;
2334 return($count, @results);
2340 $itemdata = &bibitemdata($biblioitemnumber);
2342 Looks up the biblioitem with the given biblioitemnumber. Returns a
2343 reference-to-hash. The keys are the fields from the C<biblio>,
2344 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2345 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2351 my $dbh = C4::Context->dbh;
2352 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");
2355 $sth->execute($bibitem);
2357 $data = $sth->fetchrow_hashref;
2364 =item getbibliofromitemnumber
2366 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2368 Looks up the item with the given itemnumber.
2370 C<$env> and C<$dbh> are ignored.
2372 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2373 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2378 sub getbibliofromitemnumber {
2379 my ($env,$dbh,$itemnumber) = @_;
2380 $dbh = C4::Context->dbh;
2381 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2382 where items.itemnumber = ?
2383 and biblio.biblionumber = items.biblionumber
2384 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2386 $sth->execute($itemnumber);
2387 my $data=$sth->fetchrow_hashref;
2394 @barcodes = &barcodes($biblioitemnumber);
2396 Given a biblioitemnumber, looks up the corresponding items.
2398 Returns an array of references-to-hash; the keys are C<barcode> and
2401 The returned items include very overdue items, but not lost ones.
2406 #called from request.pl
2407 my ($biblioitemnumber)=@_;
2408 my $dbh = C4::Context->dbh;
2409 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2410 WHERE biblioitemnumber = ?
2411 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2412 $sth->execute($biblioitemnumber);
2415 while (my $data=$sth->fetchrow_hashref){
2416 $barcodes[$i]=$data;
2426 $item = &itemdata($barcode);
2428 Looks up the item with the given barcode, and returns a
2429 reference-to-hash containing information about that item. The keys of
2430 the hash are the fields from the C<items> and C<biblioitems> tables in
2435 sub get_item_from_barcode {
2437 my $dbh = C4::Context->dbh;
2438 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2439 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2440 $sth->execute($barcode);
2441 my $data=$sth->fetchrow_hashref;
2449 @issues = &itemissues($biblioitemnumber, $biblio);
2451 Looks up information about who has borrowed the bookZ<>(s) with the
2452 given biblioitemnumber.
2454 C<$biblio> is ignored.
2456 C<&itemissues> returns an array of references-to-hash. The keys
2457 include the fields from the C<items> table in the Koha database.
2458 Additional keys include:
2464 If the item is currently on loan, this gives the due date.
2466 If the item is not on loan, then this is either "Available" or
2467 "Cancelled", if the item has been withdrawn.
2471 If the item is currently on loan, this gives the card number of the
2472 patron who currently has the item.
2474 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2476 These give the timestamp for the last three times the item was
2479 =item C<card0>, C<card1>, C<card2>
2481 The card number of the last three patrons who borrowed this item.
2483 =item C<borrower0>, C<borrower1>, C<borrower2>
2485 The borrower number of the last three patrons who borrowed this item.
2492 my ($bibitem, $biblio)=@_;
2493 my $dbh = C4::Context->dbh;
2494 # FIXME - If this function die()s, the script will abort, and the
2495 # user won't get anything; depending on how far the script has
2496 # gotten, the user might get a blank page. It would be much better
2497 # to at least print an error message. The easiest way to do this
2498 # is to set $SIG{__DIE__}.
2499 my $sth = $dbh->prepare("Select * from items where
2500 items.biblioitemnumber = ?")
2501 || die $dbh->errstr;
2505 $sth->execute($bibitem)
2506 || die $sth->errstr;
2508 while (my $data = $sth->fetchrow_hashref) {
2509 # Find out who currently has this item.
2510 # FIXME - Wouldn't it be better to do this as a left join of
2511 # some sort? Currently, this code assumes that if
2512 # fetchrow_hashref() fails, then the book is on the shelf.
2513 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2514 # database server crash), not just because no items match the
2516 my $sth2 = $dbh->prepare("select * from issues,borrowers
2517 where itemnumber = ?
2518 and returndate is NULL
2519 and issues.borrowernumber = borrowers.borrowernumber");
2521 $sth2->execute($data->{'itemnumber'});
2522 if (my $data2 = $sth2->fetchrow_hashref) {
2523 $data->{'date_due'} = $data2->{'date_due'};
2524 $data->{'card'} = $data2->{'cardnumber'};
2525 $data->{'borrower'} = $data2->{'borrowernumber'};
2527 if ($data->{'wthdrawn'} eq '1') {
2528 $data->{'date_due'} = 'Cancelled';
2530 $data->{'date_due'} = 'Available';
2536 # Find the last 3 people who borrowed this item.
2537 $sth2 = $dbh->prepare("select * from issues, borrowers
2538 where itemnumber = ?
2539 and issues.borrowernumber = borrowers.borrowernumber
2540 and returndate is not NULL
2541 order by returndate desc,timestamp desc") || die $dbh->errstr;
2542 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2543 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2544 if (my $data2 = $sth2->fetchrow_hashref) {
2545 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2546 $data->{"card$i2"} = $data2->{'cardnumber'};
2547 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2552 $results[$i] = $data;
2562 ($count, $subjects) = &getsubject($biblionumber);
2564 Looks up the subjects of the book with the given biblionumber. Returns
2565 a two-element list. C<$subjects> is a reference-to-array, where each
2566 element is a subject of the book, and C<$count> is the number of
2567 elements in C<$subjects>.
2573 my $dbh = C4::Context->dbh;
2574 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2575 $sth->execute($bibnum);
2578 while (my $data=$sth->fetchrow_hashref){
2583 return($i,\@results);
2588 ($count, $authors) = &getaddauthor($biblionumber);
2590 Looks up the additional authors for the book with the given
2593 Returns a two-element list. C<$authors> is a reference-to-array, where
2594 each element is an additional author, and C<$count> is the number of
2595 elements in C<$authors>.
2601 my $dbh = C4::Context->dbh;
2602 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2603 $sth->execute($bibnum);
2606 while (my $data=$sth->fetchrow_hashref){
2611 return($i,\@results);
2617 ($count, $subtitles) = &getsubtitle($biblionumber);
2619 Looks up the subtitles for the book with the given biblionumber.
2621 Returns a two-element list. C<$subtitles> is a reference-to-array,
2622 where each element is a subtitle, and C<$count> is the number of
2623 elements in C<$subtitles>.
2629 my $dbh = C4::Context->dbh;
2630 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2631 $sth->execute($bibnum);
2634 while (my $data=$sth->fetchrow_hashref){
2639 return($i,\@results);
2645 ($count, @websites) = &getwebsites($biblionumber);
2647 Looks up the web sites pertaining to the book with the given
2650 C<$count> is the number of elements in C<@websites>.
2652 C<@websites> is an array of references-to-hash; the keys are the
2653 fields from the C<websites> table in the Koha database.
2656 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2657 #(with add / modify / delete subs)
2660 my ($biblionumber) = @_;
2661 my $dbh = C4::Context->dbh;
2662 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2666 $sth->execute($biblionumber);
2667 while (my $data = $sth->fetchrow_hashref) {
2668 # FIXME - The URL scheme shouldn't be stripped off, at least
2669 # not here, since it's part of the URL, and will be useful in
2670 # constructing a link to the site. If you don't want the user
2671 # to see the "http://" part, strip that off when building the
2673 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2675 $results[$count] = $data;
2680 return($count, @results);
2683 =item getwebbiblioitems
2685 ($count, @results) = &getwebbiblioitems($biblionumber);
2687 Given a book's biblionumber, looks up the web versions of the book
2688 (biblioitems with itemtype C<WEB>).
2690 C<$count> is the number of items in C<@results>. C<@results> is an
2691 array of references-to-hash; the keys are the items from the
2692 C<biblioitems> table of the Koha database.
2696 sub getwebbiblioitems {
2697 my ($biblionumber) = @_;
2698 my $dbh = C4::Context->dbh;
2699 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2700 and itemtype = 'WEB'");
2704 $sth->execute($biblionumber);
2705 while (my $data = $sth->fetchrow_hashref) {
2706 $data->{'url'} =~ s/^http:\/\///;
2707 $results[$count] = $data;
2712 return($count, @results);
2713 } # sub getwebbiblioitems
2717 # converts ISO 5426 coded string to ISO 8859-1
2718 # sloppy code : should be improved in next issue
2719 my ( $string, $encoding ) = @_;
2722 # $encoding = C4::Context->preference("marcflavour") unless $encoding;
2723 if ( $encoding eq "UNIMARC" ) {
2792 # this handles non-sorting blocks (if implementation requires this)
2793 $string = nsb_clean($_);
2795 elsif ( $encoding eq "USMARC" || $encoding eq "MARC21" ) {
2796 if (/[\xc1-\xff]/) {
2849 # this handles non-sorting blocks (if implementation requires this)
2850 $string = nsb_clean($_);
2857 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2858 my $NSE = '\x89'; # NSE : Non Sorting Block end
2859 # handles non sorting blocks
2863 s/[ ]{0,1}$NSE/) /gm;
2870 my $dbh = C4::Context->dbh;
2871 my $result = MARCmarc2koha($dbh,$record,'');
2873 my ($biblionumber,$bibid,$title);
2874 # search duplicate on ISBN, easy and fast...
2875 if ($result->{isbn}) {
2876 $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=?");
2877 $sth->execute($result->{'isbn'});
2878 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2879 return $biblionumber,$bibid,$title if ($biblionumber);
2881 # a more complex search : build a request for SearchMarc::catalogsearch()
2882 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2883 # search on biblio.title
2884 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2885 if ($record->field($tag)) {
2886 if ($record->field($tag)->subfields($subfield)) {
2887 push @tags, "'".$tag.$subfield."'";
2888 push @and_or, "and";
2889 push @excluding, "";
2890 push @operator, "contains";
2891 push @value, $record->field($tag)->subfield($subfield);
2892 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2895 # ... and on biblio.author
2896 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2897 if ($record->field($tag)) {
2898 if ($record->field($tag)->subfields($subfield)) {
2899 push @tags, "'".$tag.$subfield."'";
2900 push @and_or, "and";
2901 push @excluding, "";
2902 push @operator, "contains";
2903 push @value, $record->field($tag)->subfield($subfield);
2904 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2907 # ... and on publicationyear.
2908 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2909 if ($record->field($tag)) {
2910 if ($record->field($tag)->subfields($subfield)) {
2911 push @tags, "'".$tag.$subfield."'";
2912 push @and_or, "and";
2913 push @excluding, "";
2914 push @operator, "=";
2915 push @value, $record->field($tag)->subfield($subfield);
2916 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2920 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2921 if ($record->field($tag)) {
2922 if ($record->field($tag)->subfields($subfield)) {
2923 push @tags, "'".$tag.$subfield."'";
2924 push @and_or, "and";
2925 push @excluding, "";
2926 push @operator, "=";
2927 push @value, $record->field($tag)->subfield($subfield);
2928 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2931 # ... and on publisher.
2932 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
2933 if ($record->field($tag)) {
2934 if ($record->field($tag)->subfields($subfield)) {
2935 push @tags, "'".$tag.$subfield."'";
2936 push @and_or, "and";
2937 push @excluding, "";
2938 push @operator, "=";
2939 push @value, $record->field($tag)->subfield($subfield);
2940 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2943 # ... and on volume.
2944 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
2945 if ($record->field($tag)) {
2946 if ($record->field($tag)->subfields($subfield)) {
2947 push @tags, "'".$tag.$subfield."'";
2948 push @and_or, "and";
2949 push @excluding, "";
2950 push @operator, "=";
2951 push @value, $record->field($tag)->subfield($subfield);
2952 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2956 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
2957 # there is at least 1 result => return the 1st one
2959 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2960 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
2962 # no result, returns nothing
2969 if(substr($isbn, 0, 1) <=7) {
2970 $seg1 = substr($isbn, 0, 1);
2971 } elsif(substr($isbn, 0, 2) <= 94) {
2972 $seg1 = substr($isbn, 0, 2);
2973 } elsif(substr($isbn, 0, 3) <= 995) {
2974 $seg1 = substr($isbn, 0, 3);
2975 } elsif(substr($isbn, 0, 4) <= 9989) {
2976 $seg1 = substr($isbn, 0, 4);
2978 $seg1 = substr($isbn, 0, 5);
2980 my $x = substr($isbn, length($seg1));
2982 if(substr($x, 0, 2) <= 19) {
2983 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
2984 $seg2 = substr($x, 0, 2);
2985 } elsif(substr($x, 0, 3) <= 699) {
2986 $seg2 = substr($x, 0, 3);
2987 } elsif(substr($x, 0, 4) <= 8399) {
2988 $seg2 = substr($x, 0, 4);
2989 } elsif(substr($x, 0, 5) <= 89999) {
2990 $seg2 = substr($x, 0, 5);
2991 } elsif(substr($x, 0, 6) <= 9499999) {
2992 $seg2 = substr($x, 0, 6);
2994 $seg2 = substr($x, 0, 7);
2996 my $seg3=substr($x,length($seg2));
2997 $seg3=substr($seg3,0,length($seg3)-1) ;
2998 my $seg4 = substr($x, -1, 1);
2999 return "$seg1-$seg2-$seg3-$seg4";
3003 END { } # module clean-up code here (global destructor)
3009 Koha Developement team <info@koha.org>
3011 Paul POULAIN paul.poulain@free.fr
3017 # Revision 1.144 2006/02/20 14:22:38 kados
3020 # Revision 1.143 2006/02/20 13:26:11 kados
3021 # A new subroutine to handle Z39.50 extended services. You pass it a
3022 # connection object, service type, service options, and a record, and
3023 # it performs the service and handles any exception found.
3025 # Revision 1.142 2006/02/16 20:49:56 kados
3026 # destroy a connection after we're done -- we really should just have one
3027 # connection object and not destroy it until the whole transaction is
3028 # finished -- but this will do for now
3030 # Revision 1.141 2006/02/16 19:47:22 rangi
3031 # Trying to error trap a little more.
3033 # Revision 1.140 2006/02/14 21:36:03 kados
3034 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3035 # also adding diagnostic error if not able to connect to Zebra
3037 # Revision 1.139 2006/02/14 19:53:25 rangi
3038 # Just a little missing my
3040 # Seems to be working great Paul, and I like what you did with zebradb
3042 # Revision 1.138 2006/02/14 11:25:22 tipaul
3043 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3045 # Revision 1.137 2006/02/13 16:34:26 tipaul
3046 # fixing some warnings (perl -w should be quiet)
3048 # Revision 1.136 2006/01/10 17:01:29 tipaul
3049 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3051 # Revision 1.135 2006/01/06 16:39:37 tipaul
3052 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3053 # Seems not to break too many things, but i'm probably wrong here.
3054 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3056 # - removing useless directories (koha-html and koha-plucene)
3058 # Revision 1.134 2006/01/04 15:54:55 tipaul
3059 # utf8 is a : go for beta test in HEAD.
3060 # some explanations :
3061 # - 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.
3062 # - *-top.inc will show the pages in utf8
3063 # - 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.
3064 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3066 # Revision 1.133 2005/12/12 14:25:51 thd
3069 # Reverse array filled with elements from repeated subfields
3070 # to avoid last to first concatenation of elements in Koha DB.-
3072 # Revision 1.132 2005-10-26 09:12:33 tipaul
3073 # big commit, still breaking things...
3075 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3076 # * code cleaning (cleaning warnings from perl -w) continued
3078 # Revision 1.131 2005/09/22 10:01:45 tipaul
3079 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3081 # Revision 1.130 2005/09/02 14:34:14 tipaul
3082 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3083 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3084 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3086 # Revision 1.129 2005/08/12 13:50:31 tipaul
3087 # removing useless sub declarations
3089 # Revision 1.128 2005/08/11 16:12:47 tipaul
3090 # Playing with the zebra...
3092 # * go to koha cvs home directory
3093 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3094 # * put your zebra.cfg files here & create your database.
3095 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3096 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3099 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3100 # * deletion still not work
3101 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3103 # recordId: (bib1,Local-number)
3107 # elm 090 Local-number -
3108 # elm 090/? Local-number -
3109 # elm 090/?/9 Local-number !:w
3111 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3113 # Revision 1.127 2005/08/11 14:37:32 tipaul
3115 # * removing useless subs
3116 # * removing some subs that are also elsewhere
3117 # * 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)
3119 # Revision 1.126 2005/08/11 09:13:28 tipaul
3120 # just removing useless subs (a lot !!!) for code cleaning
3122 # Revision 1.125 2005/08/11 09:00:07 tipaul
3123 # Ok guys, this time, it seems that item add and modif begin working as expected...
3124 # Still a lot of bugs to fix, of course
3126 # Revision 1.124 2005/08/10 10:21:15 tipaul
3127 # continuing the road to zebra :
3128 # - the biblio add begins to work.
3129 # - the biblio modif begins to work.
3131 # (still without doing anything on zebra)
3132 # (no new change in updatedatabase)
3134 # Revision 1.123 2005/08/09 14:10:28 tipaul
3135 # 1st commit to go to zebra.
3136 # don't update your cvs if you want to have a working head...
3138 # this commit contains :
3139 # * 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...
3140 # * 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.
3141 # * other files : get rid of bibid and use biblionumber instead.
3144 # * does not do anything on zebra yet.
3145 # * if you rename marc_subfield_table, you can't search anymore.
3146 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3147 # * 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 ;-) )
3149 # 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
3150 # 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.
3152 # tipaul cutted previous commit notes