@@ -, +, @@ - OpenURLinOPACResults: enable or disable this feature - OpenURLResolverURL: url of the openURL resolver - OpenURLText: text of the link - OpenURLImageLocation: image of the link - Title should be in rft.jtitle instead of rft.title - rft.date, rft.aulast, rft.aufirst, rft.au, rft.pub and rft.pages have no meaning for a subscription, so they are simply removed from URL $var .= "&$value" --- C4/Biblio.pm | 129 ++++++++++++--------- C4/XSLT.pm | 24 +++- .../mysql/atomicupdate/8995_OpenURL_sysprefs.sql | 6 + installer/data/mysql/sysprefs.sql | 5 + .../prog/en/modules/admin/preferences/opac.pref | 27 +++++ .../bootstrap/en/xslt/MARC21slim2OPACDetail.xsl | 64 ++++++++++ .../bootstrap/en/xslt/MARC21slim2OPACResults.xsl | 66 ++++++++++- .../bootstrap/en/xslt/UNIMARCslim2OPACDetail.xsl | 65 +++++++++++ .../bootstrap/en/xslt/UNIMARCslim2OPACResults.xsl | 64 ++++++++++ koha-tmpl/opac-tmpl/bootstrap/less/opac.less | 4 + opac/opac-detail.pl | 14 +++ opac/opac-search.pl | 18 ++- 12 files changed, 424 insertions(+), 62 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/8995_OpenURL_sysprefs.sql --- a/C4/Biblio.pm +++ a/C4/Biblio.pm @@ -29,6 +29,7 @@ use MARC::File::USMARC; use MARC::File::XML; use POSIX qw(strftime); use Module::Load::Conditional qw(can_load); +use URI::Escape; # GetCOinSBiblio use C4::Koha; use C4::Log; # logaction @@ -1385,45 +1386,44 @@ sub GetCOinSBiblio { carp 'GetCOinSBiblio called with undefined record'; return; } + my $pos7 = substr $record->leader(), 7, 1; my $pos6 = substr $record->leader(), 6, 1; my $mtx; my $genre; my ( $aulast, $aufirst ) = ( '', '' ); - my $oauthors = ''; - my $title = ''; - my $subtitle = ''; + my @authors; + my $title; + my $hosttitle; my $pubyear = ''; my $isbn = ''; my $issn = ''; my $publisher = ''; my $pages = ''; - my $titletype = 'b'; + my $titletype = ''; # For the purposes of generating COinS metadata, LDR/06-07 can be # considered the same for UNIMARC and MARC21 - my $fmts6; - my $fmts7; - %$fmts6 = ( - 'a' => 'book', - 'b' => 'manuscript', - 'c' => 'book', - 'd' => 'manuscript', - 'e' => 'map', - 'f' => 'map', - 'g' => 'film', - 'i' => 'audioRecording', - 'j' => 'audioRecording', - 'k' => 'artwork', - 'l' => 'document', - 'm' => 'computerProgram', - 'o' => 'document', - 'r' => 'document', - ); - %$fmts7 = ( - 'a' => 'journalArticle', - 's' => 'journal', - ); + my $fmts6 = { + 'a' => 'book', + 'b' => 'manuscript', + 'c' => 'book', + 'd' => 'manuscript', + 'e' => 'map', + 'f' => 'map', + 'g' => 'film', + 'i' => 'audioRecording', + 'j' => 'audioRecording', + 'k' => 'artwork', + 'l' => 'document', + 'm' => 'computerProgram', + 'o' => 'document', + 'r' => 'document', + }; + my $fmts7 = { + 'a' => 'journalArticle', + 's' => 'journal', + }; $genre = $fmts6->{$pos6} ? $fmts6->{$pos6} : 'book'; @@ -1434,6 +1434,7 @@ sub GetCOinSBiblio { ##### We must transform mtx to a valable mtx and document type #### if ( $genre eq 'book' ) { $mtx = 'book'; + $titletype = 'b'; } elsif ( $genre eq 'journal' ) { $mtx = 'journal'; $titletype = 'j'; @@ -1445,26 +1446,25 @@ sub GetCOinSBiblio { $mtx = 'dc'; } - $genre = ( $mtx eq 'dc' ) ? "&rft.type=$genre" : "&rft.genre=$genre"; - if ( C4::Context->preference("marcflavour") eq "UNIMARC" ) { # Setting datas $aulast = $record->subfield( '700', 'a' ) || ''; $aufirst = $record->subfield( '700', 'b' ) || ''; - $oauthors = "&rft.au=$aufirst $aulast"; + push @authors, "$aufirst $aulast" if ($aufirst or $aulast); # others authors if ( $record->field('200') ) { for my $au ( $record->field('200')->subfield('g') ) { - $oauthors .= "&rft.au=$au"; + push @authors, $au; } } - $title = - ( $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' ) || ''; + + $title = $record->subfield( '200', 'a' ); + my $subfield_210d = $record->subfield('210', 'd'); + if ($subfield_210d and $subfield_210d =~ /(\d{4})/) { + $pubyear = $1; + } $publisher = $record->subfield( '210', 'c' ) || ''; $isbn = $record->subfield( '010', 'a' ) || ''; $issn = $record->subfield( '011', 'a' ) || ''; @@ -1474,34 +1474,24 @@ sub GetCOinSBiblio { # Setting datas if ( $record->field('100') ) { - $oauthors .= "&rft.au=" . $record->subfield( '100', 'a' ); + push @authors, $record->subfield( '100', 'a' ); } # others authors if ( $record->field('700') ) { for my $au ( $record->field('700')->subfield('a') ) { - $oauthors .= "&rft.au=$au"; + push @authors, $au; } } - $title = "&rft." . $titletype . "title=" . $record->subfield( '245', 'a' ); - $subtitle = $record->subfield( '245', 'b' ) || ''; - $title .= $subtitle; + $title = $record->subfield( '245', 'a' ) . $record->subfield( '245', 'b' ); if ($titletype eq 'a') { $pubyear = $record->field('008') || ''; $pubyear = substr($pubyear->data(), 7, 4) if $pubyear; $isbn = $record->subfield( '773', 'z' ) || ''; $issn = $record->subfield( '773', 'x' ) || ''; - if ($mtx eq 'journal') { - $title .= "&rft.title=" . (($record->subfield( '773', 't' ) || $record->subfield( '773', 'a'))); - } else { - $title .= "&rft.btitle=" . (($record->subfield( '773', 't' ) || $record->subfield( '773', 'a')) || ''); - } - foreach my $rel ($record->subfield( '773', 'g' )) { - if ($pages) { - $pages .= ', '; - } - $pages .= $rel; - } + $hosttitle = $record->subfield( '773', 't' ) || $record->subfield( '773', 'a'); + my @rels = $record->subfield( '773', 'g' ); + $pages = join(', ', @rels); } else { $pubyear = $record->subfield( '260', 'c' ) || ''; $publisher = $record->subfield( '260', 'b' ) || ''; @@ -1510,12 +1500,39 @@ sub GetCOinSBiblio { } } - my $coins_value = -"ctx_ver=Z39.88-2004&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3A$mtx$genre$title&rft.isbn=$isbn&rft.issn=$issn&rft.aulast=$aulast&rft.aufirst=$aufirst$oauthors&rft.pub=$publisher&rft.date=$pubyear&rft.pages=$pages"; - $coins_value =~ s/(\ |&[^a])/\+/g; - $coins_value =~ s/\"/\"\;/g; -#&rft.au=&rft.btitle=&rft.date=&rft.pages=&rft.isbn=&rft.aucorp=&rft.place=&rft.pub=&rft.edition=&rft.series=&rft.genre=" + my @params = ( + [ 'ctx_ver', 'Z39.88-2004' ], + [ 'rft_val_fmt', "info:ofi/fmt:kev:mtx:$mtx" ], + [ ($mtx eq 'dc' ? 'rft.type' : 'rft.genre'), $genre ], + [ "rft.${titletype}title", $title ], + ); + + # rft.title is authorized only once, so by checking $titletype + # we ensure that rft.title is not already in the list. + if ($hosttitle and $titletype) { + push @params, [ 'rft.title', $hosttitle ]; + } + + push @params, ( + [ 'rft.isbn', $isbn ], + [ 'rft.issn', $issn ], + ); + + # If it's a subscription, these informations have no meaning. + if ($genre ne 'journal') { + push @params, ( + [ 'rft.aulast', $aulast ], + [ 'rft.aufirst', $aufirst ], + (map { [ 'rft.au', $_ ] } @authors), + [ 'rft.pub', $publisher ], + [ 'rft.date', $pubyear ], + [ 'rft.pages', $pages ], + ); + } + + my $coins_value = join( '&', + map { $$_[1] ? $$_[0] . '=' . uri_escape_utf8( $$_[1] ) : () } @params ); return $coins_value; } --- a/C4/XSLT.pm +++ a/C4/XSLT.pm @@ -171,7 +171,9 @@ sub get_xslt_sysprefs { OPACItemLocation DisplayIconsXSLT AlternateHoldingsField AlternateHoldingsSeparator TrackClicks opacthemes IdRef OpacSuppression - OPACResultsLibrary / ) + OPACResultsLibrary OPACShowOpenURL + OpenURLResolverURL OpenURLImageLocation + OpenURLText / ) { my $sp = C4::Context->preference( $syspref ); next unless defined($sp); @@ -188,7 +190,7 @@ sub get_xslt_sysprefs { } sub XSLTParse4Display { - my ( $biblionumber, $orig_record, $xslsyspref, $fixamps, $hidden_items, $sysxml, $xslfilename, $lang ) = @_; + my ( $biblionumber, $orig_record, $xslsyspref, $fixamps, $hidden_items, $sysxml, $xslfilename, $lang, $variables ) = @_; $sysxml ||= C4::Context->preference($xslsyspref); $xslfilename ||= C4::Context->preference($xslsyspref); @@ -243,8 +245,22 @@ sub XSLTParse4Display { my $itemsxml = buildKohaItemsNamespace($biblionumber, $hidden_items); my $xmlrecord = $record->as_xml(C4::Context->preference('marcflavour')); - $xmlrecord =~ s/\<\/record\>/$itemsxml$sysxml\<\/record\>/; - if ($fixamps) { # We need to correct the HTML entities that Zebra outputs + $variables ||= {}; + if (C4::Context->preference('OPACShowOpenURL')) { + my ($biblio) = GetBiblioItemByBiblioNumber($biblionumber); + my @itypes = split( /\s/, C4::Context->preference('OPACOpenURLItemTypes') ); + if (grep /^$biblio->{itemtype}$/, @itypes) { + $variables->{COinS} = C4::Biblio::GetCOinSBiblio($orig_record); + } + } + my $varxml = "\n"; + while (my ($key, $value) = each %$variables) { + $varxml .= "$value\n"; + } + $varxml .= "\n"; + + $xmlrecord =~ s/\<\/record\>/$itemsxml$sysxml$varxml\<\/record\>/; + if ($fixamps) { # We need to correct the ampersand entities that Zebra outputs $xmlrecord =~ s/\&amp;/\&/g; $xmlrecord =~ s/\&\;lt\;/\<\;/g; $xmlrecord =~ s/\&\;gt\;/\>\;/g; --- a/installer/data/mysql/atomicupdate/8995_OpenURL_sysprefs.sql +++ a/installer/data/mysql/atomicupdate/8995_OpenURL_sysprefs.sql @@ -0,0 +1,6 @@ +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES + ('OpenURLResolverURL', '', 'URL of OpenURL Resolver', NULL, 'Free'), + ('OpenURLText', '', 'Text of OpenURL links (or image title if OpenURLImageLocation is defined)', NULL, 'Free'), + ('OpenURLImageLocation', '', 'Location of image for OpenURL links', NULL, 'Free'), + ('OPACShowOpenURL', '', 'Enable display of OpenURL links in OPAC search results and detail page', NULL, 'YesNo'), + ('OPACOpenURLItemTypes', '', 'Show the OpenURL link only for these item types', NULL, 'Free'); --- a/installer/data/mysql/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -371,6 +371,11 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('OPACXSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on OPAC','Free'), ('OpenLibraryCovers','0',NULL,'If ON Openlibrary book covers will be show','YesNo'), ('OpenLibrarySearch','0',NULL,'If Yes Open Library search results will show in OPAC','YesNo'), +('OpenURLResolverURL', '', NULL, 'URL of OpenURL Resolver', 'Free'), +('OpenURLText', '', NULL, 'Text of OpenURL links (or image title if OpenURLImageLocation is defined)', 'Free'), +('OpenURLImageLocation', '', NULL, 'Location of image for OpenURL links', 'Free'), +('OPACShowOpenURL', '', NULL, 'Enable display of OpenURL links in OPAC search results and detail page', 'YesNo'), +('OPACOpenURLItemTypes', '', NULL, 'Show the OpenURL link only for these item types', 'Free'), ('OrderPdfFormat','pdfformat::layout3pages','Controls what script is used for printing (basketgroups)','','free'), ('OverDriveClientKey','','Client key for OverDrive integration','30','Free'), ('OverDriveClientSecret','','Client key for OverDrive integration','30','YesNo'), --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -500,6 +500,33 @@ OPAC: - pref: OPACISBD type: textarea class: code + OpenURL: + - + - 'Complete URL of OpenURL resolver (starting with http:// or https://):' + - pref: OpenURLResolverURL + class: url + - + - 'Text of OpenURL links (or image title if OpenURLImageLocation is defined):' + - pref: OpenURLText + - + - 'Location of image for OpenURL links:' + - pref: OpenURLImageLocation + class: url + - '
Can be a complete URL starting with http:// or' + - 'https:// or the name of a file in images directory' + - '
Examples:' + - '
- http://www.example.com/img/openurl.png' + - '
- OpenURL/OpenURL.png (file is in opac-tmpl/<opacthemes>/images/OpenURL/OpenURL.png)' + - + - pref: OPACShowOpenURL + choices: + yes: Enable + no: Disable + - 'display of OpenURL link in OPAC search results and detail page.' + - + - 'List of item type codes (separated by spaces) for those you want to show the OpenURL link:' + - pref: OPACOpenURLItemTypes + - '
' Policy: - - pref: SearchMyLibraryFirst --- a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl +++ a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl @@ -1229,6 +1229,70 @@ + + + + + + + + + + + + + + + OpenURL + + + + + + + + + + + /opac-tmpl/prog/images/ + + + + + + + + + ? + + + + + + + OpenURL + + + + _blank + + + + + + + + + + + + + + + + + + --- a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACResults.xsl +++ a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACResults.xsl @@ -443,8 +443,72 @@ -

