diff --git a/C4/XSLT.pm b/C4/XSLT.pm index e86ee03a0f..c328b2f2fc 100644 --- a/C4/XSLT.pm +++ b/C4/XSLT.pm @@ -224,6 +224,14 @@ sub XSLTParse4Display { } } + # possibly show volumes link in Detail views + if ($xslsyspref =~ m/Details/) { + $biblio //= Koha::Biblios->find( $biblionumber ); + my $volumes = $biblio->get_marc_volumes(); + $variables->{show_volumes_link} = ( scalar @{$volumes} == 0 ) ? 0 : 1; + } + + # embed variables my $varxml = "\n"; while (my ($key, $value) = each %$variables) { $value //= q{}; diff --git a/Koha/Biblio.pm b/Koha/Biblio.pm index 7f0f2ecb4f..1e42496839 100644 --- a/Koha/Biblio.pm +++ b/Koha/Biblio.pm @@ -1658,6 +1658,76 @@ sub opac_summary_html { return $summary_html; } +=head3 get_marc_volumes + + my $volumes = $self->get_marc_volumes(); + +Returns an array of MARCXML data, which are volumes parts of +this object (MARC21 773$w points to this) + +=cut + +sub get_marc_volumes { + my ($self, $max_results) = @_; + + return [] if (C4::Context->preference('marcflavour') ne 'MARC21'); + + my $searchstr = $self->get_volumes_query; + + if (defined($searchstr)) { + my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX}); + my ( $errors, $results, $total_hits ) = $searcher->simple_search_compat( $searchstr, 0, $max_results ); + $self->{_volumes} = $results if ( defined($results) && scalar(@$results) ); + } + + return $self->{_volumes} || []; +} + +=head2 get_volumes_query + +Returns a query which can be used to search for all component parts of MARC21 biblios + +=cut + +sub get_volumes_query { + my ($self) = @_; + + my $marc = $self->metadata->record; + + my $searchstr; + if ( C4::Context->preference('UseControlNumber') ) { + my $pf001 = $marc->field('001') || undef; + + if ( defined($pf001) ) { + $searchstr = "("; + my $pf003 = $marc->field('003') || undef; + + if ( !defined($pf003) ) { + # search for 773$w='Host001' + $searchstr .= "rcn:" . $pf001->data(); + } + else { + $searchstr .= "("; + # search for (773$w='Host001' and 003='Host003') or 773$w='(Host003)Host001' + $searchstr .= "(rcn:" . $pf001->data() . " AND cni:" . $pf003->data() . ")"; + $searchstr .= " OR rcn:\"" . $pf003->data() . " " . $pf001->data() . "\""; + $searchstr .= ")"; + } + + # exclude monograph and serial component part records + $searchstr .= " NOT (bib-level:a OR bib-level:b)"; + $searchstr .= ")"; + } + } + else { + my $cleaned_title = $marc->title; + $cleaned_title =~ tr|/||; + $searchstr = "ti,phr:($cleaned_title)"; + } + + return $searchstr; +} + =head2 Internal methods =head3 type diff --git a/koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21slim2intranetDetail.xsl b/koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21slim2intranetDetail.xsl index 3aade69a51..e4f1719fc7 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21slim2intranetDetail.xsl +++ b/koha-tmpl/intranet-tmpl/prog/en/xslt/MARC21slim2intranetDetail.xsl @@ -231,7 +231,8 @@ - + + Volumes: diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl b/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl index a27c8b9830..842f52e79e 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl +++ b/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl @@ -273,7 +273,8 @@ - + + Volumes: diff --git a/t/db_dependent/Koha/Biblio.t b/t/db_dependent/Koha/Biblio.t index a0c77d64aa..261864d041 100755 --- a/t/db_dependent/Koha/Biblio.t +++ b/t/db_dependent/Koha/Biblio.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 29; +use Test::More tests => 30; use Test::Exception; use Test::Warn; @@ -615,6 +615,39 @@ subtest 'get_components_query' => sub { } }; +subtest 'get_volumes_query' => sub { + plan tests => 3; + + my $biblio = $builder->build_sample_biblio(); + my $biblionumber = $biblio->biblionumber; + my $record = $biblio->metadata->record; + + t::lib::Mocks::mock_preference( 'UseControlNumber', '0' ); + is( $biblio->get_volumes_query, "ti,phr:(Some boring read)", "UseControlNumber disabled" ); + + t::lib::Mocks::mock_preference( 'UseControlNumber', '1' ); + my $marc_001_field = MARC::Field->new( '001', $biblionumber ); + $record->append_fields($marc_001_field); + C4::Biblio::ModBiblio( $record, $biblio->biblionumber ); + $biblio = Koha::Biblios->find( $biblio->biblionumber ); + + is( + $biblio->get_volumes_query, "rcn:$biblionumber NOT (bib-level:a OR bib-level:b)", + "UseControlNumber enabled without MarcOrgCode" + ); + + my $marc_003_field = MARC::Field->new( '003', 'OSt' ); + $record->append_fields($marc_003_field); + C4::Biblio::ModBiblio( $record, $biblio->biblionumber ); + $biblio = Koha::Biblios->find( $biblio->biblionumber ); + + is( + $biblio->get_volumes_query, + "((rcn:$biblionumber AND cni:OSt) OR rcn:OSt $biblionumber) NOT (bib-level:a OR bib-level:b)", + "UseControlNumber enabled with MarcOrgCode" + ); +}; + subtest 'orders() and active_orders() tests' => sub { plan tests => 5;