20fd03724a
This patch adds a syspref UseICU for toggling between using "" and {} for quoting in subject tracings. With normal Zebra indexing, "" must be used. With ICU Zebra indexing, {} must be used. This syspref interacts with TraceCompleteSubfields and TraceSubjectSubdivisions. To test: - marcflavour = MARC21 - make sure you have a record with a "complex subject", like "Internet -- Law and legislation" Toggle UseICU, TraceCompleteSubfields, and TraceSubjectSubdivisions and check that you get the expected results for the clickable links in the OPAC detail view: TraceCompleteSubfields = Don't force TraceSubjectSubdivisions = Don't include UseICU = Not using opac-search.pl?q=su:"Internet" UseICU = Using opac-search.pl?q=su:{Internet} TraceCompleteSubfields = Force TraceSubjectSubdivisions = Don't include UseICU = Not using opac-search.pl?q=su,complete-subfield:"Internet" UseICU = Using opac-search.pl?q=su,complete-subfield:{Internet} TraceCompleteSubfields = Don't force TraceSubjectSubdivisions = Include UsingICU = Not using opac-search.pl?q=(su:"Internet") and (su:"Law and legislation.") UsingICU = Using opac-search.pl?q=(su:{Internet}) and (su:{Law and legislation.}) TraceCompleteSubfields = Force TraceSubjectSubdivisions = Include UseICU = Not using opac-search.pl?q=(su,complete-subfield:"Internet") and (su,complete-subfield:"Law and legislation.") UseICU = Using opac-search.pl?q=(su,complete-subfield:{Internet}) and (su,complete-subfield:{Law and legislation.}) Check that clicking on the generated links gives the expected search results, but with normal and ICU indexing. (I have actually not tested this with ICU, so doing that before signing off is crucial.) UPDATE 2012-03-16: Changed the name of the syspref from TracingQuotes to UseICU after a suggestion from Paul P., to make it more generally useful. I have used "Using/Not using" instead of "Use/Don't use" in the description of the syspref, to reflect the fact that this syspref will not change how Zebra does its indexing - it's just a way of telling Koha how the indexing is actually done. I have also set UseICU = 1 in updatedatabase.pl, since that will preserve the current behaviour of Koha, but UseICU = 0 in sysprefs.sql, since most new installations will not have ICU activated. Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
254 lines
8.7 KiB
Perl
254 lines
8.7 KiB
Perl
package C4::XSLT;
|
|
# Copyright (C) 2006 LibLime
|
|
# <jmf at liblime dot com>
|
|
# Parts Copyright Katrin Fischer 2011
|
|
# Parts Copyright ByWater Solutions 2011
|
|
#
|
|
# This file is part of Koha.
|
|
#
|
|
# Koha is free software; you can redistribute it and/or modify it under the
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
# Foundation; either version 2 of the License, or (at your option) any later
|
|
# version.
|
|
#
|
|
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License along
|
|
# with Koha; if not, write to the Free Software Foundation, Inc.,
|
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use C4::Context;
|
|
use C4::Branch;
|
|
use C4::Items;
|
|
use C4::Koha;
|
|
use C4::Biblio;
|
|
use C4::Circulation;
|
|
use C4::Reserves;
|
|
use Encode;
|
|
use XML::LibXML;
|
|
use XML::LibXSLT;
|
|
|
|
use vars qw($VERSION @ISA @EXPORT);
|
|
|
|
BEGIN {
|
|
require Exporter;
|
|
$VERSION = 0.03;
|
|
@ISA = qw(Exporter);
|
|
@EXPORT = qw(
|
|
&XSLTParse4Display
|
|
);
|
|
}
|
|
|
|
=head1 NAME
|
|
|
|
C4::XSLT - Functions for displaying XSLT-generated content
|
|
|
|
=head1 FUNCTIONS
|
|
|
|
=head2 transformMARCXML4XSLT
|
|
|
|
Replaces codes with authorized values in a MARC::Record object
|
|
|
|
=cut
|
|
|
|
sub transformMARCXML4XSLT {
|
|
my ($biblionumber, $record) = @_;
|
|
my $frameworkcode = GetFrameworkCode($biblionumber) || '';
|
|
my $tagslib = &GetMarcStructure(1,$frameworkcode);
|
|
my @fields;
|
|
# FIXME: wish there was a better way to handle exceptions
|
|
eval {
|
|
@fields = $record->fields();
|
|
};
|
|
if ($@) { warn "PROBLEM WITH RECORD"; next; }
|
|
my $av = getAuthorisedValues4MARCSubfields($frameworkcode);
|
|
foreach my $tag ( keys %$av ) {
|
|
foreach my $field ( $record->field( $tag ) ) {
|
|
if ( $av->{ $tag } ) {
|
|
my @new_subfields = ();
|
|
for my $subfield ( $field->subfields() ) {
|
|
my ( $letter, $value ) = @$subfield;
|
|
$value = GetAuthorisedValueDesc( $tag, $letter, $value, '', $tagslib )
|
|
if $av->{ $tag }->{ $letter };
|
|
push( @new_subfields, $letter, $value );
|
|
}
|
|
$field ->replace_with( MARC::Field->new(
|
|
$tag,
|
|
$field->indicator(1),
|
|
$field->indicator(2),
|
|
@new_subfields
|
|
) );
|
|
}
|
|
}
|
|
}
|
|
return $record;
|
|
}
|
|
|
|
=head2 getAuthorisedValues4MARCSubfields
|
|
|
|
Returns a ref of hash of ref of hash for tag -> letter controled by authorised values
|
|
|
|
=cut
|
|
|
|
# Cache for tagfield-tagsubfield to decode per framework.
|
|
# Should be preferably be placed in Koha-core...
|
|
my %authval_per_framework;
|
|
|
|
sub getAuthorisedValues4MARCSubfields {
|
|
my ($frameworkcode) = @_;
|
|
unless ( $authval_per_framework{ $frameworkcode } ) {
|
|
my $dbh = C4::Context->dbh;
|
|
my $sth = $dbh->prepare("SELECT DISTINCT tagfield, tagsubfield
|
|
FROM marc_subfield_structure
|
|
WHERE authorised_value IS NOT NULL
|
|
AND authorised_value!=''
|
|
AND frameworkcode=?");
|
|
$sth->execute( $frameworkcode );
|
|
my $av = { };
|
|
while ( my ( $tag, $letter ) = $sth->fetchrow() ) {
|
|
$av->{ $tag }->{ $letter } = 1;
|
|
}
|
|
$authval_per_framework{ $frameworkcode } = $av;
|
|
}
|
|
return $authval_per_framework{ $frameworkcode };
|
|
}
|
|
|
|
my $stylesheet;
|
|
|
|
sub XSLTParse4Display {
|
|
my ( $biblionumber, $orig_record, $xsl_suffix, $interface, $fixamps, $hidden_items ) = @_;
|
|
$interface = 'opac' unless $interface;
|
|
# grab the XML, run it through our stylesheet, push it out to the browser
|
|
my $record = transformMARCXML4XSLT($biblionumber, $orig_record);
|
|
#return $record->as_formatted();
|
|
my $itemsxml = buildKohaItemsNamespace($biblionumber, $hidden_items);
|
|
my $xmlrecord = $record->as_xml(C4::Context->preference('marcflavour'));
|
|
my $sysxml = "<sysprefs>\n";
|
|
foreach my $syspref ( qw/ hidelostitems OPACURLOpenInNewWindow
|
|
DisplayOPACiconsXSLT URLLinkText viewISBD
|
|
OPACBaseURL TraceCompleteSubfields UseICU
|
|
UseAuthoritiesForTracings TraceSubjectSubdivisions
|
|
Display856uAsImage OPACDisplay856uAsImage
|
|
UseControlNumber
|
|
AlternateHoldingsField AlternateHoldingsSeparator / )
|
|
{
|
|
my $sp = C4::Context->preference( $syspref );
|
|
next unless defined($sp);
|
|
$sysxml .= "<syspref name=\"$syspref\">$sp</syspref>\n";
|
|
}
|
|
$sysxml .= "</sysprefs>\n";
|
|
$xmlrecord =~ s/\<\/record\>/$itemsxml$sysxml\<\/record\>/;
|
|
if ($fixamps) { # We need to correct the ampersand entities that Zebra outputs
|
|
$xmlrecord =~ s/\&amp;/\&/g;
|
|
}
|
|
$xmlrecord =~ s/\& /\&\; /;
|
|
$xmlrecord =~ s/\&\;amp\; /\&\; /;
|
|
|
|
my $parser = XML::LibXML->new();
|
|
# don't die when you find &, >, etc
|
|
$parser->recover_silently(0);
|
|
my $source = $parser->parse_string($xmlrecord);
|
|
unless ( $stylesheet ) {
|
|
my $xslt = XML::LibXSLT->new();
|
|
my $xslfile;
|
|
if ($interface eq 'intranet') {
|
|
$xslfile = C4::Context->config('intrahtdocs') .
|
|
'/' . C4::Context->preference("template") .
|
|
'/' . C4::Templates::_current_language() .
|
|
'/xslt/' .
|
|
C4::Context->preference('marcflavour') .
|
|
"slim2intranet$xsl_suffix.xsl";
|
|
} else {
|
|
$xslfile = C4::Context->config('opachtdocs') .
|
|
'/' . C4::Context->preference("opacthemes") .
|
|
'/' . C4::Templates::_current_language() .
|
|
'/xslt/' .
|
|
C4::Context->preference('marcflavour') .
|
|
"slim2OPAC$xsl_suffix.xsl";
|
|
}
|
|
my $style_doc = $parser->parse_file($xslfile);
|
|
$stylesheet = $xslt->parse_stylesheet($style_doc);
|
|
}
|
|
my $results = $stylesheet->transform($source);
|
|
my $newxmlrecord = $stylesheet->output_string($results);
|
|
return $newxmlrecord;
|
|
}
|
|
|
|
sub buildKohaItemsNamespace {
|
|
my ($biblionumber, $hidden_items) = @_;
|
|
|
|
my @items = C4::Items::GetItemsInfo($biblionumber);
|
|
if ($hidden_items && @$hidden_items) {
|
|
my %hi = map {$_ => 1} @$hidden_items;
|
|
@items = grep { !$hi{$_->{itemnumber}} } @items;
|
|
}
|
|
my $branches = GetBranches();
|
|
my $itemtypes = GetItemTypes();
|
|
my $xml = '';
|
|
for my $item (@items) {
|
|
my $status;
|
|
|
|
my ( $transfertwhen, $transfertfrom, $transfertto ) = C4::Circulation::GetTransfers($item->{itemnumber});
|
|
|
|
my ( $reservestatus, $reserveitem, undef ) = C4::Reserves::CheckReserves($item->{itemnumber});
|
|
|
|
if ( $itemtypes->{ $item->{itype} }->{notforloan} || $item->{notforloan} || $item->{onloan} || $item->{wthdrawn} || $item->{itemlost} || $item->{damaged} ||
|
|
(defined $transfertwhen && $transfertwhen ne '') || $item->{itemnotforloan} || (defined $reservestatus && $reservestatus eq "Waiting") ){
|
|
if ( $item->{notforloan} < 0) {
|
|
$status = "On order";
|
|
}
|
|
if ( $item->{itemnotforloan} > 0 || $item->{notforloan} > 0 || $itemtypes->{ $item->{itype} }->{notforloan} == 1 ) {
|
|
$status = "reference";
|
|
}
|
|
if ($item->{onloan}) {
|
|
$status = "Checked out";
|
|
}
|
|
if ( $item->{wthdrawn}) {
|
|
$status = "Withdrawn";
|
|
}
|
|
if ($item->{itemlost}) {
|
|
$status = "Lost";
|
|
}
|
|
if ($item->{damaged}) {
|
|
$status = "Damaged";
|
|
}
|
|
if (defined $transfertwhen && $transfertwhen ne '') {
|
|
$status = 'In transit';
|
|
}
|
|
if (defined $reservestatus && $reservestatus eq "Waiting") {
|
|
$status = 'Waiting';
|
|
}
|
|
} else {
|
|
$status = "available";
|
|
}
|
|
my $homebranch = $item->{homebranch}? xml_escape($branches->{$item->{homebranch}}->{'branchname'}):'';
|
|
my $itemcallnumber = xml_escape($item->{itemcallnumber});
|
|
$xml.= "<item><homebranch>$homebranch</homebranch>".
|
|
"<status>$status</status>".
|
|
"<itemcallnumber>".$itemcallnumber."</itemcallnumber>"
|
|
. "</item>";
|
|
|
|
}
|
|
$xml = "<items xmlns=\"http://www.koha-community.org/items\">".$xml."</items>";
|
|
return $xml;
|
|
}
|
|
|
|
|
|
|
|
1;
|
|
__END__
|
|
|
|
=head1 NOTES
|
|
|
|
=cut
|
|
|
|
=head1 AUTHOR
|
|
|
|
Joshua Ferraro <jmf@liblime.com>
|
|
|
|
=cut
|