# Copyright 2000-2002 Katipo Communications
# Copyright 2010 BibLibre
+# Copyright 2011 Equinox Software, Inc.
#
# This file is part of Koha.
#
use strict;
use warnings;
+use Carp;
# use utf8;
use MARC::Record;
use C4::Charset;
require C4::Heading;
require C4::Serials;
+require C4::Items;
use vars qw($VERSION @ISA @EXPORT);
sub ModBiblio {
my ( $record, $biblionumber, $frameworkcode ) = @_;
+ croak "No record" unless $record;
+
if ( C4::Context->preference("CataloguingLog") ) {
my $newrecord = GetMarcBiblio($biblionumber);
logaction( "CATALOGUING", "MODIFY", $biblionumber, "BEFORE=>" . $newrecord->as_formatted );
}
- SetUTF8Flag($record);
- my $dbh = C4::Context->dbh;
-
- $frameworkcode = "" unless $frameworkcode;
-
- # get the items before and append them to the biblio before updating the record, atm we just have the biblio
- my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
- my $oldRecord = GetMarcBiblio($biblionumber);
-
- # delete any item fields from incoming record to avoid
- # duplication or incorrect data - use AddItem() or ModItem()
- # to change items
- foreach my $field ( $record->field($itemtag) ) {
- $record->delete_field($field);
- }
-
- # parse each item, and, for an unknown reason, re-encode each subfield
- # if you don't do that, the record will have encoding mixed
- # and the biblio will be re-encoded.
- # strange, I (Paul P.) searched more than 1 day to understand what happends
- # but could only solve the problem this way...
- my @fields = $oldRecord->field($itemtag);
- foreach my $fielditem (@fields) {
- my $field;
- foreach ( $fielditem->subfields() ) {
- # re-encode the subfield only if it isn't already in utf-8.
- my ($tag, $value) = @$_;
- $tag = Encode::encode('utf-8', $tag) unless utf8::is_utf8($tag);
- $value = Encode::encode('utf-8', $value) unless utf8::is_utf8($value);
-
- if ($field) {
- $field->add_subfields( $tag => $value );
- } else {
- $field = MARC::Field->new( "$itemtag", '', '', $tag => $value );
- }
- }
- $record->append_fields($field);
- }
-
+ # Cleaning up invalid fields must be done early or SetUTF8Flag is liable to
+ # throw an exception which probably won't be handled.
foreach my $field ($record->fields()) {
if (! $field->is_control_field()) {
- if (scalar($field->subfields()) == 0) {
- $record->delete_fields($field);
+ if (scalar($field->subfields()) == 0 || (scalar($field->subfields()) == 1 && $field->subfield('9'))) {
+ $record->delete_field($field);
}
}
}
+ SetUTF8Flag($record);
+ my $dbh = C4::Context->dbh;
+
+ $frameworkcode = "" unless $frameworkcode;
+
+ _strip_item_fields($record, $frameworkcode);
+
# update biblionumber and biblioitemnumber in MARC
# FIXME - this is assuming a 1 to 1 relationship between
# biblios and biblioitems
return 1;
}
+=head2 _strip_item_fields
+
+ _strip_item_fields($record, $frameworkcode)
+
+Utility routine to remove item tags from a
+MARC bib.
+
+=cut
+
+sub _strip_item_fields {
+ my $record = shift;
+ my $frameworkcode = shift;
+ # get the items before and append them to the biblio before updating the record, atm we just have the biblio
+ my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
+
+ # delete any item fields from incoming record to avoid
+ # duplication or incorrect data - use AddItem() or ModItem()
+ # to change items
+ foreach my $field ( $record->field($itemtag) ) {
+ $record->delete_field($field);
+ }
+}
+
=head2 ModBiblioframework
ModBiblioframework($biblionumber,$frameworkcode);
sub GetISBDView {
my ( $biblionumber, $template ) = @_;
- my $record = GetMarcBiblio($biblionumber);
+ my $record = GetMarcBiblio($biblionumber, 1);
+ return undef unless defined $record;
my $itemtype = &GetFrameworkCode($biblionumber);
my ( $holdingbrtagf, $holdingbrtagsubf ) = &GetMarcFromKohaField( "items.holdingbranch", $itemtype );
my $tagslib = &GetMarcStructure( 1, $itemtype );
=head2 GetMarcBiblio
- my $record = GetMarcBiblio($biblionumber);
+ my $record = GetMarcBiblio($biblionumber, [$embeditems]);
Returns MARC::Record representing bib identified by
C<$biblionumber>. If no bib exists, returns undef.
-The MARC record contains both biblio & item data.
+C<$embeditems>. If set to true, items data are included.
+The MARC record contains biblio data, and items data if $embeditems is set to true.
=cut
sub GetMarcBiblio {
my $biblionumber = shift;
+ my $embeditems = shift || 0;
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT marcxml FROM biblioitems WHERE biblionumber=? ");
$sth->execute($biblionumber);
if ($marcxml) {
$record = eval { MARC::Record::new_from_xml( $marcxml, "utf8", C4::Context->preference('marcflavour') ) };
if ($@) { warn " problem with :$biblionumber : $@ \n$marcxml"; }
+ return unless $record;
+
+ C4::Biblio::EmbedItemsInMarcBiblio($record, $biblionumber) if ($embeditems);
# $record = MARC::Record::new_from_usmarc( $marc) if $marc;
return $record;
if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) {
# Setting datas
- $aulast = $record->subfield( '700', 'a' );
- $aufirst = $record->subfield( '700', 'b' );
+ $aulast = $record->subfield( '700', 'a' ) || '';
+ $aufirst = $record->subfield( '700', 'b' ) || '';
$oauthors = "&rft.au=$aufirst $aulast";
# others authors
( $mtx eq 'dc' )
? "&rft.title=" . $record->subfield( '200', 'a' )
: "&rft.title=" . $record->subfield( '200', 'a' ) . "&rft.btitle=" . $record->subfield( '200', 'a' );
- $pubyear = $record->subfield( '210', 'd' );
- $publisher = $record->subfield( '210', 'c' );
- $isbn = $record->subfield( '010', 'a' );
- $issn = $record->subfield( '011', 'a' );
+ $pubyear = $record->subfield( '210', 'd' ) || '';
+ $publisher = $record->subfield( '210', 'c' ) || '';
+ $isbn = $record->subfield( '010', 'a' ) || '';
+ $issn = $record->subfield( '011', 'a' ) || '';
} else {
# MARC21 need some improve
my $value = $subject_subfield->[1];
my $linkvalue = $value;
$linkvalue =~ s/(\(|\))//g;
- my $operator = " and " unless $counter == 0;
+ my $operator;
+ if ( $counter != 0 ) {
+ $operator = ' and ';
+ }
if ( $code eq 9 ) {
$found9 = 1;
@link_loop = ( { 'limit' => 'an', link => "$linkvalue" } );
if ( not $found9 ) {
push @link_loop, { 'limit' => $subject_limit, link => $linkvalue, operator => $operator };
}
- my $separator = C4::Context->preference("authoritysep") unless $counter == 0;
+ my $separator;
+ if ( $counter != 0 ) {
+ $separator = C4::Context->preference('authoritysep');
+ }
# ignore $9
my @this_link_loop = @link_loop;
my $value = $authors_subfield->[1];
my $linkvalue = $value;
$linkvalue =~ s/(\(|\))//g;
- my $operator = " and " unless $count_auth == 0;
+ my $operator;
+ if ( $count_auth != 0 ) {
+ $operator = ' and ';
+ }
# if we have an authority link, use that as the link, otherwise use standard searching
if ($subfield9) {
$value = GetAuthorisedValueDesc( $field->tag(), $authors_subfield->[0], $authors_subfield->[1], '', $tagslib )
if ( $marcflavour eq 'UNIMARC' and ( $authors_subfield->[0] =~ /4/ ) );
my @this_link_loop = @link_loop;
- my $separator = C4::Context->preference("authoritysep") unless $count_auth == 0;
- push @subfields_loop, { code => $subfieldcode, value => $value, link_loop => \@this_link_loop, separator => $separator } unless ( $authors_subfield->[0] eq '9' );
+ my $separator;
+ if ( $count_auth != 0 ) {
+ $separator = C4::Context->preference('authoritysep');
+ }
+ push @subfields_loop,
+ { code => $subfieldcode,
+ value => $value,
+ link_loop => \@this_link_loop,
+ separator => $separator
+ }
+ unless ( $authors_subfield->[0] eq '9' );
$count_auth++;
}
push @marcauthors, { MARCAUTHOR_SUBFIELDS_LOOP => \@subfields_loop };
my $value = $series_subfield->[1];
my $linkvalue = $value;
$linkvalue =~ s/(\(|\))//g;
- my $operator = " and " unless $counter == 0;
- push @link_loop, { link => $linkvalue, operator => $operator };
- my $separator = C4::Context->preference("authoritysep") unless $counter == 0;
+ if ( $counter != 0 ) {
+ push @link_loop, { link => $linkvalue, operator => ' and ', };
+ } else {
+ push @link_loop, { link => $linkvalue, operator => undef, };
+ }
+ my $separator;
+ if ( $counter != 0 ) {
+ $separator = C4::Context->preference('authoritysep');
+ }
if ($volume_number) {
push @subfields_loop, { volumenum => $value };
} else {
- push @subfields_loop, { code => $code, value => $value, link_loop => \@link_loop, separator => $separator, volumenum => $volume_number } unless ( $series_subfield->[0] eq '9' );
+ if ( $series_subfield->[0] ne '9' ) {
+ push @subfields_loop, {
+ code => $code,
+ value => $value,
+ link_loop => \@link_loop,
+ separator => $separator,
+ volumenum => $volume_number,
+ };
+ }
}
$counter++;
}
my $tagslib = &GetMarcStructure( 1, $frameworkcode );
# return nothing if we don't have found an existing framework.
- return "" unless $tagslib;
- my $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum ) if ($itemnum);
+ return q{} unless $tagslib;
+ my $itemrecord;
+ if ($itemnum) {
+ $itemrecord = C4::Items::GetMarcItem( $bibnum, $itemnum );
+ }
my @loop_data;
my $authorised_values_sth = $dbh->prepare( "SELECT authorised_value,lib FROM authorised_values WHERE category=? ORDER BY lib" );
foreach my $tag ( sort keys %{$tagslib} ) {
&& C4::Context->preference('itemcallnumber') ) {
my $CNtag = substr( C4::Context->preference('itemcallnumber'), 0, 3 );
my $CNsubfield = substr( C4::Context->preference('itemcallnumber'), 3, 1 );
- my $temp = $itemrecord->field($CNtag) if ($itemrecord);
- if ($temp) {
- $defaultvalue = $temp->subfield($CNsubfield);
+ if ($itemrecord) {
+ my $temp = $itemrecord->field($CNtag);
+ if ($temp) {
+ $defaultvalue = $temp->subfield($CNsubfield);
+ }
}
}
if ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.itemcallnumber'
&& $defaultvalues
&& $defaultvalues->{'callnumber'} ) {
- my $temp = $itemrecord->field($subfield) if ($itemrecord);
+ my $temp;
+ if ($itemrecord) {
+ $temp = $itemrecord->field($subfield);
+ }
unless ($temp) {
$defaultvalue = $defaultvalues->{'callnumber'} if $defaultvalues;
}
if ( ( $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.holdingbranch' || $tagslib->{$tag}->{$subfield}->{kohafield} eq 'items.homebranch' )
&& $defaultvalues
&& $defaultvalues->{'branchcode'} ) {
- my $temp = $itemrecord->field($subfield) if ($itemrecord);
+ my $temp;
+ if ($itemrecord) {
+ $temp = $itemrecord->field($subfield);
+ }
unless ($temp) {
$defaultvalue = $defaultvalues->{branchcode} if $defaultvalues;
}
}
}
}
- my $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield )
- if ( $itemrecord && $itemrecord->field($itemtagfield) );
+ my $itemnumber;
+ if ( $itemrecord && $itemrecord->field($itemtagfield) ) {
+ $itemnumber = $itemrecord->subfield( $itemtagfield, $itemtagsubfield );
+ }
return {
'itemtagfield' => $itemtagfield,
'itemtagsubfield' => $itemtagsubfield,
return %indexes;
}
+=head2 EmbedItemsInMarcBiblio
+
+ EmbedItemsInMarcBiblio($marc, $biblionumber);
+
+Given a MARC::Record object containing a bib record,
+modify it to include the items attached to it as 9XX
+per the bib's MARC framework.
+
+=cut
+
+sub EmbedItemsInMarcBiblio {
+ my ($marc, $biblionumber) = @_;
+ croak "No MARC record" unless $marc;
+
+ my $frameworkcode = GetFrameworkCode($biblionumber);
+ _strip_item_fields($marc, $frameworkcode);
+
+ # ... and embed the current items
+ my $dbh = C4::Context->dbh;
+ my $sth = $dbh->prepare("SELECT itemnumber FROM items WHERE biblionumber = ?");
+ $sth->execute($biblionumber);
+ my @item_fields;
+ my ( $itemtag, $itemsubfield ) = GetMarcFromKohaField( "items.itemnumber", $frameworkcode );
+ while (my ($itemnumber) = $sth->fetchrow_array) {
+ my $item_marc = C4::Items::GetMarcItem($biblionumber, $itemnumber);
+ push @item_fields, $item_marc->field($itemtag);
+ }
+ $marc->insert_fields_ordered(@item_fields);
+}
+
=head1 INTERNAL FUNCTIONS
=head2 _DelBiblioNoZebra($biblionumber,$record,$server);
# drop old field and create new one...
$old_field = $record->field($biblio_tag);
$record->delete_field($old_field) if $old_field;
- $record->append_fields($new_field);
+ $record->insert_fields_ordered($new_field);
# deal with biblioitemnumber
if ( $biblioitem_tag < 10 ) {
}
substr( $string, 22, 6, "frey50" );
unless ( $record->subfield( 100, "a" ) ) {
- $record->insert_grouped_field( MARC::Field->new( 100, "", "", "a" => $string ) );
+ $record->insert_fields_ordered( MARC::Field->new( 100, "", "", "a" => $string ) );
}
}