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
28 use MARC::File::USMARC;
30 # use Smart::Comments;
33 use vars qw($VERSION @ISA @EXPORT);
35 # set the version for version checking
36 $VERSION = do { my @v = '$Revision$' =~ /\d+/g;
37 shift(@v) . "." . join("_", map {sprintf "%03d", $_ } @v); };
42 # don't forget MARCxxx subs are exported only for testing purposes. Should not be used
43 # as the old-style API and the NEW one are the only public functions.
46 &newbiblio &newbiblioitem
47 &newsubject &newsubtitle &newitems
49 &modbiblio &checkitems &modbibitem
50 &modsubtitle &modsubject &modaddauthor &moditem
52 &delitem &deletebiblioitem &delbiblio
54 &getbiblio &bibdata &bibitems &bibitemdata
55 &barcodes &ItemInfo &itemdata &itemissues &itemcount
56 &getsubject &getaddauthor &getsubtitle
57 &getwebbiblioitems &getwebsites
58 &GetBiblioItemByBiblioNumber
59 &getbibliofromitemnumber
60 &getbiblioitem &getitemsbybiblioitem
62 &MARCfind_marc_from_kohafield
63 &MARCfind_frameworkcode
64 &find_biblioitemnumber
67 &NEWnewbiblio &NEWnewitem
68 &NEWmodbiblio &NEWmoditem
69 &NEWdelbiblio &NEWdelitem
70 &NEWmodbiblioframework
72 &MARCkoha2marcBiblio &MARCmarc2koha
73 &MARCkoha2marcItem &MARChtml2marc &MARChtml2xml
74 &MARCgetbiblio &MARCgetitem
81 &z3950_extended_services
84 &get_item_from_barcode
85 &MARCfind_MARCbibid_from_oldbiblionumber
89 get_biblioiteminfos_of
94 C4::Biblio - Acquisitions, Catalog Management Functions
98 ( lot of changes for Koha 3.X)
100 Koha 1.2 and previous versions used a specific API to manage biblios. This API uses old-DB style parameters.
101 They are based on a hash, and store data in biblio/biblioitems/items tables (plus additionalauthors,
102 bibliosubject and bibliosubtitle where applicable).
104 In Koha 2.X, we introduced a MARC-DB.
106 In Koha 3.X, we removed this MARC-DB for search as we wanted to use Zebra as search system.
108 So in Koha 3.X, saving a record means :
110 - storing the raw marc record (iso2709) in biblioitems.marc field. It contains both biblio & items information.
111 - storing the "decoded information" in biblio/biblioitems/items as previously.
112 - using zebra to manage search & indexing on the MARC data.
114 In Koha, there is a systempreference for "MARC=ON" or "MARC=OFF" :
116 * MARC=ON : when MARC=ON, Koha uses a MARC::Record object (in sub parameters). Saving information in the DB means :
118 - transform the MARC record into a hash
119 - add the raw MARC record into the hash
120 - store them & update Zebra
122 * MARC=OFF : when MARC=OFF, Koha uses a hash object (in sub parameters). Saving information in the DB means :
124 - transform the hash into a MARC record
125 - add the raw marc record into the hash
126 - store them & update zebra
128 That's why we need 3 types of subs :
132 all I<subs beginning by REAL> do the effective storage of information (with a hash, one field of the hash being the raw marc record). Those subs also update the record in Zebra. REAL subs should be only for internal use (called by NEW or "something else" subs).
134 =head2 NEWxxx related subs
138 all I<subs beginning by NEW> use MARC::Record as parameters. It's the API that MUST be used in the MARC acquisition system. They just create the hash, add it the raw marc record. Then, they call REALxxx sub.
140 all subs requires/use $dbh as 1st parameter and a MARC::Record object as 2nd parameter. They sometimes require another parameter.
144 =head2 something_elsexxx related subs
148 all I<subs beginning by seomething else> are the old-style API. They use a hash as parameter, transform the hash into a -small- marc record, and call REAL subs.
150 all subs require/use $dbh as 1st parameter and a hash as 2nd parameter.
156 =head2 z3950_extended_services
158 z3950_extended_services($serviceType,$serviceOptions,$record);
160 z3950_extended_services is used to handle all interactions with Zebra's extended serices package.
162 C<$serviceType> one of: itemorder,create,drop,commit,update,xmlupdate
164 C<$serviceOptions> a has of key/value pairs. For instance, if service_type is 'update', $service_options should contain:
166 action => update action, one of specialUpdate, recordInsert, recordReplace, recordDelete, elementUpdate.
170 recordidOpaque => Opaque Record ID (user supplied) or recordidNumber => Record ID number (system number).
171 syntax => the record syntax (transfer syntax)
172 databaseName = Database from connection object
174 To set serviceOptions, call set_service_options($serviceType)
176 C<$record> the record, if one is needed for the service type
178 A record should be in XML. You can convert it to XML from MARC by running it through marc2xml().
181 sub z3950_extended_services {
182 my ($serviceType,$serviceOptions,$record) = @_;
184 my $Zconn = C4::Context->Zconn;
185 # create a new package object
186 my $Zpackage = $Zconn->package();
189 $Zpackage->option(action => $serviceOptions->{'action'});
191 if ($serviceOptions->{'databaseName'}) {
192 $Zpackage->option(databaseName => $serviceOptions->{'databaseName'});
194 if ($serviceOptions->{'recordIdNumber'}) {
195 $Zpackage->option(recordIdNumber => $serviceOptions->{'recordIdNumber'});
197 if ($serviceOptions->{'recordIdOpaque'}) {
198 $Zpackage->option(recordIdOpaque => $serviceOptions->{'recordIdOpaque'});
201 # this is an ILL request (Zebra doesn't support it)
202 #if ($serviceType eq 'itemorder') {
203 # $Zpackage->option('contact-name' => $serviceOptions->{'contact-name'});
204 # $Zpackage->option('contact-phone' => $serviceOptions->{'contact-phone'});
205 # $Zpackage->option('contact-email' => $serviceOptions->{'contact-email'});
206 # $Zpackage->option('itemorder-item' => $serviceOptions->{'itemorder-item'});
210 my $xmlrecord = marc2xml($record);
211 $Zpackage->option(record => $xmlrecord);
212 if ($serviceOptions->{'syntax'}) {
213 $Zpackage->option(syntax => $serviceOptions->{'syntax'});
217 # send the request, handle any exception encountered
218 eval { $Zpackage->send($serviceType) };
219 if ($@ && $@->isa("ZOOM::Exception")) {
220 print "Oops! ", $@->message(), "\n";
223 # free up package resources
224 $Zpackage->destroy();
227 =head2 set_service_options
229 my $serviceOptions = set_service_options($serviceType);
231 C<$serviceType> itemorder,create,drop,commit,update,xmlupdate
233 Currently, we only support 'create', 'commit', and 'update'. 'drop' support will be added as soon as Zebra supports it.
237 sub set_service_options {
238 my ($serviceType,$action,$recordId) = @_;
241 if ($serviceType eq 'update') {
243 $serviceOptions->{ 'action' } = $action;
245 $serviceOptions->{ 'action' } = 'specialUpdate';
248 $serviceOptions->{'recordIdNumber'} = $recordId;
251 # FIXME: This needs to be an OID ... if we ever need 'syntax' this sub will need to change
252 # $serviceOptions->{ 'syntax' } = ''; #zebra doesn't support syntaxes other than xml
255 if ($serviceType eq 'commit') {
259 if ($serviceType eq 'create') {
262 if ($serviceType eq 'drop') {
263 die "ERROR: 'drop' not currently supported (by Zebra)";
267 return $serviceOptions;
272 my $xmlrecord = marc2xml($record);
274 Convert from MARC to XML. Note that MARC::File::XML will automatically encode from MARC-8 to UTF-8 as of version .8
276 C<$record> a MARC record
283 eval { $xmlrecord=$record->as_xml_record() };
284 #TODO: better error handling here
286 warn "ERROR: I suspect a badly formatted MARC record";
291 =head2 MARCgettagslib
293 @tagslib = &MARCgettagslib($dbh,1|0,$frameworkcode);
297 2nd param is 1 for liblibrarian and 0 for libopac
298 $frameworkcode contains the framework reference. If empty or does not exist, the default one is used
300 returns a hash with all values for all fields and subfields for a given MARC framework :
301 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
303 ->{mandatory} = $mandatory;
304 ->{repeatable} = $repeatable;
305 ->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
307 ->{mandatory} = $mandatory;
308 ->{repeatable} = $repeatable;
309 ->{authorised_value} = $authorised_value;
310 ->{authtypecode} = $authtypecode;
311 ->{value_builder} = $value_builder;
312 ->{kohafield} = $kohafield;
313 ->{seealso} = $seealso;
314 ->{hidden} = $hidden;
323 # old subroutine to provide backwards compatibility.
324 # opac-detail breaks without this. Can be removed once opac-detail is fixed
325 sub MARCfind_MARCbibid_from_oldbiblionumber {
326 my ($biblionumber)=@_;
327 return ($biblionumber);
332 my ( $dbh, $forlibrarian, $frameworkcode ) = @_;
333 $frameworkcode = "" unless $frameworkcode;
334 $forlibrarian = 1 unless $forlibrarian;
336 my $libfield = ( $forlibrarian eq 1 ) ? 'liblibrarian' : 'libopac';
338 # check that framework exists
341 "select count(*) from marc_tag_structure where frameworkcode=?");
342 $sth->execute($frameworkcode);
343 my ($total) = $sth->fetchrow;
344 $frameworkcode = "" unless ( $total > 0 );
347 "select tagfield,liblibrarian,libopac,mandatory,repeatable from marc_tag_structure where frameworkcode=? order by tagfield"
349 $sth->execute($frameworkcode);
350 my ( $liblibrarian, $libopac, $tag, $res, $tab, $mandatory, $repeatable );
352 while ( ( $tag, $liblibrarian, $libopac, $mandatory, $repeatable ) = $sth->fetchrow ) {
353 $res->{$tag}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
354 $res->{$tag}->{tab} = ""; # XXX
355 $res->{$tag}->{mandatory} = $mandatory;
356 $res->{$tag}->{repeatable} = $repeatable;
361 "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"
363 $sth->execute($frameworkcode);
366 my $authorised_value;
376 ( $tag, $subfield, $liblibrarian, , $libopac, $tab,
377 $mandatory, $repeatable, $authorised_value, $authtypecode,
378 $value_builder, $kohafield, $seealso, $hidden,
383 $res->{$tag}->{$subfield}->{lib} = ($forlibrarian or !$libopac)?$liblibrarian:$libopac;
384 $res->{$tag}->{$subfield}->{tab} = $tab;
385 $res->{$tag}->{$subfield}->{mandatory} = $mandatory;
386 $res->{$tag}->{$subfield}->{repeatable} = $repeatable;
387 $res->{$tag}->{$subfield}->{authorised_value} = $authorised_value;
388 $res->{$tag}->{$subfield}->{authtypecode} = $authtypecode;
389 $res->{$tag}->{$subfield}->{value_builder} = $value_builder;
390 $res->{$tag}->{$subfield}->{kohafield} = $kohafield;
391 $res->{$tag}->{$subfield}->{seealso} = $seealso;
392 $res->{$tag}->{$subfield}->{hidden} = $hidden;
393 $res->{$tag}->{$subfield}->{isurl} = $isurl;
394 $res->{$tag}->{$subfield}->{link} = $link;
399 =head2 MARCfind_marc_from_kohafield
401 ($tagfield,$tagsubfield) = &MARCfind_marc_from_kohafield($dbh,$kohafield);
405 finds MARC tag and subfield for a given kohafield
406 kohafield is "table.field" where table= biblio|biblioitems|items, and field a field of the previous table
412 sub MARCfind_marc_from_kohafield {
413 my ( $dbh, $kohafield,$frameworkcode ) = @_;
414 return 0, 0 unless $kohafield;
415 $frameworkcode='' unless $frameworkcode;
416 my $relations = C4::Context->marcfromkohafield;
417 return ($relations->{$frameworkcode}->{$kohafield}->[0],$relations->{$frameworkcode}->{$kohafield}->[1]);
422 $MARCRecord = &MARCgetbiblio($dbh,$biblionumber);
426 Returns a MARC::Record for the biblio $biblionumber.
432 # Returns MARC::Record of the biblio passed in parameter.
433 my ( $dbh, $biblionumber ) = @_;
434 my $sth = $dbh->prepare('select marc from biblioitems where biblionumber=?');
435 $sth->execute($biblionumber);
436 my ($marc) = $sth->fetchrow;
437 my $record = MARC::Record::new_from_usmarc($marc);
443 $XML = &XMLgetbiblio($dbh,$biblionumber);
447 Returns a raw XML for the biblio $biblionumber.
453 # Returns MARC::Record of the biblio passed in parameter.
454 my ( $dbh, $biblionumber ) = @_;
455 my $sth = $dbh->prepare('select marcxml,marc from biblioitems where biblionumber=?');
456 $sth->execute($biblionumber);
457 my ($XML,$marc) = $sth->fetchrow;
458 # my $record =MARC::Record::new_from_usmarc($marc);
459 # warn "MARC : \n*-************************\n".$record->as_xml."\n*-************************\n";
465 $MARCrecord = &MARCgetitem($dbh,$biblionumber);
469 Returns a MARC::Record with all items of biblio # $biblionumber
477 my ( $dbh, $biblionumber, $itemnumber ) = @_;
478 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
479 # get the complete MARC record
480 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
481 $sth->execute($biblionumber);
482 my ($rawmarc) = $sth->fetchrow;
483 my $record = C4::Search::get_record($biblionumber);
484 # warn "ITEMRECORD".$record->as_formatted;
485 # now, find the relevant itemnumber
486 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
487 # prepare the new item record
488 my $itemrecord = MARC::Record->new();
489 # parse all fields fields from the complete record
490 foreach ($record->field($itemnumberfield)) {
491 # when the item field is found, save it
492 # warn "Itenumberfield = $itemnumberfield";
493 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
494 # warn "Inside if subfield=$itemnumbersubfield";
495 $itemrecord->append_fields($_);
497 warn "No match subfield=$itemnumbersubfield and
498 itemnumber=$itemnumber";
501 # warn "ITEMS".$itemrecord->as_formatted;
506 ##Changes only field or subfield from the holdings fields of MARC record used for branch transfers or onloan flag -TG
509 sub MARCmoditemonefield{
510 my ($dbh,$biblionumber,$itemnumber,$itemfield,$newvalue)=@_;
512 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
513 # get the complete MARC record
514 my $sth = $dbh->prepare("select marc from biblioitems where biblionumber=?");
515 $sth->execute($biblionumber);
516 my ($rawmarc) = $sth->fetchrow;
517 my $bibliorecord=MARC::File::USMARC::decode($rawmarc);
518 # now, find the relevant itemnumber
519 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
520 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,$itemfield,$frameworkcode);
522 # parse all fields fields from the complete record
523 foreach ($bibliorecord->field($itemnumberfield)) {
524 # when the item field is found, update it
525 if ($_->subfield($itemnumbersubfield) == $itemnumber) {
526 $_->update($tagsubfield =>$newvalue);
530 # save the record into biblioitem
531 $dbh->do('lock tables biblioitems WRITE');
532 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
533 $sth->execute($bibliorecord->as_usmarc(),$bibliorecord->as_xml_record(),$biblionumber);
534 z3950_extended_services('update',set_service_options('update'),$bibliorecord);
535 z3950_extended_services('commit');
536 $dbh->do('unlock tables');
539 =head2 find_biblioitemnumber
541 my $biblioitemnumber = find_biblioitemnumber($dbh,$biblionumber);
545 Returns the 1st biblioitemnumber related to $biblionumber. When MARC=ON we should have 1 biblionumber = 1 and only 1 biblioitemnumber
546 This sub is useless when MARC=OFF
551 sub find_biblioitemnumber {
552 my ( $dbh, $biblionumber ) = @_;
553 my $sth = $dbh->prepare("select biblioitemnumber from biblioitems where biblionumber=?");
554 $sth->execute($biblionumber);
555 my ($biblioitemnumber) = $sth->fetchrow;
556 return $biblioitemnumber;
559 =head2 MARCfind_frameworkcode
561 my $frameworkcode = MARCfind_frameworkcode($dbh,$biblionumber);
565 returns the framework of a given biblio
571 sub MARCfind_frameworkcode {
572 my ( $dbh, $biblionumber ) = @_;
573 my $sth = $dbh->prepare("select frameworkcode from biblio where biblionumber=?");
574 $sth->execute($biblionumber);
575 my ($frameworkcode) = $sth->fetchrow;
576 return $frameworkcode;
579 =head2 MARCkoha2marcBiblio
581 $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibliohash);
585 MARCkoha2marcBiblio is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB biblio/biblioitem :
586 all entries of the hash are transformed into their matching MARC field/subfield.
592 sub MARCkoha2marcBiblio {
594 # this function builds partial MARC::Record from the old koha-DB fields
595 my ( $dbh, $bibliohash ) = @_;
596 # we don't have biblio entries in the hash, so we add them first
597 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
598 $sth->execute($bibliohash->{biblionumber});
599 my $biblio = $sth->fetchrow_hashref;
600 foreach (keys %$biblio) {
601 $bibliohash->{$_}=$biblio->{$_};
603 $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
604 my $record = MARC::Record->new();
605 foreach ( keys %$bibliohash ) {
606 &MARCkoha2marcOnefield( $sth, $record, "biblio." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
607 &MARCkoha2marcOnefield( $sth, $record, "biblioitems." . $_, $bibliohash->{$_}, '') if $bibliohash->{$_};
610 # other fields => additional authors, subjects, subtitles
611 my $sth2 = $dbh->prepare(" SELECT author FROM additionalauthors WHERE biblionumber=?");
612 $sth2->execute($bibliohash->{biblionumber});
613 while ( my $row = $sth2->fetchrow_hashref ) {
614 &MARCkoha2marcOnefield( $sth, $record, "additionalauthors.author", $bibliohash->{'author'},'' );
616 $sth2 = $dbh->prepare(" SELECT subject FROM bibliosubject WHERE biblionumber=?");
617 $sth2->execute($bibliohash->{biblionumber});
618 while ( my $row = $sth2->fetchrow_hashref ) {
619 &MARCkoha2marcOnefield( $sth, $record, "bibliosubject.subject", $row->{'subject'},'' );
621 $sth2 = $dbh->prepare(" SELECT subtitle FROM bibliosubtitle WHERE biblionumber=?");
622 $sth2->execute($bibliohash->{biblionumber});
623 while ( my $row = $sth2->fetchrow_hashref ) {
624 &MARCkoha2marcOnefield( $sth, $record, "bibliosubtitle.subtitle", $row->{'subtitle'},'' );
630 =head2 MARCkoha2marcItem
632 $MARCRecord = &MARCkoha2marcItem($dbh,$biblionumber,itemnumber);
634 MARCkoha2marcItem is a wrapper between old-DB and MARC-DB. It returns a MARC::Record builded with old-DB items :
635 all entries of the hash are transformed into their matching MARC field/subfield.
643 sub MARCkoha2marcItem {
645 # this function builds partial MARC::Record from the old koha-DB fields
646 my ( $dbh, $item ) = @_;
648 # my $dbh=&C4Connect;
649 my $sth = $dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
650 my $record = MARC::Record->new();
652 foreach( keys %$item ) {
654 &MARCkoha2marcOnefield( $sth, $record, "items." . $_,
661 =head2 MARCkoha2marcOnefield
665 This sub is for internal use only, used by koha2marcBiblio & koha2marcItem
671 sub MARCkoha2marcOnefield {
672 my ( $sth, $record, $kohafieldname, $value,$frameworkcode ) = @_;
675 $sth->execute($frameworkcode,$kohafieldname);
676 if ( ( $tagfield, $tagsubfield ) = $sth->fetchrow ) {
677 if ( $record->field($tagfield) ) {
678 my $tag = $record->field($tagfield);
680 $tag->add_subfields( $tagsubfield, $value );
681 $record->delete_field($tag);
682 $record->add_fields($tag);
686 $record->add_fields( $tagfield, " ", " ", $tagsubfield => $value );
693 $XMLrecord = MARChtml2xml($rtags,$rsubfields,$rvalues,$indicator,$ind_tag);
695 transforms the parameters (coming from HTML form) into a MARC::File::XML
696 object. parameters with r are references to arrays
700 my ($tags,$subfields,$values,$indicator,$ind_tag) = @_;
702 my $xml= MARC::File::XML::header();
707 for (my $i=0;$i<=@$tags;$i++){
708 @$values[$i] =~ s/&/&/g;
709 @$values[$i] =~ s/</</g;
710 @$values[$i] =~ s/>/>/g;
711 @$values[$i] =~ s/"/"/g;
712 @$values[$i] =~ s/'/'/g;
714 if ((@$tags[$i] ne $prevtag)){
715 $j++ unless (@$tags[$i] eq "");
716 #warn "IND:".substr(@$indicator[$j],0,1).substr(@$indicator[$j],1,1)." ".@$tags[$i];
718 $xml.="</datafield>\n";
719 if ((@$tags[$i] > 10) && (@$values[$i] ne "")){
720 my $ind1 = substr(@$indicator[$j],0,1);
721 my $ind2 = substr(@$indicator[$j],1,1);
722 $xml.="<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
723 $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
729 if (@$values[$i] ne "") {
731 if (@$tags[$i] eq "000") {
732 $xml.="<leader>@$values[$i]</leader>\n";
734 # rest of the fixed fields
735 } elsif (@$tags[$i] < 10) {
736 $xml.="<controlfield tag=\"@$tags[$i]\">@$values[$i]</controlfield>\n";
739 my $ind1 = substr(@$indicator[$j],0,1);
740 my $ind2 = substr(@$indicator[$j],1,1);
741 $xml.="<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
742 $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
747 } else { # @$tags[$i] eq $prevtag
748 if (@$values[$i] eq "") {
752 my $ind1 = substr(@$indicator[$j],0,1);
753 my $ind2 = substr(@$indicator[$j],1,1);
754 $xml.="<datafield tag=\"@$tags[$i]\" ind1=\"$ind1\" ind2=\"$ind2\">\n";
757 $xml.="<subfield code=\"@$subfields[$i]\">@$values[$i]</subfield>\n";
760 $prevtag = @$tags[$i];
762 $xml.= MARC::File::XML::footer();
769 $hash = &MARCmarc2koha($dbh,$MARCRecord);
773 builds a hash with old-db datas from a MARC::Record
780 my ($dbh,$record,$frameworkcode) = @_;
781 my $sth=$dbh->prepare("select tagfield,tagsubfield from marc_subfield_structure where frameworkcode=? and kohafield=?");
783 my $sth2=$dbh->prepare("SHOW COLUMNS from biblio");
786 while (($field)=$sth2->fetchrow) {
787 # warn "biblio.".$field;
788 $result=&MARCmarc2kohaOneField($sth,"biblio",$field,$record,$result,$frameworkcode);
790 $sth2=$dbh->prepare("SHOW COLUMNS from biblioitems");
792 while (($field)=$sth2->fetchrow) {
793 if ($field eq 'notes') { $field = 'bnotes'; }
794 # warn "biblioitems".$field;
795 $result=&MARCmarc2kohaOneField($sth,"biblioitems",$field,$record,$result,$frameworkcode);
797 $sth2=$dbh->prepare("SHOW COLUMNS from items");
799 while (($field)=$sth2->fetchrow) {
800 # warn "items".$field;
801 $result=&MARCmarc2kohaOneField($sth,"items",$field,$record,$result,$frameworkcode);
803 # additional authors : specific
804 $result = &MARCmarc2kohaOneField($sth,"bibliosubtitle","subtitle",$record,$result,$frameworkcode);
805 $result = &MARCmarc2kohaOneField($sth,"additionalauthors","additionalauthors",$record,$result,$frameworkcode);
806 # modify copyrightdate to keep only the 1st year found
807 my $temp = $result->{'copyrightdate'};
809 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
811 $result->{'copyrightdate'} = $1;
812 } else { # if no cYYYY, get the 1st date.
813 $temp =~ m/(\d\d\d\d)/;
814 $result->{'copyrightdate'} = $1;
817 # modify publicationyear to keep only the 1st year found
818 $temp = $result->{'publicationyear'};
819 $temp =~ m/c(\d\d\d\d)/; # search cYYYY first
821 $result->{'publicationyear'} = $1;
822 } else { # if no cYYYY, get the 1st date.
823 $temp =~ m/(\d\d\d\d)/;
824 $result->{'publicationyear'} = $1;
829 sub MARCmarc2kohaOneField {
831 # FIXME ? if a field has a repeatable subfield that is used in old-db, only the 1st will be retrieved...
832 my ( $sth, $kohatable, $kohafield, $record, $result,$frameworkcode ) = @_;
833 # warn "kohatable / $kohafield / $result / ";
837 ( $tagfield, $subfield ) = MARCfind_marc_from_kohafield("",$kohatable.".".$kohafield,$frameworkcode);
838 foreach my $field ( $record->field($tagfield) ) {
839 if ($field->tag()<10) {
840 if ($result->{$kohafield}) {
841 # Reverse array filled with elements from repeated subfields
842 # from first to last to avoid last to first concatenation of
843 # elements in Koha DB. -- thd.
844 $result->{$kohafield} .= " | ".reverse($field->data());
846 $result->{$kohafield} = $field->data();
849 if ( $field->subfields ) {
850 my @subfields = $field->subfields();
851 foreach my $subfieldcount ( 0 .. $#subfields ) {
852 if ($subfields[$subfieldcount][0] eq $subfield) {
853 if ( $result->{$kohafield} ) {
854 $result->{$kohafield} .= " | " . $subfields[$subfieldcount][1];
857 $result->{$kohafield} = $subfields[$subfieldcount][1];
864 # warn "OneField for $kohatable.$kohafield and $frameworkcode=> $tagfield, $subfield";
870 ($biblionumber,$biblioitemnumber) = NEWnewbibilio($dbh,$MARCRecord,$frameworkcode);
874 creates a biblio from a MARC::Record.
881 my ( $dbh,$record,$frameworkcode ) = @_;
883 my $biblioitemnumber;
884 my $olddata = MARCmarc2koha( $dbh, $record,$frameworkcode );
885 $olddata->{frameworkcode} = $frameworkcode;
886 $biblionumber = REALnewbiblio( $dbh, $olddata );
887 $olddata->{biblionumber} = $biblionumber;
888 # add biblionumber into the MARC record (it's the ID for zebra)
889 my ( $tagfield, $tagsubfield ) =
890 MARCfind_marc_from_kohafield( $dbh, "biblio.biblionumber",$frameworkcode );
894 $newfield = MARC::Field->new(
895 $tagfield, $biblionumber,
898 $newfield = MARC::Field->new(
899 $tagfield, '', '', "$tagsubfield" => $biblionumber,
902 # drop old field (just in case it already exist and create new one...
903 my $old_field = $record->field($tagfield);
904 $record->delete_field($old_field);
905 $record->add_fields($newfield);
906 #Change MARC Leader to UTF-8 incase user did not set it.New M::F::XML is sensitive to this
907 $record->encoding('UTF-8');
908 #create the marc entry, that stores the rax marc record in Koha 3.0
909 $olddata->{marc} = $record->as_usmarc();
910 $olddata->{marcxml} = $record->as_xml_record();
911 # and create biblioitem, that's all folks !
912 $biblioitemnumber = REALnewbiblioitem( $dbh, $olddata );
914 # search subtiles, addiauthors and subjects
915 ( $tagfield, $tagsubfield ) =
916 MARCfind_marc_from_kohafield( $dbh, "additionalauthors.author",$frameworkcode );
917 my @addiauthfields = $record->field($tagfield);
918 foreach my $addiauthfield (@addiauthfields) {
919 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
920 foreach my $subfieldcount ( 0 .. $#addiauthsubfields ) {
921 REALmodaddauthor( $dbh, $biblionumber,
922 $addiauthsubfields[$subfieldcount] );
925 ( $tagfield, $tagsubfield ) =
926 MARCfind_marc_from_kohafield( $dbh, "bibliosubtitle.subtitle",$frameworkcode );
927 my @subtitlefields = $record->field($tagfield);
928 foreach my $subtitlefield (@subtitlefields) {
929 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
930 foreach my $subfieldcount ( 0 .. $#subtitlesubfields ) {
931 REALnewsubtitle( $dbh, $biblionumber,
932 $subtitlesubfields[$subfieldcount] );
935 ( $tagfield, $tagsubfield ) =
936 MARCfind_marc_from_kohafield( $dbh, "bibliosubject.subject",$frameworkcode );
937 my @subj = $record->field($tagfield);
939 foreach my $subject (@subj) {
940 my @subjsubfield = $subject->subfield($tagsubfield);
941 foreach my $subfieldcount ( 0 .. $#subjsubfield ) {
942 push @subjects, $subjsubfield[$subfieldcount];
945 REALmodsubject( $dbh, $biblionumber, 1, @subjects );
946 return ( $biblionumber, $biblioitemnumber );
949 =head2 NEWmodbilbioframework
951 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
955 modify the framework of a biblio
961 sub NEWmodbiblioframework {
962 my ($dbh,$biblionumber,$frameworkcode) =@_;
963 my $sth = $dbh->prepare("Update biblio SET frameworkcode=? WHERE biblionumber=?");
964 $sth->execute($frameworkcode,$biblionumber);
970 NEWmodbiblio($dbh,$MARCrecord,$biblionumber,$frameworkcode);
974 modify a biblio (MARC=ON)
981 my ($dbh,$record,$biblionumber,$frameworkcode) =@_;
982 $frameworkcode="" unless $frameworkcode;
983 # &MARCmodbiblio($dbh,$bibid,$record,$frameworkcode,0);
984 my $oldbiblio = MARCmarc2koha($dbh,$record,$frameworkcode);
986 $oldbiblio->{frameworkcode} = $frameworkcode;
987 #create the marc entry, that stores the rax marc record in Koha 3.0
988 $oldbiblio->{biblionumber} = $biblionumber unless $oldbiblio->{biblionumber};
989 $oldbiblio->{marc} = $record->as_usmarc();
990 $oldbiblio->{marcxml} = $record->as_xml_record();
991 warn "dans NEWmodbiblio $biblionumber = ".$oldbiblio->{biblionumber}." = ".$oldbiblio->{marcxml};
992 REALmodbiblio($dbh,$oldbiblio);
993 REALmodbiblioitem($dbh,$oldbiblio);
994 # now, modify addi authors, subject, addititles.
995 my ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"additionalauthors.author",$frameworkcode);
996 my @addiauthfields = $record->field($tagfield);
997 foreach my $addiauthfield (@addiauthfields) {
998 my @addiauthsubfields = $addiauthfield->subfield($tagsubfield);
999 $dbh->do("delete from additionalauthors where biblionumber=$biblionumber");
1000 foreach my $subfieldcount (0..$#addiauthsubfields) {
1001 REALmodaddauthor($dbh,$biblionumber,$addiauthsubfields[$subfieldcount]);
1004 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle",$frameworkcode);
1005 my @subtitlefields = $record->field($tagfield);
1006 foreach my $subtitlefield (@subtitlefields) {
1007 my @subtitlesubfields = $subtitlefield->subfield($tagsubfield);
1008 # delete & create subtitle again because REALmodsubtitle can't handle new subtitles
1010 $dbh->do("delete from bibliosubtitle where biblionumber=$biblionumber");
1011 foreach my $subfieldcount (0..$#subtitlesubfields) {
1012 foreach my $subtit(split /\||#/,$subtitlesubfields[$subfieldcount]) {
1013 REALnewsubtitle($dbh,$biblionumber,$subtit);
1017 ($tagfield,$tagsubfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubject.subject",$frameworkcode);
1018 my @subj = $record->field($tagfield);
1020 foreach my $subject (@subj) {
1021 my @subjsubfield = $subject->subfield($tagsubfield);
1022 foreach my $subfieldcount (0..$#subjsubfield) {
1023 push @subjects,$subjsubfield[$subfieldcount];
1026 REALmodsubject($dbh,$biblionumber,1,@subjects);
1030 =head2 NEWmodbilbioframework
1032 NEWmodbilbioframework($dbh,$biblionumber,$frameworkcode);
1043 my ( $dbh, $bibid ) = @_;
1044 # my $biblio = &MARCfind_oldbiblionumber_from_MARCbibid( $dbh, $bibid );
1045 &REALdelbiblio( $dbh, $bibid );
1048 "select biblioitemnumber from biblioitems where biblionumber=?");
1049 $sth->execute($bibid);
1050 while ( my ($biblioitemnumber) = $sth->fetchrow ) {
1051 REALdelbiblioitem( $dbh, $biblioitemnumber );
1053 # &MARCdelbiblio( $dbh, $bibid, 0 );
1055 warn "heres the bibid $bibid";
1056 # my $record = C4::Search::get_record($bibid);
1057 my $record = C4::Search::get_xml_record($bibid);
1058 # z3950_extended_services('update',set_service_options('update'),$record);
1059 warn "heres the record to delete $bibid";
1060 my $Zconn = C4::Context->Zconn;
1061 my $p = $Zconn->package();
1062 $p->option(action => "recordDelete");
1063 $p->option(record => $record);
1066 # z3950_extended_services('update',set_service_options('update','recordDelete',$record));
1067 z3950_extended_services('commit');
1072 $itemnumber = NEWnewitem($dbh, $record, $biblionumber, $biblioitemnumber);
1076 creates an item from a MARC::Record
1083 my ( $dbh,$record,$biblionumber,$biblioitemnumber ) = @_;
1084 warn "here is the $biblioitemnumber";
1085 # add item in old-DB
1086 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1087 my $item = &MARCmarc2koha( $dbh,$record,$frameworkcode );
1088 # needs old biblionumber and biblioitemnumber
1089 $item->{'biblionumber'} = $biblionumber;
1090 $item->{'biblioitemnumber'}=$biblioitemnumber;
1091 $item->{marc} = $record->as_usmarc();
1092 #warn $item->{marc};
1093 my ( $itemnumber, $error ) = &REALnewitems( $dbh, $item, $item->{barcode} );
1100 $itemnumber = NEWmoditem($dbh, $record, $biblionumber, $biblioitemnumber,$itemnumber);
1111 my ( $dbh, $record, $biblionumber, $biblioitemnumber, $itemnumber) = @_;
1113 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblionumber);
1114 my $olditem = MARCmarc2koha( $dbh, $record,$frameworkcode );
1116 $olditem->{marc} = $record->as_usmarc();
1117 $olditem->{biblionumber} = $biblionumber;
1118 $olditem->{biblioitemnumber} = $biblioitemnumber;
1120 REALmoditem( $dbh, $olditem );
1126 $itemnumber = NEWdelitem($dbh, $biblionumber, $biblioitemnumber, $itemnumber);
1137 my ( $dbh, $bibid, $itemnumber ) = @_;
1138 &REALdelitem( $dbh, $itemnumber );
1139 # &MARCdelitem( $dbh, $bibid, $itemnumber );
1140 # we must now delete the item data from zebra
1144 =head2 REALnewbiblio
1146 $biblionumber = REALnewbiblio($dbh,$biblio);
1150 adds a record in biblio table. Datas are in the hash $biblio.
1157 my ( $dbh, $biblio ) = @_;
1159 $dbh->do('lock tables biblio WRITE');
1160 my $sth = $dbh->prepare("Select max(biblionumber) from biblio");
1162 my $data = $sth->fetchrow_arrayref;
1163 my $bibnum = $$data[0] + 1;
1166 if ( $biblio->{'seriestitle'} ) { $series = 1 }
1169 $dbh->prepare("insert into biblio set biblionumber=?, title=?, author=?, copyrightdate=?,
1170 serial=?, seriestitle=?, notes=?, abstract=?,
1174 $bibnum, $biblio->{'title'},
1175 $biblio->{'author'}, $biblio->{'copyrightdate'},
1176 $biblio->{'serial'}, $biblio->{'seriestitle'},
1177 $biblio->{'notes'}, $biblio->{'abstract'},
1178 $biblio->{'unititle'}
1182 $dbh->do('unlock tables');
1186 =head2 REALmodbiblio
1188 $biblionumber = REALmodbiblio($dbh,$biblio);
1192 modify a record in biblio table. Datas are in the hash $biblio.
1199 my ( $dbh, $biblio ) = @_;
1200 my $sth = $dbh->prepare("Update biblio set title=?, author=?, abstract=?, copyrightdate=?,
1201 seriestitle=?, serial=?, unititle=?, notes=?, frameworkcode=?
1202 where biblionumber = ?"
1205 $biblio->{'title'}, $biblio->{'author'},
1206 $biblio->{'abstract'}, $biblio->{'copyrightdate'},
1207 $biblio->{'seriestitle'}, $biblio->{'serial'},
1208 $biblio->{'unititle'}, $biblio->{'notes'},
1209 $biblio->{frameworkcode},
1210 $biblio->{'biblionumber'}
1213 return ( $biblio->{'biblionumber'} );
1216 =head2 REALmodsubtitle
1218 REALmodsubtitle($dbh,$bibnum,$subtitle);
1222 modify subtitles in bibliosubtitle table.
1228 sub REALmodsubtitle {
1229 my ( $dbh, $bibnum, $subtitle ) = @_;
1232 "update bibliosubtitle set subtitle = ? where biblionumber = ?");
1233 $sth->execute( $subtitle, $bibnum );
1237 =head2 REALmodaddauthor
1239 REALmodaddauthor($dbh,$bibnum,$author);
1243 adds or modify additional authors
1244 NOTE : Strange sub : seems to delete MANY and add only ONE author... maybe buggy ?
1250 sub REALmodaddauthor {
1251 my ( $dbh, $bibnum, @authors ) = @_;
1253 # my $dbh = C4Connect;
1255 $dbh->prepare("Delete from additionalauthors where biblionumber = ?");
1257 $sth->execute($bibnum);
1259 foreach my $author (@authors) {
1260 if ( $author ne '' ) {
1263 "Insert into additionalauthors set author = ?, biblionumber = ?"
1266 $sth->execute( $author, $bibnum );
1271 } # sub modaddauthor
1273 =head2 REALmodsubject
1275 $errors = REALmodsubject($dbh,$bibnum, $force, @subject);
1279 modify/adds subjects
1284 sub REALmodsubject {
1285 my ( $dbh, $bibnum, $force, @subject ) = @_;
1287 # my $dbh = C4Connect;
1288 my $count = @subject;
1290 for ( my $i = 0 ; $i < $count ; $i++ ) {
1291 $subject[$i] =~ s/^ //g;
1292 $subject[$i] =~ s/ $//g;
1295 "select * from catalogueentry where entrytype = 's' and catalogueentry = ?"
1297 $sth->execute( $subject[$i] );
1299 if ( my $data = $sth->fetchrow_hashref ) {
1302 if ( $force eq $subject[$i] || $force == 1 ) {
1304 # subject not in aut, chosen to force anway
1305 # so insert into cataloguentry so its in auth file
1308 "Insert into catalogueentry (entrytype,catalogueentry) values ('s',?)"
1311 $sth2->execute( $subject[$i] ) if ( $subject[$i] );
1316 "$subject[$i]\n does not exist in the subject authority file";
1319 "Select * from catalogueentry where entrytype = 's' and (catalogueentry like ? or catalogueentry like ? or catalogueentry like ?)"
1321 $sth2->execute( "$subject[$i] %", "% $subject[$i] %",
1323 while ( my $data = $sth2->fetchrow_hashref ) {
1324 $error .= "<br>$data->{'catalogueentry'}";
1333 $dbh->prepare("Delete from bibliosubject where biblionumber = ?");
1334 $sth->execute($bibnum);
1338 "Insert into bibliosubject (subject,biblionumber) values (?,?)");
1340 foreach $query (@subject) {
1341 $sth->execute( $query, $bibnum ) if ( $query && $bibnum );
1350 =head2 REALmodbiblioitem
1352 REALmodbiblioitem($dbh, $biblioitem);
1361 sub REALmodbiblioitem {
1362 my ( $dbh, $biblioitem ) = @_;
1365 my $sth = $dbh->prepare("update biblioitems set number=?,volume=?, volumedate=?, lccn=?,
1366 itemtype=?, url=?, isbn=?, issn=?,
1367 publishercode=?, publicationyear=?, classification=?, dewey=?,
1368 subclass=?, illus=?, pages=?, volumeddesc=?,
1369 notes=?, size=?, place=?, marc=?,
1371 where biblioitemnumber=?");
1372 $sth->execute( $biblioitem->{number}, $biblioitem->{volume}, $biblioitem->{volumedate}, $biblioitem->{lccn},
1373 $biblioitem->{itemtype}, $biblioitem->{url}, $biblioitem->{isbn}, $biblioitem->{issn},
1374 $biblioitem->{publishercode}, $biblioitem->{publicationyear}, $biblioitem->{classification}, $biblioitem->{dewey},
1375 $biblioitem->{subclass}, $biblioitem->{illus}, $biblioitem->{pages}, $biblioitem->{volumeddesc},
1376 $biblioitem->{bnotes}, $biblioitem->{size}, $biblioitem->{place}, $biblioitem->{marc},
1377 $biblioitem->{marcxml}, $biblioitem->{biblioitemnumber});
1379 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1381 z3950_extended_services('update',set_service_options('update'),$record);
1382 z3950_extended_services('commit');
1385 # warn "MOD : $biblioitem->{biblioitemnumber} = ".$biblioitem->{marc};
1388 =head2 REALnewbiblioitem
1390 REALnewbiblioitem($dbh,$biblioitem);
1394 adds a biblioitem ($biblioitem is a hash with the values)
1400 sub REALnewbiblioitem {
1401 my ( $dbh, $biblioitem ) = @_;
1403 $dbh->do("lock tables biblioitems WRITE, biblio WRITE, marc_subfield_structure READ");
1404 my $sth = $dbh->prepare("Select max(biblioitemnumber) from biblioitems");
1406 my $biblioitemnumber;
1409 $data = $sth->fetchrow_arrayref;
1410 $biblioitemnumber = $$data[0] + 1;
1412 # Insert biblioitemnumber in MARC record, we need it to manage items later...
1413 my $frameworkcode=MARCfind_frameworkcode($dbh,$biblioitem->{biblionumber});
1414 my ($biblioitemnumberfield,$biblioitemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'biblioitems.biblioitemnumber',$frameworkcode);
1415 my $record = MARC::File::USMARC::decode($biblioitem->{marc});
1416 my $field=$record->field($biblioitemnumberfield);
1417 $field->update($biblioitemnumbersubfield => "$biblioitemnumber");
1418 $biblioitem->{marc} = $record->as_usmarc();
1419 $biblioitem->{marcxml} = $record->as_xml_record();
1421 $sth = $dbh->prepare( "insert into biblioitems set
1422 biblioitemnumber = ?, biblionumber = ?,
1423 volume = ?, number = ?,
1424 classification = ?, itemtype = ?,
1426 issn = ?, dewey = ?,
1427 subclass = ?, publicationyear = ?,
1428 publishercode = ?, volumedate = ?,
1429 volumeddesc = ?, illus = ?,
1430 pages = ?, notes = ?,
1432 marc = ?, place = ?,
1436 $biblioitemnumber, $biblioitem->{'biblionumber'},
1437 $biblioitem->{'volume'}, $biblioitem->{'number'},
1438 $biblioitem->{'classification'}, $biblioitem->{'itemtype'},
1439 $biblioitem->{'url'}, $biblioitem->{'isbn'},
1440 $biblioitem->{'issn'}, $biblioitem->{'dewey'},
1441 $biblioitem->{'subclass'}, $biblioitem->{'publicationyear'},
1442 $biblioitem->{'publishercode'}, $biblioitem->{'volumedate'},
1443 $biblioitem->{'volumeddesc'}, $biblioitem->{'illus'},
1444 $biblioitem->{'pages'}, $biblioitem->{'bnotes'},
1445 $biblioitem->{'size'}, $biblioitem->{'lccn'},
1446 $biblioitem->{'marc'}, $biblioitem->{'place'},
1447 $biblioitem->{marcxml},
1449 $dbh->do("unlock tables");
1450 z3950_extended_services('update',set_service_options('update'),$record);
1451 z3950_extended_services('commit');
1452 return ($biblioitemnumber);
1455 =head2 REALnewsubtitle
1457 REALnewsubtitle($dbh,$bibnum,$subtitle);
1461 create a new subtitle
1466 sub REALnewsubtitle {
1467 my ( $dbh, $bibnum, $subtitle ) = @_;
1470 "insert into bibliosubtitle set biblionumber = ?, subtitle = ?");
1471 $sth->execute( $bibnum, $subtitle ) if $subtitle;
1477 ($itemnumber,$errors)= REALnewitems($dbh,$item,$barcode);
1481 create a item. $item is a hash and $barcode the barcode.
1488 my ( $dbh, $item, $barcode ) = @_;
1490 # warn "OLDNEWITEMS";
1492 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE,marc_subfield_structure WRITE');
1493 my $sth = $dbh->prepare("Select max(itemnumber) from items");
1498 $data = $sth->fetchrow_hashref;
1499 $itemnumber = $data->{'max(itemnumber)'} + 1;
1501 # FIXME the "notforloan" field seems to be named "loan" in some places. workaround bugfix.
1502 if ( $item->{'loan'} ) {
1503 $item->{'notforloan'} = $item->{'loan'};
1505 # $item->{'biblioitemnumber'} = 1;
1506 # if dateaccessioned is provided, use it. Otherwise, set to NOW()
1507 if ( $item->{'dateaccessioned'} ) {
1508 $sth = $dbh->prepare( "Insert into items set
1509 itemnumber = ?, biblionumber = ?,
1510 multivolumepart = ?,
1511 biblioitemnumber = ?, barcode = ?,
1512 booksellerid = ?, dateaccessioned = ?,
1513 homebranch = ?, holdingbranch = ?,
1514 price = ?, replacementprice = ?,
1515 replacementpricedate = NOW(), datelastseen = NOW(),
1516 multivolume = ?, stack = ?,
1517 itemlost = ?, wthdrawn = ?,
1518 paidfor = ?, itemnotes = ?,
1519 itemcallnumber =?, notforloan = ?,
1524 $itemnumber, $item->{'biblionumber'},
1525 $item->{'multivolumepart'},
1526 $item->{'biblioitemnumber'},$item->{barcode},
1527 $item->{'booksellerid'}, $item->{'dateaccessioned'},
1528 $item->{'homebranch'}, $item->{'holdingbranch'},
1529 $item->{'price'}, $item->{'replacementprice'},
1530 $item->{multivolume}, $item->{stack},
1531 $item->{itemlost}, $item->{wthdrawn},
1532 $item->{paidfor}, $item->{'itemnotes'},
1533 $item->{'itemcallnumber'}, $item->{'notforloan'},
1536 if ( defined $sth->errstr ) {
1537 $error .= $sth->errstr;
1541 $sth = $dbh->prepare( "Insert into items set
1542 itemnumber = ?, biblionumber = ?,
1543 multivolumepart = ?,
1544 biblioitemnumber = ?, barcode = ?,
1545 booksellerid = ?, dateaccessioned = NOW(),
1546 homebranch = ?, holdingbranch = ?,
1547 price = ?, replacementprice = ?,
1548 replacementpricedate = NOW(), datelastseen = NOW(),
1549 multivolume = ?, stack = ?,
1550 itemlost = ?, wthdrawn = ?,
1551 paidfor = ?, itemnotes = ?,
1552 itemcallnumber =?, notforloan = ?,
1557 $itemnumber, $item->{'biblionumber'},
1558 $item->{'multivolumepart'},
1559 $item->{'biblioitemnumber'},$item->{barcode},
1560 $item->{'booksellerid'},
1561 $item->{'homebranch'}, $item->{'holdingbranch'},
1562 $item->{'price'}, $item->{'replacementprice'},
1563 $item->{multivolume}, $item->{stack},
1564 $item->{itemlost}, $item->{wthdrawn},
1565 $item->{paidfor}, $item->{'itemnotes'},
1566 $item->{'itemcallnumber'}, $item->{'notforloan'},
1569 if ( defined $sth->errstr ) {
1570 $error .= $sth->errstr;
1573 # item stored, now, deal with the marc part...
1574 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1575 where biblio.biblionumber=biblioitems.biblionumber and
1576 biblio.biblionumber=?");
1577 $sth->execute($item->{biblionumber});
1578 if ( defined $sth->errstr ) {
1579 $error .= $sth->errstr;
1581 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1582 warn "ERROR IN REALnewitem, MARC record not found FOR $item->{biblionumber} => $rawmarc <=" unless $rawmarc;
1583 my $record = MARC::File::USMARC::decode($rawmarc);
1584 # ok, we have the marc record, add item number to the item field (in {marc}, and add the field to the record)
1585 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1586 my $itemrecord = MARC::Record->new_from_usmarc($item->{marc});
1588 #warn $itemnumberfield;
1589 #warn $itemrecord->field($itemnumberfield);
1590 my $itemfield = $itemrecord->field($itemnumberfield);
1591 $itemfield->add_subfields($itemnumbersubfield => "$itemnumber");
1592 $record->insert_grouped_field($itemfield);
1593 # save the record into biblioitem
1594 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=?");
1595 $sth->execute($record->as_usmarc(),$record->as_xml_record(),$item->{biblionumber});
1596 if ( defined $sth->errstr ) {
1597 $error .= $sth->errstr;
1599 z3950_extended_services('update',set_service_options('update'),$record);
1600 z3950_extended_services('commit');
1601 $dbh->do('unlock tables');
1602 return ( $itemnumber, $error );
1605 =head2 REALmoditem($dbh,$item);
1616 my ( $dbh, $item ) = @_;
1617 $item->{'bibitemnum'} = 1;
1619 $dbh->do('lock tables items WRITE, biblio WRITE,biblioitems WRITE');
1620 $item->{'itemnum'} = $item->{'itemnumber'} unless $item->{'itemnum'};
1621 my $query = "update items set barcode=?,itemnotes=?,itemcallnumber=?,notforloan=?,location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1623 $item->{'barcode'}, $item->{'itemnotes'},
1624 $item->{'itemcallnumber'}, $item->{'notforloan'},
1625 $item->{'location'}, $item->{multivolumepart},
1626 $item->{multivolume}, $item->{stack},
1629 if ( $item->{'lost'} ne '' ) {
1630 $query = "update items set biblioitemnumber=?,barcode=?,itemnotes=?,homebranch=?,
1631 itemlost=?,wthdrawn=?,itemcallnumber=?,notforloan=?,
1632 location=?,multivolumepart=?,multivolume=?,stack=?,wthdrawn=?";
1634 $item->{'bibitemnum'}, $item->{'barcode'},
1635 $item->{'itemnotes'}, $item->{'homebranch'},
1636 $item->{'lost'}, $item->{'wthdrawn'},
1637 $item->{'itemcallnumber'}, $item->{'notforloan'},
1638 $item->{'location'}, $item->{multivolumepart},
1639 $item->{multivolume}, $item->{stack},
1642 if ($item->{homebranch}) {
1643 $query.=",homebranch=?";
1644 push @bind, $item->{homebranch};
1646 if ($item->{holdingbranch}) {
1647 $query.=",holdingbranch=?";
1648 push @bind, $item->{holdingbranch};
1651 $query.=" where itemnumber=?";
1652 push @bind,$item->{'itemnum'};
1653 if ( $item->{'replacement'} ne '' ) {
1654 $query =~ s/ where/,replacementprice='$item->{'replacement'}' where/;
1656 my $sth = $dbh->prepare($query);
1657 $sth->execute(@bind);
1659 # item stored, now, deal with the marc part...
1660 $sth = $dbh->prepare("select biblioitems.marc,biblio.frameworkcode from biblioitems,biblio
1661 where biblio.biblionumber=biblioitems.biblionumber and
1662 biblio.biblionumber=? and
1663 biblioitems.biblioitemnumber=?");
1664 $sth->execute($item->{biblionumber},$item->{biblioitemnumber});
1665 if ( defined $sth->errstr ) {
1666 $error .= $sth->errstr;
1668 my ($rawmarc,$frameworkcode) = $sth->fetchrow;
1669 # warn "ERROR IN REALmoditem, MARC record not found" unless $rawmarc;
1670 # my $record = MARC::File::USMARC::decode($rawmarc);
1671 my $record=C4::Search::get_record($item->{biblionumber});
1673 # ok, we have the marc record, find the previous item record for this itemnumber and delete it
1674 my ($itemnumberfield,$itemnumbersubfield) = MARCfind_marc_from_kohafield($dbh,'items.itemnumber',$frameworkcode);
1675 # prepare the new item record
1676 my $itemrecord = MARC::File::USMARC::decode($item->{marc});
1677 my $itemfield = $itemrecord->field($itemnumberfield);
1679 # $itemfield->add_subfields($itemnumbersubfield => '$itemnumber');
1680 # parse all fields fields from the complete record
1681 foreach ($record->field($itemnumberfield)) {
1682 # when the previous field is found, replace by the new one
1683 if ($_->subfield($itemnumbersubfield) == $item->{itemnum}) {
1684 $_->replace_with($itemfield);
1687 my $temptest = $_->subfield($itemnumbersubfield);
1688 warn " failed itemnum is $item->{itemnum} and value in record is $temptest";
1691 # $record->insert_grouped_field($itemfield);
1692 # save the record into biblioitem
1693 $sth=$dbh->prepare("update biblioitems set marc=?,marcxml=? where biblionumber=? and biblioitemnumber=?");
1694 $sth->execute($record->as_usmarc(),$record->as_xml_record(),$item->{biblionumber},$item->{biblioitemnumber});
1695 z3950_extended_services('update',set_service_options('update'),$record);
1696 z3950_extended_services('commit');
1697 if ( defined $sth->errstr ) {
1698 $error .= $sth->errstr;
1700 $dbh->do('unlock tables');
1704 =head2 REALdelitem($dbh,$itemnum);
1715 my ( $dbh, $itemnum ) = @_;
1717 # my $dbh=C4Connect;
1718 my $sth = $dbh->prepare("select * from items where itemnumber=?");
1719 $sth->execute($itemnum);
1720 my $data = $sth->fetchrow_hashref;
1722 my $query = "Insert into deleteditems set ";
1724 foreach my $temp ( keys %$data ) {
1725 $query .= "$temp = ?,";
1726 push ( @bind, $data->{$temp} );
1731 $sth = $dbh->prepare($query);
1732 $sth->execute(@bind);
1734 $sth = $dbh->prepare("Delete from items where itemnumber=?");
1735 $sth->execute($itemnum);
1741 =head2 REALdelbiblioitem($dbh,$biblioitemnumber);
1745 deletes a biblioitem
1746 NOTE : not standard sub name. Should be REALdelbiblioitem()
1752 sub REALdelbiblioitem {
1753 my ( $dbh, $biblioitemnumber ) = @_;
1755 # my $dbh = C4Connect;
1756 my $sth = $dbh->prepare( "Select * from biblioitems
1757 where biblioitemnumber = ?"
1761 $sth->execute($biblioitemnumber);
1763 if ( $results = $sth->fetchrow_hashref ) {
1767 "Insert into deletedbiblioitems (biblioitemnumber, biblionumber, volume, number, classification, itemtype,
1768 isbn, issn ,dewey ,subclass ,publicationyear ,publishercode ,volumedate ,volumeddesc ,timestamp ,illus ,
1769 pages ,notes ,size ,url ,lccn ) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"
1773 $results->{biblioitemnumber}, $results->{biblionumber},
1774 $results->{volume}, $results->{number},
1775 $results->{classification}, $results->{itemtype},
1776 $results->{isbn}, $results->{issn},
1777 $results->{dewey}, $results->{subclass},
1778 $results->{publicationyear}, $results->{publishercode},
1779 $results->{volumedate}, $results->{volumeddesc},
1780 $results->{timestamp}, $results->{illus},
1781 $results->{pages}, $results->{notes},
1782 $results->{size}, $results->{url},
1786 $dbh->prepare("Delete from biblioitems where biblioitemnumber = ?");
1787 $sth2->execute($biblioitemnumber);
1792 # Now delete all the items attached to the biblioitem
1793 $sth = $dbh->prepare("Select * from items where biblioitemnumber = ?");
1794 $sth->execute($biblioitemnumber);
1796 while ( my $data = $sth->fetchrow_hashref ) {
1797 my $query = "Insert into deleteditems set ";
1799 foreach my $temp ( keys %$data ) {
1800 next if ($temp =~/itemcallnumber/);
1801 $query .= "$temp = ?,";
1802 push ( @bind, $data->{$temp} );
1805 my $sth2 = $dbh->prepare($query);
1806 $sth2->execute(@bind);
1809 $sth = $dbh->prepare("Delete from items where biblioitemnumber = ?");
1810 $sth->execute($biblioitemnumber);
1814 } # sub deletebiblioitem
1816 =head2 REALdelbiblio($dbh,$biblio);
1827 my ( $dbh, $biblio ) = @_;
1828 my $sth = $dbh->prepare("select * from biblio where biblionumber=?");
1829 $sth->execute($biblio);
1830 if ( my $data = $sth->fetchrow_hashref ) {
1832 my $query = "Insert into deletedbiblio set ";
1834 foreach my $temp ( keys %$data ) {
1835 $query .= "$temp = ?,";
1836 push ( @bind, $data->{$temp} );
1839 #replacing the last , by ",?)"
1841 $sth = $dbh->prepare($query);
1842 $sth->execute(@bind);
1844 $sth = $dbh->prepare("Delete from biblio where biblionumber=?");
1845 $sth->execute($biblio);
1853 $number = itemcount($biblio);
1857 returns the number of items attached to a biblio
1865 my $dbh = C4::Context->dbh;
1868 my $sth = $dbh->prepare("Select count(*) from items where biblionumber=?");
1869 $sth->execute($biblio);
1870 my $data = $sth->fetchrow_hashref;
1872 return ( $data->{'count(*)'} );
1877 $biblionumber = newbiblio($biblio);
1881 create a biblio. The parameter is a hash
1889 my $dbh = C4::Context->dbh;
1890 my $bibnum = REALnewbiblio( $dbh, $biblio );
1891 # finds new (MARC bibid
1892 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1893 # my $record = &MARCkoha2marcBiblio( $dbh, $bibnum );
1894 # MARCaddbiblio( $dbh, $record, $bibnum,'' );
1900 $biblionumber = &modbiblio($biblio);
1904 Update a biblio record.
1906 C<$biblio> is a reference-to-hash whose keys are the fields in the
1907 biblio table in the Koha database. All fields must be present, not
1908 just the ones you wish to change.
1910 C<&modbiblio> updates the record defined by
1911 C<$biblio-E<gt>{biblionumber}> with the values in C<$biblio>.
1913 C<&modbiblio> returns C<$biblio-E<gt>{biblionumber}> whether it was
1922 my $dbh = C4::Context->dbh;
1923 my $biblionumber=REALmodbiblio($dbh,$biblio);
1924 my $record = MARCkoha2marcBiblio($dbh,$biblionumber,$biblionumber);
1925 # finds new (MARC bibid
1926 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$biblionumber);
1927 MARCmodbiblio($dbh,$bibid,$record,"",0);
1928 return($biblionumber);
1931 =head2 &modsubtitle($biblionumber, $subtitle);
1935 Sets the subtitle of a book.
1937 C<$biblionumber> is the biblionumber of the book to modify.
1939 C<$subtitle> is the new subtitle.
1946 my ( $bibnum, $subtitle ) = @_;
1947 my $dbh = C4::Context->dbh;
1948 &REALmodsubtitle( $dbh, $bibnum, $subtitle );
1951 =head2 &modaddauthor($biblionumber, $author);
1955 Replaces all additional authors for the book with biblio number
1956 C<$biblionumber> with C<$author>. If C<$author> is the empty string,
1957 C<&modaddauthor> deletes all additional authors.
1964 my ( $bibnum, @authors ) = @_;
1965 my $dbh = C4::Context->dbh;
1966 &REALmodaddauthor( $dbh, $bibnum, @authors );
1967 } # sub modaddauthor
1971 $error = &modsubject($biblionumber, $force, @subjects);
1975 $force - a subject to force
1976 $error - Error message, or undef if successful.
1983 my ( $bibnum, $force, @subject ) = @_;
1984 my $dbh = C4::Context->dbh;
1985 my $error = &REALmodsubject( $dbh, $bibnum, $force, @subject );
1987 # When MARC is off, ensures that the MARC biblio table gets updated with new
1988 # subjects, of course, it deletes the biblio in marc, and then recreates.
1989 # This check is to ensure that no MARC data exists to lose.
1990 # if (C4::Context->preference("MARC") eq '0'){
1991 # warn "in modSUBJECT";
1992 # my $MARCRecord = &MARCkoha2marcBiblio($dbh,$bibnum);
1993 # my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber($dbh,$bibnum);
1994 # &MARCmodbiblio($dbh,$bibid, $MARCRecord);
2000 =head2 modbibitem($dbh, $biblioitem);
2004 modify a biblioitem. The parameter is a hash
2011 my ($dbh, $biblioitem) = @_;
2012 #my $dbh = C4::Context->dbh;
2013 &REALmodbiblioitem( $dbh, $biblioitem );
2016 =head2 newbiblioitem
2018 $biblioitemnumber = newbiblioitem($biblioitem)
2022 create a biblioitem, the parameter is a hash
2029 my ($biblioitem) = @_;
2030 my $dbh = C4::Context->dbh;
2031 # add biblio information to the hash
2032 my $MARCbiblio = MARCkoha2marcBiblio( $dbh, $biblioitem );
2033 $biblioitem->{marc} = $MARCbiblio->as_usmarc();
2034 my $bibitemnum = &REALnewbiblioitem( $dbh, $biblioitem );
2035 return ($bibitemnum);
2038 =head2 newsubtitle($biblionumber,$subtitle);
2042 insert a subtitle for $biblionumber biblio
2050 my ( $bibnum, $subtitle ) = @_;
2051 my $dbh = C4::Context->dbh;
2052 &REALnewsubtitle( $dbh, $bibnum, $subtitle );
2057 $errors = newitems($dbh, $item, @barcodes);
2061 insert items ($item is a hash)
2069 my ( $dbh, $item, @barcodes ) = @_;
2070 #my $dbh = C4::Context->dbh;
2074 foreach my $barcode (@barcodes) {
2075 # add items, one by one for each barcode.
2077 $oneitem->{barcode}= $barcode;
2078 my $MARCitem = &MARCkoha2marcItem( $dbh, $oneitem);
2079 $oneitem->{marc} = $MARCitem->as_usmarc;
2080 ( $itemnumber, $error ) = &REALnewitems( $dbh, $oneitem);
2081 # $errors .= $error;
2082 # &MARCadditem( $dbh, $MARCitem, $item->{biblionumber} );
2087 =head2 moditem($dbh,$item);
2091 modify an item ($item is a hash with all item informations)
2099 my ($dbh, $item) = @_;
2100 #my $dbh = C4::Context->dbh;
2101 &REALmoditem( $dbh, $item );
2103 &MARCkoha2marcItem( $dbh, $item->{'biblionumber'}, $item->{'itemnum'} );
2105 &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $item->{biblionumber} );
2106 &MARCmoditem( $dbh, $MARCitem, $bibid, $item->{itemnum}, 0 );
2111 $error = checkitems($count,@barcodes);
2115 check for each @barcode entry that the barcode is not a duplicate
2122 my ( $count, @barcodes ) = @_;
2123 my $dbh = C4::Context->dbh;
2125 my $sth = $dbh->prepare("Select * from items where barcode=?");
2126 for ( my $i = 0 ; $i < $count ; $i++ ) {
2127 $barcodes[$i] = uc $barcodes[$i];
2128 $sth->execute( $barcodes[$i] );
2129 if ( my $data = $sth->fetchrow_hashref ) {
2130 $error .= " Duplicate Barcode: $barcodes[$i]";
2137 =head2 delitem($itemnum);
2141 delete item $itemnum being the item number to delete
2149 my $dbh = C4::Context->dbh;
2150 &REALdelitem( $dbh, $itemnum );
2153 =head2 deletebiblioitem($biblioitemnumber);
2157 delete the biblioitem $biblioitemnumber
2163 sub deletebiblioitem {
2164 my ($biblioitemnumber) = @_;
2165 my $dbh = C4::Context->dbh;
2166 &REALdelbiblioitem( $dbh, $biblioitemnumber );
2167 } # sub deletebiblioitem
2169 =head2 delbiblio($biblionumber)
2173 delete biblio $biblionumber
2181 my $dbh = C4::Context->dbh;
2182 &REALdelbiblio( $dbh, $biblio );
2183 my $bibid = &MARCfind_MARCbibid_from_oldbiblionumber( $dbh, $biblio );
2184 &MARCdelbiblio( $dbh, $bibid, 0 );
2189 ($count,@results) = getbiblio($biblionumber);
2193 return an array with hash of biblios.
2195 FIXME : biblionumber being the primary key, this sub will always return only 1 result, API should be modified...
2202 my ($biblionumber) = @_;
2203 my $dbh = C4::Context->dbh;
2204 my $sth = $dbh->prepare("Select * from biblio where biblionumber = ?");
2206 # || die "Cannot prepare $query\n" . $dbh->errstr;
2210 $sth->execute($biblionumber);
2212 # || die "Cannot execute $query\n" . $sth->errstr;
2213 while ( my $data = $sth->fetchrow_hashref ) {
2214 $results[$count] = $data;
2219 return ( $count, @results );
2224 $data = &bibdata($biblionumber, $type);
2226 Returns information about the book with the given biblionumber.
2228 C<$type> is ignored.
2230 C<&bibdata> returns a reference-to-hash. The keys are the fields in
2231 the C<biblio>, C<biblioitems>, and C<bibliosubtitle> tables in the
2234 In addition, C<$data-E<gt>{subject}> is the list of the book's
2235 subjects, separated by C<" , "> (space, comma, space).
2237 If there are multiple biblioitems with the given biblionumber, only
2238 the first one is considered.
2243 my ($bibnum, $type) = @_;
2244 my $dbh = C4::Context->dbh;
2245 my $sth = $dbh->prepare("Select *, biblioitems.notes AS bnotes, biblio.notes
2247 left join biblioitems on biblioitems.biblionumber = biblio.biblionumber
2248 left join bibliosubtitle on
2249 biblio.biblionumber = bibliosubtitle.biblionumber
2250 left join itemtypes on biblioitems.itemtype=itemtypes.itemtype
2251 where biblio.biblionumber = ?
2253 $sth->execute($bibnum);
2255 $data = $sth->fetchrow_hashref;
2257 # handle management of repeated subtitle
2258 $sth = $dbh->prepare("Select * from bibliosubtitle where biblionumber = ?");
2259 $sth->execute($bibnum);
2261 while (my $dat = $sth->fetchrow_hashref){
2263 $line{subtitle} = $dat->{subtitle};
2264 push @subtitles, \%line;
2266 $data->{subtitles} = \@subtitles;
2268 $sth = $dbh->prepare("SELECT * FROM bibliosubject
2270 AND biblionumber = ?");
2271 $sth->execute($bibnum);
2273 while (my $dat = $sth->fetchrow_hashref){
2275 $line{subject} = $dat->{'subject'};
2276 push @subjects, \%line;
2278 $data->{subjects} = \@subjects;
2280 $sth = $dbh->prepare("Select * from additionalauthors where biblionumber = ?");
2281 $sth->execute($bibnum);
2282 while (my $dat = $sth->fetchrow_hashref){
2283 $data->{'additionalauthors'} .= "$dat->{'author'} - ";
2285 chop $data->{'additionalauthors'};
2286 chop $data->{'additionalauthors'};
2287 chop $data->{'additionalauthors'};
2292 =head2 getbiblioitem
2294 ($count,@results) = getbiblioitem($biblioitemnumber);
2298 return an array with hash of biblioitemss.
2300 FIXME : biblioitemnumber being unique, this sub will always return only 1 result, API should be modified...
2307 my ($biblioitemnum) = @_;
2308 my $dbh = C4::Context->dbh;
2309 my $sth = $dbh->prepare( "Select * from biblioitems where
2310 biblioitemnumber = ?"
2315 $sth->execute($biblioitemnum);
2317 while ( my $data = $sth->fetchrow_hashref ) {
2318 $results[$count] = $data;
2323 return ( $count, @results );
2324 } # sub getbiblioitem
2326 =head2 GetBiblioItemByBiblioNumber
2328 @results= GetBiblioItemByBiblioNumber($biblionumber);
2332 return an array with hash of biblioitems for the given biblionumber.
2338 sub GetBiblioItemByBiblioNumber {
2339 my ($biblionumber) = @_;
2340 my $dbh = C4::Context->dbh;
2341 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?");
2345 $sth->execute($biblionumber);
2347 while ( my $data = $sth->fetchrow_hashref ) {
2348 push @results, $data;
2355 =head2 getitemsbybiblioitem
2357 ($count,@results) = getitemsbybiblioitem($biblionumber);
2361 returns an array with hash of items
2367 sub getitemsbybiblioitem {
2368 my ($biblioitemnum) = @_;
2369 my $dbh = C4::Context->dbh;
2370 my $sth = $dbh->prepare( "Select * from items, biblio where
2371 biblio.biblionumber = items.biblionumber and biblioitemnumber
2375 # || die "Cannot prepare $query\n" . $dbh->errstr;
2379 $sth->execute($biblioitemnum);
2381 # || die "Cannot execute $query\n" . $sth->errstr;
2382 while ( my $data = $sth->fetchrow_hashref ) {
2383 $results[$count] = $data;
2388 return ( $count, @results );
2389 } # sub getitemsbybiblioitem
2393 @results = &ItemInfo($env, $biblionumber, $type);
2395 Returns information about books with the given biblionumber.
2397 C<$type> may be either C<intra> or anything else. If it is not set to
2398 C<intra>, then the search will exclude lost, very overdue, and
2403 C<&ItemInfo> returns a list of references-to-hash. Each element
2404 contains a number of keys. Most of them are table items from the
2405 C<biblio>, C<biblioitems>, C<items>, and C<itemtypes> tables in the
2406 Koha database. Other keys include:
2410 =item C<$data-E<gt>{branchname}>
2412 The name (not the code) of the branch to which the book belongs.
2414 =item C<$data-E<gt>{datelastseen}>
2416 This is simply C<items.datelastseen>, except that while the date is
2417 stored in YYYY-MM-DD format in the database, here it is converted to
2418 DD/MM/YYYY format. A NULL date is returned as C<//>.
2420 =item C<$data-E<gt>{datedue}>
2422 =item C<$data-E<gt>{class}>
2424 This is the concatenation of C<biblioitems.classification>, the book's
2425 Dewey code, and C<biblioitems.subclass>.
2427 =item C<$data-E<gt>{ocount}>
2429 I think this is the number of copies of the book available.
2431 =item C<$data-E<gt>{order}>
2433 If this is set, it is set to C<One Order>.
2440 my ($env,$biblionumber,$type) = @_;
2441 my $dbh = C4::Context->dbh;
2442 my $query = "SELECT *,items.notforloan as itemnotforloan FROM items, biblio, biblioitems
2443 left join itemtypes on biblioitems.itemtype = itemtypes.itemtype
2444 WHERE items.biblionumber = ?
2445 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2446 AND biblio.biblionumber = items.biblionumber";
2447 $query .= " order by items.dateaccessioned desc";
2448 my $sth=$dbh->prepare($query);
2449 $sth->execute($biblionumber);
2452 while (my $data=$sth->fetchrow_hashref){
2454 my $isth=$dbh->prepare("Select issues.*,borrowers.cardnumber from issues,borrowers where itemnumber = ? and returndate is null and issues.borrowernumber=borrowers.borrowernumber");
2455 $isth->execute($data->{'itemnumber'});
2456 if (my $idata=$isth->fetchrow_hashref){
2457 $data->{borrowernumber} = $idata->{borrowernumber};
2458 $data->{cardnumber} = $idata->{cardnumber};
2459 $datedue = format_date($idata->{'date_due'});
2461 if ($datedue eq ''){
2462 my ($restype,$reserves)=C4::Reserves2::CheckReserves($data->{'itemnumber'});
2468 #get branch information.....
2469 my $bsth=$dbh->prepare("SELECT * FROM branches WHERE branchcode = ?");
2470 $bsth->execute($data->{'holdingbranch'});
2471 if (my $bdata=$bsth->fetchrow_hashref){
2472 $data->{'branchname'} = $bdata->{'branchname'};
2474 my $date=format_date($data->{'datelastseen'});
2475 $data->{'datelastseen'}=$date;
2476 $data->{'datedue'}=$datedue;
2477 # get notforloan complete status if applicable
2478 my $sthnflstatus = $dbh->prepare('select authorised_value from marc_subfield_structure where kohafield="items.notforloan"');
2479 $sthnflstatus->execute;
2480 my ($authorised_valuecode) = $sthnflstatus->fetchrow;
2481 if ($authorised_valuecode) {
2482 $sthnflstatus = $dbh->prepare("select lib from authorised_values where category=? and authorised_value=?");
2483 $sthnflstatus->execute($authorised_valuecode,$data->{itemnotforloan});
2484 my ($lib) = $sthnflstatus->fetchrow;
2485 $data->{notforloan} = $lib;
2496 ($count, @results) = &bibitems($biblionumber);
2498 Given the biblionumber for a book, C<&bibitems> looks up that book's
2499 biblioitems (different publications of the same book, the audio book
2500 and film versions, etc.).
2502 C<$count> is the number of elements in C<@results>.
2504 C<@results> is an array of references-to-hash; the keys are the fields
2505 of the C<biblioitems> and C<itemtypes> tables of the Koha database. In
2506 addition, C<itemlost> indicates the availability of the item: if it is
2507 "2", then all copies of the item are long overdue; if it is "1", then
2508 all copies are lost; otherwise, there is at least one copy available.
2515 my $dbh = C4::Context->dbh;
2516 my $sth = $dbh->prepare("SELECT biblioitems.*,
2518 MIN(items.itemlost) as itemlost,
2519 MIN(items.dateaccessioned) as dateaccessioned
2520 FROM biblioitems, itemtypes, items
2521 WHERE biblioitems.biblionumber = ?
2522 AND biblioitems.itemtype = itemtypes.itemtype
2523 AND biblioitems.biblioitemnumber = items.biblioitemnumber
2524 GROUP BY items.biblioitemnumber");
2527 $sth->execute($bibnum);
2528 while (my $data = $sth->fetchrow_hashref) {
2529 $results[$count] = $data;
2533 return($count, @results);
2539 $itemdata = &bibitemdata($biblioitemnumber);
2541 Looks up the biblioitem with the given biblioitemnumber. Returns a
2542 reference-to-hash. The keys are the fields from the C<biblio>,
2543 C<biblioitems>, and C<itemtypes> tables in the Koha database, except
2544 that C<biblioitems.notes> is given as C<$itemdata-E<gt>{bnotes}>.
2550 my $dbh = C4::Context->dbh;
2551 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");
2554 $sth->execute($bibitem);
2556 $data = $sth->fetchrow_hashref;
2563 =head2 getbibliofromitemnumber
2565 $item = &getbibliofromitemnumber($env, $dbh, $itemnumber);
2567 Looks up the item with the given itemnumber.
2569 C<$env> and C<$dbh> are ignored.
2571 C<&itemnodata> returns a reference-to-hash whose keys are the fields
2572 from the C<biblio>, C<biblioitems>, and C<items> tables in the Koha
2577 sub getbibliofromitemnumber {
2578 my ($env,$dbh,$itemnumber) = @_;
2579 $dbh = C4::Context->dbh;
2580 my $sth=$dbh->prepare("Select * from biblio,items,biblioitems
2581 where items.itemnumber = ?
2582 and biblio.biblionumber = items.biblionumber
2583 and biblioitems.biblioitemnumber = items.biblioitemnumber");
2585 $sth->execute($itemnumber);
2586 my $data=$sth->fetchrow_hashref;
2593 @barcodes = &barcodes($biblioitemnumber);
2595 Given a biblioitemnumber, looks up the corresponding items.
2597 Returns an array of references-to-hash; the keys are C<barcode> and
2600 The returned items include very overdue items, but not lost ones.
2605 #called from request.pl
2606 my ($biblioitemnumber)=@_;
2607 my $dbh = C4::Context->dbh;
2608 my $sth=$dbh->prepare("SELECT barcode, itemlost, holdingbranch FROM items
2609 WHERE biblioitemnumber = ?
2610 AND (wthdrawn <> 1 OR wthdrawn IS NULL)");
2611 $sth->execute($biblioitemnumber);
2614 while (my $data=$sth->fetchrow_hashref){
2615 $barcodes[$i]=$data;
2625 $item = &itemdata($barcode);
2627 Looks up the item with the given barcode, and returns a
2628 reference-to-hash containing information about that item. The keys of
2629 the hash are the fields from the C<items> and C<biblioitems> tables in
2634 sub get_item_from_barcode {
2636 my $dbh = C4::Context->dbh;
2637 my $sth=$dbh->prepare("Select * from items,biblioitems where barcode=?
2638 and items.biblioitemnumber=biblioitems.biblioitemnumber");
2639 $sth->execute($barcode);
2640 my $data=$sth->fetchrow_hashref;
2648 @issues = &itemissues($biblioitemnumber, $biblio);
2650 Looks up information about who has borrowed the bookZ<>(s) with the
2651 given biblioitemnumber.
2653 C<$biblio> is ignored.
2655 C<&itemissues> returns an array of references-to-hash. The keys
2656 include the fields from the C<items> table in the Koha database.
2657 Additional keys include:
2663 If the item is currently on loan, this gives the due date.
2665 If the item is not on loan, then this is either "Available" or
2666 "Cancelled", if the item has been withdrawn.
2670 If the item is currently on loan, this gives the card number of the
2671 patron who currently has the item.
2673 =item C<timestamp0>, C<timestamp1>, C<timestamp2>
2675 These give the timestamp for the last three times the item was
2678 =item C<card0>, C<card1>, C<card2>
2680 The card number of the last three patrons who borrowed this item.
2682 =item C<borrower0>, C<borrower1>, C<borrower2>
2684 The borrower number of the last three patrons who borrowed this item.
2691 my ($bibitem, $biblio)=@_;
2692 my $dbh = C4::Context->dbh;
2693 # FIXME - If this function die()s, the script will abort, and the
2694 # user won't get anything; depending on how far the script has
2695 # gotten, the user might get a blank page. It would be much better
2696 # to at least print an error message. The easiest way to do this
2697 # is to set $SIG{__DIE__}.
2698 my $sth = $dbh->prepare("Select * from items where
2699 items.biblioitemnumber = ?")
2700 || die $dbh->errstr;
2704 $sth->execute($bibitem)
2705 || die $sth->errstr;
2707 while (my $data = $sth->fetchrow_hashref) {
2708 # Find out who currently has this item.
2709 # FIXME - Wouldn't it be better to do this as a left join of
2710 # some sort? Currently, this code assumes that if
2711 # fetchrow_hashref() fails, then the book is on the shelf.
2712 # fetchrow_hashref() can fail for any number of reasons (e.g.,
2713 # database server crash), not just because no items match the
2715 my $sth2 = $dbh->prepare("select * from issues,borrowers
2716 where itemnumber = ?
2717 and returndate is NULL
2718 and issues.borrowernumber = borrowers.borrowernumber");
2720 $sth2->execute($data->{'itemnumber'});
2721 if (my $data2 = $sth2->fetchrow_hashref) {
2722 $data->{'date_due'} = $data2->{'date_due'};
2723 $data->{'card'} = $data2->{'cardnumber'};
2724 $data->{'borrower'} = $data2->{'borrowernumber'};
2726 if ($data->{'wthdrawn'} eq '1') {
2727 $data->{'date_due'} = 'Cancelled';
2729 $data->{'date_due'} = 'Available';
2735 # Find the last 3 people who borrowed this item.
2736 $sth2 = $dbh->prepare("select * from issues, borrowers
2737 where itemnumber = ?
2738 and issues.borrowernumber = borrowers.borrowernumber
2739 and returndate is not NULL
2740 order by returndate desc,timestamp desc") || die $dbh->errstr;
2741 $sth2->execute($data->{'itemnumber'}) || die $sth2->errstr;
2742 for (my $i2 = 0; $i2 < 2; $i2++) { # FIXME : error if there is less than 3 pple borrowing this item
2743 if (my $data2 = $sth2->fetchrow_hashref) {
2744 $data->{"timestamp$i2"} = $data2->{'timestamp'};
2745 $data->{"card$i2"} = $data2->{'cardnumber'};
2746 $data->{"borrower$i2"} = $data2->{'borrowernumber'};
2751 $results[$i] = $data;
2761 ($count, $subjects) = &getsubject($biblionumber);
2763 Looks up the subjects of the book with the given biblionumber. Returns
2764 a two-element list. C<$subjects> is a reference-to-array, where each
2765 element is a subject of the book, and C<$count> is the number of
2766 elements in C<$subjects>.
2772 my $dbh = C4::Context->dbh;
2773 my $sth=$dbh->prepare("Select * from bibliosubject where biblionumber=?");
2774 $sth->execute($bibnum);
2777 while (my $data=$sth->fetchrow_hashref){
2782 return($i,\@results);
2787 ($count, $authors) = &getaddauthor($biblionumber);
2789 Looks up the additional authors for the book with the given
2792 Returns a two-element list. C<$authors> is a reference-to-array, where
2793 each element is an additional author, and C<$count> is the number of
2794 elements in C<$authors>.
2800 my $dbh = C4::Context->dbh;
2801 my $sth=$dbh->prepare("Select * from additionalauthors where biblionumber=?");
2802 $sth->execute($bibnum);
2805 while (my $data=$sth->fetchrow_hashref){
2810 return($i,\@results);
2816 ($count, $subtitles) = &getsubtitle($biblionumber);
2818 Looks up the subtitles for the book with the given biblionumber.
2820 Returns a two-element list. C<$subtitles> is a reference-to-array,
2821 where each element is a subtitle, and C<$count> is the number of
2822 elements in C<$subtitles>.
2828 my $dbh = C4::Context->dbh;
2829 my $sth=$dbh->prepare("Select * from bibliosubtitle where biblionumber=?");
2830 $sth->execute($bibnum);
2833 while (my $data=$sth->fetchrow_hashref){
2838 return($i,\@results);
2844 ($count, @websites) = &getwebsites($biblionumber);
2846 Looks up the web sites pertaining to the book with the given
2849 C<$count> is the number of elements in C<@websites>.
2851 C<@websites> is an array of references-to-hash; the keys are the
2852 fields from the C<websites> table in the Koha database.
2855 #FIXME : could maybe be deleted. Otherwise, would be better in a Websites.pm package
2856 #(with add / modify / delete subs)
2859 my ($biblionumber) = @_;
2860 my $dbh = C4::Context->dbh;
2861 my $sth = $dbh->prepare("Select * from websites where biblionumber = ?");
2865 $sth->execute($biblionumber);
2866 while (my $data = $sth->fetchrow_hashref) {
2867 # FIXME - The URL scheme shouldn't be stripped off, at least
2868 # not here, since it's part of the URL, and will be useful in
2869 # constructing a link to the site. If you don't want the user
2870 # to see the "http://" part, strip that off when building the
2872 $data->{'url'} =~ s/^http:\/\///; # FIXME - Leaning toothpick
2874 $results[$count] = $data;
2879 return($count, @results);
2882 =head2 getwebbiblioitems
2884 ($count, @results) = &getwebbiblioitems($biblionumber);
2886 Given a book's biblionumber, looks up the web versions of the book
2887 (biblioitems with itemtype C<WEB>).
2889 C<$count> is the number of items in C<@results>. C<@results> is an
2890 array of references-to-hash; the keys are the items from the
2891 C<biblioitems> table of the Koha database.
2895 sub getwebbiblioitems {
2896 my ($biblionumber) = @_;
2897 my $dbh = C4::Context->dbh;
2898 my $sth = $dbh->prepare("Select * from biblioitems where biblionumber = ?
2899 and itemtype = 'WEB'");
2903 $sth->execute($biblionumber);
2904 while (my $data = $sth->fetchrow_hashref) {
2905 $data->{'url'} =~ s/^http:\/\///;
2906 $results[$count] = $data;
2911 return($count, @results);
2912 } # sub getwebbiblioitems
2915 my $NSB = '\x88'; # NSB : begin Non Sorting Block
2916 my $NSE = '\x89'; # NSE : Non Sorting Block end
2917 # handles non sorting blocks
2921 s/[ ]{0,1}$NSE/) /gm;
2928 my $dbh = C4::Context->dbh;
2929 my $result = MARCmarc2koha($dbh,$record,'');
2931 my ($biblionumber,$bibid,$title);
2932 # search duplicate on ISBN, easy and fast...
2933 if ($result->{isbn}) {
2934 $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=?");
2935 $sth->execute($result->{'isbn'});
2936 ($biblionumber,$bibid,$title) = $sth->fetchrow;
2937 return $biblionumber,$bibid,$title if ($biblionumber);
2939 # a more complex search : build a request for SearchMarc::catalogsearch()
2940 my (@tags, @and_or, @excluding, @operator, @value, $offset,$length);
2941 # search on biblio.title
2942 my ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.title","");
2943 if ($record->field($tag)) {
2944 if ($record->field($tag)->subfields($subfield)) {
2945 push @tags, "'".$tag.$subfield."'";
2946 push @and_or, "and";
2947 push @excluding, "";
2948 push @operator, "contains";
2949 push @value, $record->field($tag)->subfield($subfield);
2950 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2953 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"bibliosubtitle.subtitle","");
2954 if ($record->field($tag)) {
2955 if ($record->field($tag)->subfields($subfield)) {
2956 push @tags, "'".$tag.$subfield."'";
2957 push @and_or, "and";
2958 push @excluding, "";
2959 push @operator, "contains";
2960 push @value, $record->field($tag)->subfield($subfield);
2961 # warn "for title, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2964 # ... and on biblio.author
2965 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblio.author","");
2966 if ($record->field($tag)) {
2967 if ($record->field($tag)->subfields($subfield)) {
2968 push @tags, "'".$tag.$subfield."'";
2969 push @and_or, "and";
2970 push @excluding, "";
2971 push @operator, "contains";
2972 push @value, $record->field($tag)->subfield($subfield);
2973 # warn "for author, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2976 # ... and on publicationyear.
2977 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publicationyear","");
2978 if ($record->field($tag)) {
2979 if ($record->field($tag)->subfields($subfield)) {
2980 push @tags, "'".$tag.$subfield."'";
2981 push @and_or, "and";
2982 push @excluding, "";
2983 push @operator, "=";
2984 push @value, $record->field($tag)->subfield($subfield);
2985 # warn "for publicationyear, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
2989 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.size","");
2990 if ($record->field($tag)) {
2991 if ($record->field($tag)->subfields($subfield)) {
2992 push @tags, "'".$tag.$subfield."'";
2993 push @and_or, "and";
2994 push @excluding, "";
2995 push @operator, "=";
2996 push @value, $record->field($tag)->subfield($subfield);
2997 # warn "for size, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
3000 # ... and on publisher.
3001 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.publishercode","");
3002 if ($record->field($tag)) {
3003 if ($record->field($tag)->subfields($subfield)) {
3004 push @tags, "'".$tag.$subfield."'";
3005 push @and_or, "and";
3006 push @excluding, "";
3007 push @operator, "=";
3008 push @value, $record->field($tag)->subfield($subfield);
3009 # warn "for publishercode, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
3012 # ... and on volume.
3013 ($tag,$subfield) = MARCfind_marc_from_kohafield($dbh,"biblioitems.volume","");
3014 if ($record->field($tag)) {
3015 if ($record->field($tag)->subfields($subfield)) {
3016 push @tags, "'".$tag.$subfield."'";
3017 push @and_or, "and";
3018 push @excluding, "";
3019 push @operator, "=";
3020 push @value, $record->field($tag)->subfield($subfield);
3021 # warn "for volume, I add $tag / $subfield".$record->field($tag)->subfield($subfield);
3025 my ($finalresult,$nbresult) = C4::SearchMarc::catalogsearch($dbh,\@tags,\@and_or,\@excluding,\@operator,\@value,0,10);
3026 # there is at least 1 result => return the 1st one
3028 # warn "$nbresult => ".@$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
3029 return @$finalresult[0]->{biblionumber},@$finalresult[0]->{bibid},@$finalresult[0]->{title};
3031 # no result, returns nothing
3038 if(substr($isbn, 0, 1) <=7) {
3039 $seg1 = substr($isbn, 0, 1);
3040 } elsif(substr($isbn, 0, 2) <= 94) {
3041 $seg1 = substr($isbn, 0, 2);
3042 } elsif(substr($isbn, 0, 3) <= 995) {
3043 $seg1 = substr($isbn, 0, 3);
3044 } elsif(substr($isbn, 0, 4) <= 9989) {
3045 $seg1 = substr($isbn, 0, 4);
3047 $seg1 = substr($isbn, 0, 5);
3049 my $x = substr($isbn, length($seg1));
3051 if(substr($x, 0, 2) <= 19) {
3052 # if(sTmp2 < 10) sTmp2 = "0" sTmp2;
3053 $seg2 = substr($x, 0, 2);
3054 } elsif(substr($x, 0, 3) <= 699) {
3055 $seg2 = substr($x, 0, 3);
3056 } elsif(substr($x, 0, 4) <= 8399) {
3057 $seg2 = substr($x, 0, 4);
3058 } elsif(substr($x, 0, 5) <= 89999) {
3059 $seg2 = substr($x, 0, 5);
3060 } elsif(substr($x, 0, 6) <= 9499999) {
3061 $seg2 = substr($x, 0, 6);
3063 $seg2 = substr($x, 0, 7);
3065 my $seg3=substr($x,length($seg2));
3066 $seg3=substr($seg3,0,length($seg3)-1) ;
3067 my $seg4 = substr($x, -1, 1);
3068 return "$seg1-$seg2-$seg3-$seg4";
3071 =head2 get_itemnumbers_of
3073 my @itemnumbers_of = get_itemnumbers_of(@biblionumbers);
3075 Given a list of biblionumbers, return the list of corresponding itemnumbers
3076 for each biblionumber.
3078 Return a reference on a hash where keys are biblionumbers and values are
3079 references on array of itemnumbers.
3082 sub get_itemnumbers_of {
3083 my @biblionumbers = @_;
3085 my $dbh = C4::Context->dbh;
3091 WHERE biblionumber IN (?'.(',?' x scalar @biblionumbers - 1).')
3093 my $sth = $dbh->prepare($query);
3094 $sth->execute(@biblionumbers);
3098 while (my ($itemnumber, $biblionumber) = $sth->fetchrow_array) {
3099 push @{$itemnumbers_of{$biblionumber}}, $itemnumber;
3102 return \%itemnumbers_of;
3105 sub get_iteminfos_of {
3106 my @itemnumbers = @_;
3111 WHERE itemnumber IN ('.join(',', @itemnumbers).')
3113 return get_infos_of($query, 'itemnumber');
3116 sub get_biblioiteminfos_of {
3117 my @biblioitemnumbers = @_;
3120 SELECT biblioitemnumber,
3124 WHERE biblioitemnumber IN ('.join(',', @biblioitemnumbers).')
3127 return get_infos_of($query, 'biblioitemnumber');
3130 END { } # module clean-up code here (global destructor)
3136 Koha Developement team <info@koha.org>
3138 Paul POULAIN paul.poulain@free.fr
3144 # Revision 1.175 2006/07/27 13:46:30 toins
3147 # Revision 1.174 2006/07/12 13:43:42 btoumi
3149 # Biblio.pm: add in export line getbibliofromitemnumber function
3150 # fines2.pl:call to biblio.pm for use of getbibliofromitemnumber function
3152 # Revision 1.173 2006/07/04 14:36:51 toins
3153 # Head & rel_2_2 merged
3155 # Revision 1.172 2006/06/06 23:13:14 bob_lyon
3156 # Merging katipo changes...
3158 # altering subject search to stop returning blank rows
3160 # Revision 1.171 2006/05/17 16:06:24 plg
3161 # New feature from SAN Ouest Provence: ability to reserve a specific item in
3162 # the intranet. The development was made on branch 2.2 by Arnaud Laurin from
3163 # Ouest Provence and integrated on HEAD by Pierrick Le Gall from INEO media
3166 # New page reserve/request.pl taking a biblionumber as entry point.
3170 # - C4::Biblio::get_iteminfos_of retrieves item informations for a list of
3173 # - C4::Biblio::get_biblioiteminfos_of retrieves biblioitem informations for a
3174 # list of biblioitemnumbers
3176 # - C4::Biblio::get_itemnumbers_of retrieve the list of itemnumbers related to
3177 # each biblionumber given in argument.
3179 # - C4::Circulation::Circ2::get_return_date_of retrieves return date for a
3180 # list of itemnumbers.
3182 # - C4::Koha::get_itemtypeinfos_of retrieves the informations related to a
3183 # list of itemtypes.
3185 # - C4::Koha::get_branchinfos_of retrieves the informations related to a list
3188 # - C4::Koha::get_notforloan_label_of retrives the list of status/label for
3189 # the authorised_values related to notforloan.
3191 # - C4::Koha::get_infos_of is the generic function used by all get_*infos_of.
3193 # - C4::Reserves2::GetNumberReservesFromBorrower
3195 # - C4::Reserves2::GetFirstReserveDateFromItem
3197 # Modified functions:
3199 # - C4::Reserves2::FindReserves was simplified to be more readable.
3201 # The reservation page is reserve/request.pl and is linked from nowhere as
3202 # long as zebra is not stable yet on HEAD.
3204 # Revision 1.170 2006/04/15 02:47:47 tgarip1957
3205 # Change the MARC Leader to UTF-8 incase user did not set it. Important for Zebra.
3206 # The new M::F::XML is sensitive to leader settings
3208 # Revision 1.169 2006/04/10 20:39:49 tgarip1957
3209 # New sub to use by Circ2.pm . Allows one subfield of MARC holdings fields to be updated to use with branch transfer(holdingbranch) and onloan flag when set
3211 # Revision 1.168 2006/04/03 04:00:02 rangi
3212 # Modify item now works
3214 # BUT only if there is only one item, if there is more than one item, it gets messed up.
3215 # They get combined into the form, ill work on this next
3217 # Revision 1.167 2006/04/03 02:12:49 kados
3218 # some modifs to improve plugin support
3220 # Revision 1.166 2006/04/01 22:10:50 rangi
3221 # Fixing the problem that all items were getting biblioitem=1 set
3223 # Revision 1.165 2006/04/01 21:22:05 rangi
3224 # Adding a little fake subroutine that a few scripts in the opac depend on, can be removed once the opac scripts are rewritten
3226 # Revision 1.164 2006/03/29 01:56:25 rangi
3227 # Delete isnt working using the extended services method
3229 # Revision 1.163 2006/03/28 23:05:08 rangi
3230 # Delete working now
3232 # Revision 1.162 2006/03/13 23:12:44 rangi
3233 # Adding commits, so that changes stick
3235 # Revision 1.161 2006/03/10 02:40:38 kados
3236 # syncing MARChtml2xml wtih rel_2_2, removing unused MARChtml2marc
3238 # Revision 1.160 2006/03/07 22:00:18 kados
3239 # adding support for 'delete' function
3241 # Revision 1.159 2006/03/07 21:54:47 rangi
3242 # Starting work on deletes
3244 # Revision 1.158 2006/03/06 02:45:41 kados
3245 # Adding fixes to MARC editor to HEAD
3247 # Revision 1.157 2006/03/01 03:07:54 kados
3248 # rollback ... by accident I committed a rel_2_2 Biblio.pm
3250 # Revision 1.155 2006/02/27 01:08:31 kados
3251 # Removing 'our Zconn' from top...
3253 # Revision 1.154 2006/02/26 00:08:20 kados
3254 # moving all $Zconn s to z3950_extended_services (currently, nothing
3257 # Revision 1.153 2006/02/25 22:39:10 kados
3258 # Another purely documentation commit. Just changing formatting to ease
3261 # Revision 1.152 2006/02/25 21:17:20 kados
3262 # Purely documentation change: converted all =head2 entries to use function
3263 # name as title rather than usage as title
3265 # Revision 1.151 2006/02/25 21:02:20 kados
3267 # Further cleanup, convering new routines to 4-chars
3269 # Revision 1.150 2006/02/25 20:49:15 kados
3270 # Better documentation, added warning if serviceType is 'drop' since it's
3271 # not supported in Zebra.
3273 # Revision 1.149 2006/02/25 20:30:32 kados
3274 # IMPORTANT: Paul, I've removed the decode_char routine because it's no
3275 # longer necessary. If we need to convert from MARC-8 for display, we should:
3278 # 2. do it with MARC::Charset
3280 # If you still need it, let me know and I'll put it back in.
3282 # Revision 1.148 2006/02/25 19:23:01 kados
3283 # cleaning up POD docs, deleting zebra_create as it's no longer used (
3284 # replaced by z3950_extended_services).
3286 # Revision 1.147 2006/02/25 19:09:59 kados
3287 # readding some lost subs
3289 # Revision 1.145 2006/02/22 01:02:39 kados
3290 # Replacing all calls to zebra_update with calls to
3291 # z3950_extended_services. More work coming, but it's
3294 # Revision 1.144 2006/02/20 14:22:38 kados
3297 # Revision 1.143 2006/02/20 13:26:11 kados
3298 # A new subroutine to handle Z39.50 extended services. You pass it a
3299 # connection object, service type, service options, and a record, and
3300 # it performs the service and handles any exception found.
3302 # Revision 1.142 2006/02/16 20:49:56 kados
3303 # destroy a connection after we're done -- we really should just have one
3304 # connection object and not destroy it until the whole transaction is
3305 # finished -- but this will do for now
3307 # Revision 1.141 2006/02/16 19:47:22 rangi
3308 # Trying to error trap a little more.
3310 # Revision 1.140 2006/02/14 21:36:03 kados
3311 # adding a 'use ZOOM' to biblio.pm, needed for non-mod_perl install.
3312 # also adding diagnostic error if not able to connect to Zebra
3314 # Revision 1.139 2006/02/14 19:53:25 rangi
3315 # Just a little missing my
3317 # Seems to be working great Paul, and I like what you did with zebradb
3319 # Revision 1.138 2006/02/14 11:25:22 tipaul
3320 # road to 3.0 : updating a biblio in zebra seems to work. Still working on it, there are probably some bugs !
3322 # Revision 1.137 2006/02/13 16:34:26 tipaul
3323 # fixing some warnings (perl -w should be quiet)
3325 # Revision 1.136 2006/01/10 17:01:29 tipaul
3326 # adding a XMLgetbiblio in Biblio.pm (1st draft, to use with zebra)
3328 # Revision 1.135 2006/01/06 16:39:37 tipaul
3329 # synch'ing head and rel_2_2 (from 2.2.5, including npl templates)
3330 # Seems not to break too many things, but i'm probably wrong here.
3331 # at least, new features/bugfixes from 2.2.5 are here (tested on some features on my head local copy)
3333 # - removing useless directories (koha-html and koha-plucene)
3335 # Revision 1.134 2006/01/04 15:54:55 tipaul
3336 # utf8 is a : go for beta test in HEAD.
3337 # some explanations :
3338 # - 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.
3339 # - *-top.inc will show the pages in utf8
3340 # - 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.
3341 # - using marcxml field and no more the iso2709 raw marc biblioitems.marc field.
3343 # Revision 1.133 2005/12/12 14:25:51 thd
3346 # Reverse array filled with elements from repeated subfields
3347 # to avoid last to first concatenation of elements in Koha DB.-
3349 # Revision 1.132 2005-10-26 09:12:33 tipaul
3350 # big commit, still breaking things...
3352 # * synch with rel_2_2. Probably the last non manual synch, as rel_2_2 should not be modified deeply.
3353 # * code cleaning (cleaning warnings from perl -w) continued
3355 # Revision 1.131 2005/09/22 10:01:45 tipaul
3356 # see mail on koha-devel : code cleaning on Search.pm + normalizing API + use of biblionumber everywhere (instead of bn, biblio, ...)
3358 # Revision 1.130 2005/09/02 14:34:14 tipaul
3359 # continuing the work to move to zebra. Begin of work for MARC=OFF support.
3360 # IMPORTANT NOTE : the MARCkoha2marc sub API has been modified. Instead of biblionumber & biblioitemnumber, it now gets a hash.
3361 # The sub is used only in Biblio.pm, so the API change should be harmless (except for me, but i'm aware ;-) )
3363 # Revision 1.129 2005/08/12 13:50:31 tipaul
3364 # removing useless sub declarations
3366 # Revision 1.128 2005/08/11 16:12:47 tipaul
3367 # Playing with the zebra...
3369 # * go to koha cvs home directory
3370 # * in misc/zebra there is a unimarc directory. I suggest that marc21 libraries create a marc21 directory
3371 # * put your zebra.cfg files here & create your database.
3372 # * from koha cvs home directory, ln -s misc/zebra/marc21 zebra (I mean create a symbolic link to YOUR zebra directory)
3373 # * now, everytime you add/modify a biblio/item your zebra DB is updated correctly.
3376 # * this uses a system call in perl. CPU consumming, but we are waiting for indexdata Perl/zoom
3377 # * deletion still not work
3378 # * UNIMARC zebra config files are provided in misc/zebra/unimarc directory. The most important line being :
3380 # recordId: (bib1,Local-number)
3384 # elm 090 Local-number -
3385 # elm 090/? Local-number -
3386 # elm 090/?/9 Local-number !:w
3388 # (090$9 being the field mapped to biblio.biblionumber in Koha)
3390 # Revision 1.127 2005/08/11 14:37:32 tipaul
3392 # * removing useless subs
3393 # * removing some subs that are also elsewhere
3394 # * 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)
3396 # Revision 1.126 2005/08/11 09:13:28 tipaul
3397 # just removing useless subs (a lot !!!) for code cleaning
3399 # Revision 1.125 2005/08/11 09:00:07 tipaul
3400 # Ok guys, this time, it seems that item add and modif begin working as expected...
3401 # Still a lot of bugs to fix, of course
3403 # Revision 1.124 2005/08/10 10:21:15 tipaul
3404 # continuing the road to zebra :
3405 # - the biblio add begins to work.
3406 # - the biblio modif begins to work.
3408 # (still without doing anything on zebra)
3409 # (no new change in updatedatabase)
3411 # Revision 1.123 2005/08/09 14:10:28 tipaul
3412 # 1st commit to go to zebra.
3413 # don't update your cvs if you want to have a working head...
3415 # this commit contains :
3416 # * 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...
3417 # * 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.
3418 # * other files : get rid of bibid and use biblionumber instead.
3421 # * does not do anything on zebra yet.
3422 # * if you rename marc_subfield_table, you can't search anymore.
3423 # * you can view a biblio & bibliodetails, go to MARC editor, but NOT save any modif.
3424 # * 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 ;-) )
3426 # 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
3427 # 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.
3429 # tipaul cutted previous commit notes