@@ -, +, @@ - 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 +++- installer/data/mysql/sysprefs.sql | 5 + installer/data/mysql/updatedatabase.pl | 28 +++++ .../prog/en/modules/admin/preferences/opac.pref | 27 ++++ koha-tmpl/opac-tmpl/bootstrap/css/opac-old.css | 5 +- .../opac-tmpl/bootstrap/en/modules/opac-detail.tt | 25 ++++ .../opac-tmpl/bootstrap/en/modules/opac-results.tt | 21 ++++ .../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 ++- 15 files changed, 496 insertions(+), 63 deletions(-) --- 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::Dates qw/format_date/; @@ -1317,45 +1318,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'; @@ -1366,6 +1366,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'; @@ -1377,26 +1378,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' ) || ''; @@ -1406,34 +1406,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' ) || ''; @@ -1442,12 +1432,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 @@ -157,7 +157,7 @@ sub _get_best_default_xslt_filename { } sub XSLTParse4Display { - my ( $biblionumber, $orig_record, $xslsyspref, $fixamps, $hidden_items ) = @_; + my ( $biblionumber, $orig_record, $xslsyspref, $fixamps, $hidden_items, $variables ) = @_; my $xslfilename = C4::Context->preference($xslsyspref); if ( $xslfilename =~ /^\s*"?default"?\s*$/i ) { my $htdocs; @@ -206,15 +206,31 @@ sub XSLTParse4Display { UseControlNumber IntranetBiblioDefaultView BiblioDefaultView singleBranchMode OPACItemLocation DisplayIconsXSLT AlternateHoldingsField AlternateHoldingsSeparator - TrackClicks opacthemes / ) + TrackClicks opacthemes + OPACShowOpenURL OpenURLResolverURL + OpenURLImageLocation OpenURLText / ) { my $sp = C4::Context->preference( $syspref ); next unless defined($sp); $sysxml .= "$sp\n"; } $sysxml .= "\n"; - $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/sysprefs.sql +++ a/installer/data/mysql/sysprefs.sql @@ -474,4 +474,9 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('XSLTResultsDisplay','default','','Enable XSL stylesheet control over results page display on intranet','Free'), ('z3950AuthorAuthFields','701,702,700',NULL,'Define the MARC biblio fields for Personal Name Authorities to fill biblio.author','free'), ('z3950NormalizeAuthor','0','','If ON, Personal Name Authorities will replace authors in biblio.author','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') ; --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -9759,6 +9759,34 @@ if ( CheckVersion($DBversion) ) { SetVersion ($DBversion); } + +$DBversion = "3.19.00.011"; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES('OpenURLResolverURL', '', 'URL of OpenURL Resolver', NULL, 'Free') + "); + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES('OpenURLText', '', 'Text of OpenURL links (or image title if OpenURLImageLocation is defined)', NULL, 'Free'); + "); + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES('OpenURLImageLocation', '', 'Location of image for OpenURL links', NULL, 'Free'); + "); + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES('OPACShowOpenURL', '', 'Enable display of OpenURL links in OPAC search results and detail page', NULL, 'YesNo'); + "); + $dbh->do(" + INSERT INTO systempreferences (variable,value,explanation,options,type) + VALUES('OPACOpenURLItemTypes', '', 'Show the OpenURL link only for these item types', NULL, 'Free'); + "); + print "Upgrade to $DBversion done (Bug 8995 - Add sysprefs for OpenURL)\n"; + SetVersion($DBversion); +} + + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -316,6 +316,33 @@ OPAC: - pref: OpacCustomSearch type: textarea class: code + - + - '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 + - '
' + - 'It uses biblioitems.itemtype field, so if you map a MARC field to it, and link this MARC field to a list of authorised values (for example CCODE), you can use these values for system preference value.' Features: - - pref: opacuserlogin --- a/koha-tmpl/opac-tmpl/bootstrap/css/opac-old.css +++ a/koha-tmpl/opac-tmpl/bootstrap/css/opac-old.css @@ -1,6 +1,5 @@ @import url("/opac-tmpl/lib/yui/reset-fonts-grids.css"); @import url("/opac-tmpl/lib/yui/skin.css"); - a { font-weight : bold; } @@ -2860,3 +2859,7 @@ padding: 0.1em 0; padding: 3px; text-align: center; } + +a.OpenURL img { + vertical-align: middle; +} --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-detail.tt +++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-detail.tt @@ -352,6 +352,31 @@ [% END # / IF MARCURLS %] + + [% IF (OPACShowOpenURL && OpenURLResolverURL && ocoins) %] + [%# Build OpenURL image location %] + [% IF (OpenURLImageLocation && !OpenURLImageLocation.match('^https?://')) %] + [% openurlimagelocation = "$interface/$theme/images/$OpenURLImageLocation" %] + [% ELSE %] + [% openurlimagelocation = "$OpenURLImageLocation" %] + [% END %] + + + [% OpenURLTarget = '_self' %] + [% IF ( OPACURLOpenInNewWindow ) %] + [% OpenURLTarget = '_blank' %] + [% END %] + + [% IF openurlimagelocation %] + + [% ELSIF OpenURLText %] + [% OpenURLText %] + [% ELSE %] + OpenURL + [% END %] + + + [% END # / IF (OPACShowOpenURL && OpenURLResolverURL && ocoins) %] [% END # / IF OPACXSLTDetailsDisplay %] [% IF ( AuthorisedValueImages && authorised_value_images ) %] --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-results.tt +++ a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-results.tt @@ -167,6 +167,16 @@ + [%# Build OpenURL image location %] + [% IF (OpenURLImageLocation && !OpenURLImageLocation.match('^https?://')) %] + [% openurlimagelocation = "$interface/$theme/images/$OpenURLImageLocation" %] + [% ELSE %] + [% openurlimagelocation = "$OpenURLImageLocation" %] + [% END %] + [% OpenURLTarget = '_self' %] + [% IF ( OPACURLOpenInNewWindow ) %] + [% OpenURLTarget = '_blank' %] + [% END %] [% FOREACH SEARCH_RESULT IN SEARCH_RESULTS %] @@ -318,6 +328,17 @@ [% ELSE %]   [% END %] + [% IF (SEARCH_RESULT.ShowOpenURL && OpenURLResolverURL && SEARCH_RESULT.coins) %] + + [% IF openurlimagelocation %] + + [% ELSIF OpenURLText %] + [% OpenURLText %] + [% ELSE %] + OpenURL + [% END %] + + [% END %] Publication: --- a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl +++ a/koha-tmpl/opac-tmpl/bootstrap/en/xslt/MARC21slim2OPACDetail.xsl @@ -1034,6 +1034,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 @@ -448,8 +448,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 @@ -82,6 +82,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 @@ -2464,4 +2464,8 @@ a.reviewlink:visited { padding-left:20px; } +a.OpenURL img { + vertical-align: middle; +} + @import "responsive.less"; --- a/opac/opac-detail.pl +++ a/opac/opac-detail.pl @@ -1133,4 +1133,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 @@ -519,6 +519,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')); @@ -601,7 +613,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); } --