+ + + + + + + + + + + + + + + OpenURL + + + + + + + + + + + /opac-tmpl/prog/images/ + + + + + + + + + ? + + + + + + + OpenURL + + + + _blank + + + + + + + + + + + + + + + + + + +

--- a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/UNIMARCslim2OPACDetail.xsl +++ a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/UNIMARCslim2OPACDetail.xsl @@ -442,6 +442,71 @@ + + + + + + + + + + + + + + + + OpenURL + + + + + + + + + + + /opac-tmpl/prog/images/ + + + + + + + + + ? + + + + + + + OpenURL + + + + _blank + + + + + + + + + + + + + + + + + + --- a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/UNIMARCslim2OPACResults.xsl +++ a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/UNIMARCslim2OPACResults.xsl @@ -84,6 +84,70 @@ + + + + + + + + + + + + + + + OpenURL + + + + + + + + + + + /opac-tmpl/prog/images/ + + + + + + + + + ? + + + + + + + OpenURL + + + + _blank + + + + + + + + + + + + + + + + + + 454 Translation of --- a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less +++ a/koha-tmpl/opac-tmpl/bootstrap/less/opac.less @@ -2503,4 +2503,8 @@ a.reviewlink:visited { cursor: pointer; } +a.OpenURL img { + vertical-align: middle; +} + @import "responsive.less"; --- a/opac/opac-detail.pl +++ a/opac/opac-detail.pl @@ -1155,4 +1155,18 @@ $template->param( 'OpacLocationBranchToDisplayShelving' => C4::Context->preference('OpacLocationBranchToDisplayShelving'), ); +# OpenURL +if (C4::Context->preference('OPACShowOpenURL')) { + my ($biblio) = GetBiblioItemByBiblioNumber($biblionumber); + my @itypes = split( /\s/, C4::Context->preference('OPACOpenURLItemTypes') ); + if (grep /^$biblio->{itemtype}$/, @itypes) { + $template->param( + OPACShowOpenURL => 1, + OpenURLResolverURL => C4::Context->preference('OpenURLResolverURL'), + OpenURLText => C4::Context->preference('OpenURLText'), + OpenURLImageLocation => C4::Context->preference('OpenURLImageLocation') + ); + } +} + output_html_with_http_headers $query, $cookie, $template->output; --- a/opac/opac-search.pl +++ a/opac/opac-search.pl @@ -586,6 +586,18 @@ if (C4::Context->preference('OpacSuppression')) { } } +# OpenURL +my @OpenURL_itypes; +if (C4::Context->preference('OPACShowOpenURL')) { + @OpenURL_itypes = split( /\s/, C4::Context->preference('OPACOpenURLItemTypes') ); + $template->param( + OPACShowOpenURL => 1, + OpenURLResolverURL => C4::Context->preference('OpenURLResolverURL'), + OpenURLText => C4::Context->preference('OpenURLText'), + OpenURLImageLocation => C4::Context->preference('OpenURLImageLocation') + ); +} + $template->param ( LIMIT_INPUTS => \@limit_inputs ); $template->param ( OPACResultsSidebar => C4::Context->preference('OPACResultsSidebar')); @@ -661,7 +673,11 @@ for (my $i=0;$i<@servers;$i++) { $res->{'incart'} = 1; } - if (C4::Context->preference('COinSinOPACResults')) { + if (C4::Context->preference('COinSinOPACResults') + or C4::Context->preference('OPACShowOpenURL')) { + if (grep /^$res->{itemtype}$/, @OpenURL_itypes) { + $res->{ShowOpenURL} = 1; + } my $record = GetMarcBiblio($res->{'biblionumber'}); $res->{coins} = GetCOinSBiblio($record); } --