Bug 33697: Remove RecordedBooks (rbdigital) integration

RecordedBooks search API integration is now obsolete following
rbdigital's incorporation into OverDrive. Associated code should be
removed.

https://company.overdrive.com/2020/06/23/overdrive-to-acquire-rbdigital-from-rbmedia/

Test plan:
use git grep extensively and confirm that this patch removes all
occurrences of this feature.

Signed-off-by: Owen Leonard <oleonard@myacpl.org>

Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
Jonathan Druart 2023-05-16 10:18:13 +02:00 committed by Tomas Cohen Arazi
parent 229b6b58ef
commit 8b9355088a
Signed by: tomascohen
GPG key ID: 0A272EA1B2F3C15F
15 changed files with 16 additions and 960 deletions

View file

@ -1,119 +0,0 @@
# Copyright 2016 Catalyst
#
# 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 3 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, see <http://www.gnu.org/licenses>.
package Koha::ExternalContent::RecordedBooks;
use Modern::Perl;
use Carp qw( croak );
use base qw(Koha::ExternalContent);
use WebService::ILS::RecordedBooks::PartnerPatron;
use WebService::ILS::RecordedBooks::Partner;
use C4::Context;
__PACKAGE__->mk_accessors(qw(domain is_identified));
=head1 NAME
Koha::ExternalContent::RecordedBooks
=head1 SYNOPSIS
use Koha::ExternalContent::RecordedBooks;
my $rb_client = Koha::ExternalContent::RecordedBooks->new();
my $rb_auth_url = $od_client->auth_url();
=head1 DESCRIPTION
A (very) thin wrapper around C<WebService::ILS::RecordedBooks::Patron>
Takes "RecordedBooks*" Koha preferences
=cut
=head2 Class Methods
=cut
=head3 new
my $rb_client = Koha::ExternalContent::RecordedBooks->new();
Create the object for interacting with RecordedBooks
=cut
sub new {
my $class = shift;
my $params = shift || {};
my $self = $class->SUPER::new($params);
unless ($params->{client}) {
my $client_secret = C4::Context->preference('RecordedBooksClientSecret')
or croak("RecordedBooksClientSecret pref not set");
my $library_id = C4::Context->preference('RecordedBooksLibraryID')
or croak("RecordedBooksLibraryID pref not set");
my $domain = C4::Context->preference('RecordedBooksDomain');
my $patron = $params->{koha_session_id} ? $self->koha_patron : undef;
my $email;
if ($patron) {
$email = $patron->email
or $self->logger->warn("User with no email, cannot identify with RecordedBooks");
}
my $client;
if ($email) {
local $@;
$client = eval { WebService::ILS::RecordedBooks::PartnerPatron->new(
client_secret => $client_secret,
library_id => $library_id,
domain => $domain,
user_id => $email,
) };
$self->logger->warn("Invalid RecordedBooks user $email ($@)") if $@;
$self->is_identified($client);
}
$client ||= WebService::ILS::RecordedBooks::Partner->new(
client_secret => $client_secret,
library_id => $library_id,
domain => $domain,
);
$self->client( $client );
}
return $self;
}
=head1 METHODS
L<WebService::ILS::RecordedBooks::PartnerPatron> methods used without mods:
=over 4
=item C<error_message()>
=back
=cut
use vars qw{$AUTOLOAD};
sub AUTOLOAD {
my $self = shift;
(my $method = $AUTOLOAD) =~ s/.*:://;
return $self->client->$method(@_);
}
sub DESTROY { }
1;

View file

@ -0,0 +1,16 @@
use Modern::Perl;
return {
bug_number => "33697",
description => "Remove RecordedBooks (rbdigital) integration",
up => sub {
my ($args) = @_;
my ($dbh, $out) = @$args{qw(dbh out)};
for my $pref_name ( qw( RecordedBooksClientSecret RecordedBooksDomain RecordedBooksLibraryID ) ) {
$dbh->do(q{
DELETE FROM systempreferences
WHERE variable=?
}, undef, $pref_name) == 1 && say $out "Removed system preference '$pref_name'";
}
},
};

View file

@ -303,9 +303,6 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, `
('IndependentBranchesTransfers','0', NULL, 'Allow non-superlibrarians to transfer items between libraries','YesNo'),
('IntranetAddMastheadLibraryPulldown','0', NULL, 'Add a library select pulldown menu on the staff header search','YesNo'),
('IntranetCatalogSearchPulldown','0', NULL, 'Show a search field pulldown for \"Search the catalog\" boxes','YesNo'),
('RecordedBooksClientSecret','','30','Client key for RecordedBooks integration','Free'),
('RecordedBooksDomain','','','RecordedBooks domain','Free'),
('RecordedBooksLibraryID','','','Library ID for RecordedBooks integration','Integer'),
('OnSiteCheckouts','0','','Enable/Disable the on-site checkouts feature','YesNo'),
('OnSiteCheckoutsForce','0','','Enable/Disable the on-site for all cases (Even if a user is debarred, etc.)','YesNo'),
('OnSiteCheckoutAutoCheck','0','','Enable/Do not enable onsite checkout by default if last checkout was an onsite checkout','YesNo'),

View file

@ -377,18 +377,6 @@ Enhanced content:
- for user access to OverDrive. <br />
- If you enable access you must have a SIP connection registered with
- OverDrive for patron authentication against Koha
RecordedBooks:
-
- Include RecordedBooks availability information with the client secret
- pref: RecordedBooksClientSecret
- .
-
- Show items from the RecordedBooks catalog of library ID
- pref: RecordedBooksLibraryID
- .
-
- RecordedBooks domain
- pref: RecordedBooksDomain
Coce cover images cache:
-
- pref: OpacCoce

View file

@ -2276,7 +2276,6 @@ nav {
}
#overdrive-results,
#recordedbooks-results,
#openlibrary-results {
font-weight: bold;
padding-left: 1em;

View file

@ -272,12 +272,6 @@
</script>
[% END %]
[% IF Koha.Preference('RecordedBooksClientSecret') && Koha.Preference('RecordedBooksLibraryID') %]
<script>
var SPINNER_THROBBER = "[% interface | html %]/[% theme | html %]/images/spinner-small.gif";
</script>
[% END %]
[% Asset.js("lib/js-cookie/js.cookie-3.0.1.min.js") | $raw %]
<script>
$(document).ready(function() {

View file

@ -1,15 +0,0 @@
<div id="recordedbooks-checkout" class="modal" tabindex="-1" role="dialog" aria-labelledby="recordedbooks-checkout-label" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="recordedbooks-checkout-label">Checkout</h3>
</div>
<form action="#" method="post" id="recordedbooks-checkout-form">
<div class="modal-body">
<input type="hidden" name="id" value="" />
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-default recordedbooks-checkout-submit" value="Checkout" />
<a href="#" data-dismiss="modal" aria-hidden="true" class="cancel">Cancel</a>
</div>
</form> <!-- /#recordedbooks-checkout-form -->
</div> <!-- /#recordedbooks-checkout -->

View file

@ -1,178 +0,0 @@
[% USE raw %]
[% USE Asset %]
[% USE Koha %]
[% USE AdditionalContents %]
[% SET OpacNav = AdditionalContents.get( location => "OpacNav", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
[% SET OpacNavBottom = AdditionalContents.get( location => "OpacNavBottom", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
[% INCLUDE 'doc-head-open.inc' %]
<title>RecordedBooks search for '[% q | html %]' &rsaquo; [% IF ( LibraryNameTitle ) %][% LibraryNameTitle | html %][% ELSE %]Koha online[% END %] catalog</title>
[% INCLUDE 'doc-head-close.inc' %]
[% BLOCK cssinclude %]
[% END %]
</head>
[% INCLUDE 'bodytag.inc' bodyid='recordedbooks-results-page' bodyclass='scrollto' %]
[% INCLUDE 'masthead.inc' %]
<div class="main">
<nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumbs">
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/cgi-bin/koha/opac-main.pl">Home</a>
</li>
<li class="breadcrumb-item active">
<a href="#" aria-current="page">RecordedBooks search for '[% q | html %]'</a>
</li>
</ol>
</nav> <!-- /#breadcrumbs -->
<div class="container-fluid">
<div class="row">
<div class="col-lg-2">
[% IF ( OpacNav || OpacNavBottom ) %]
[% INCLUDE 'navigation.inc' %]
[% END %]
</div>
<div class="col-lg-10 order-first order-md-first order-lg-2">
<div id="recordedbooks-results-content" class="maincontent searchresults">
<h1>RecordedBooks search for '[% q | html %]'</h1>
[% UNLESS ( logged_in_user ) %]
<h2 class="rb_login">Sign in to view availability and checkout items or place holds</h2>
[% END %]
<div id="breadcrumbs">
<p></p>
</div>
<div id="top-pages">
<nav class="pagination pagination-sm noprint" aria-label="Search results pagination">
</nav>
</div>
<table id="recordedbooks-results-list" class="table table-striped">
<tbody>
</tbody>
</table>
<div id="bottom-pages">
<nav class="pagination pagination-sm noprint" aria-label="Search results pagination">
</nav>
</div>
</div> <!-- / #recordedbooks-results-content -->
</div> <!-- / .col-lg-10 -->
</div> <!-- / .row -->
</div> <!-- / .container-fluid -->
</div> <!-- / .main -->
[% INCLUDE 'recordedbooks-checkout.inc' %]
[% INCLUDE 'opac-bottom.inc' %]
[% BLOCK jsinclude %]
[% Asset.js("js/recordedbooks.js") | $raw %]
<script>
var querystring = "[% q |replace( "'", "\'" ) |replace( '\n', '\\n' ) |replace( '\r', '\\r' ) |html %]";
var results_per_page = [% OPACnumSearchResults || 20 | html %];
function search( page ) {
$( '#recordedbooks-status' ).html( MSG_SEARCHING.format("RecordedBooks") + ' <img class="throbber" src="[% interface | html %]/[% theme | html %]/images/spinner-small.gif" /></span>' );
KOHA.RecordedBooks.search( querystring, results_per_page, page, function( data ) {
if ( data.error ) {
$( '#recordedbooks-status' ).html( '<strong class="unavailable">' + MSG_ERROR_SEARCHING_COLLECTION.format("RecordedBooks") + ': ' + data.error + '</strong>' );
return;
}
if ( !data.total ) {
$( '#recordedbooks-status' ).html( '<strong>' + MSG_NO_RESULTS_FOUND_IN_COLLECTION.format("RecordedBooks") + '</strong>' );
return;
}
$( '#recordedbooks-results-list tbody' ).empty();
$( '#recordedbooks-status' ).html( '<strong>' + MSG_RESULTS_FOUND_IN_COLLECTION.format(data.total, "RecordedBooks") + '</strong>' );
for ( var i = 0; data.items[i]; i++ ) {
var prod = data.items[i];
var results = [];
results.push( '<tr>' );
results.push( '<td class="info"><span class="title">' );
if (prod.url) results.push( '<a href="', prod.url, '" target="recordedbooks">' );
results.push( prod.title );
if (prod.url) results.push( '</a>' );
results.push( '</span>' );
results.push( '<p>' + MSG_BY + ' ', prod.author, '</p>' );
if (prod.description) results.push( '<p>' + prod.description, '</p>' );
results.push( '<span class="results_summary mediatype"><span class="label">' + MSG_TYPE + ': </span>', prod.media, '</span>' );
results.push( '</td>' );
results.push( '<td>' );
if ( prod.images && prod.images.medium ) {
if (prod.url) results.push( '<a href="', prod.url, '" target="recordedbooks">' );
results.push( '<img class="thumbnail" src="', prod.images.medium, '" />' );
if (prod.url) results.push( '</a>' );
}
results.push( '</td>' );
results.push( '</tr>' );
var $tr = $( results.join( '' ));
$( '#recordedbooks-results-list tbody' ).append( $tr );
$tr.find( '.info' ).each(function() {
KOHA.RecordedBooks.add_actions(this, prod.isbn);
});
}
$( '#recordedbooks-results-list tr:odd' ).addClass( 'highlight' );
var pages = [];
var max_page = Math.floor( data.total / results_per_page );
if (data.total == page*results_per_page) max_page++;
if ( page != 1 ) {
pages.push( '<li class="page-item"><a class="page-link od-nav" href="#" data-page="' + (page - 1) + '">&laquo; ' + MSG_PREVIOUS + '</a></li>' );
}
for ( var p = Math.max( 0, page - 9 ); p <= Math.min( max_page, p + 9 ); p++ ) {
if ( p == page ) {
pages.push( ' <li class="page-item disabled"><a class="page-link" href="#">' + ( p + 1 ) + '</a></li>' );
} else {
pages.push( ' <li class="page-item"><a class="page-link od-nav" href="#" data-page="' + p + '">' + p + '</a></li>' );
}
}
if ( page < max_page ) {
pages.push( ' <li class="page-item"><a class="page-link od-nav" href="#" data-page="' + (page + 1) + '">' + MSG_NEXT + ' &raquo;</a></li>' );
}
if ( pages.length > 1 ) $( '#top-pages, #bottom-pages' ).find( '.pagination' ).html( '<ul class="pagination">' + pages.join( '' ) + '</ul>');
if( KOHA.RecordedBooks.is_identified() == false ){
$("#breadcrumbs").before('<h3 class="rb_register"><a href="https://[% Koha.Preference('RecordedBooksDomain') | uri %]">To see availability you must register for RecordedBooks using your cardnumber and the email associated with your Koha account</a></h3>');
}
} );
}
$( document ).ready( function() {
$( '#breadcrumbs p' )
.append( ' ' )
.append( '<span id="recordedbooks-status"></span>' );
$( document ).on( 'click', 'a.od-nav', function() {
search( $( this ).data( 'page' ) );
return false;
});
[% IF ( logged_in_user ) %]
KOHA.RecordedBooks.with_account_details("#breadcrumbs", function() {
search( 1 );
});
[% ELSE %]
search( 1 );
[% END %]
} );
</script>
[% END %]

View file

@ -9,7 +9,6 @@
[% IF firstPage %]
[% SET OverDriveEnabled = Koha.Preference('OverDriveLibraryID') && Koha.Preference('OverDriveClientKey') && Koha.Preference('OverDriveClientSecret') %]
[% SET RecordedBooksEnabled = Koha.Preference('RecordedBooksLibraryID') && Koha.Preference('RecordedBooksClientSecret') %]
[% END %]
[% INCLUDE 'doc-head-open.inc' %]
@ -582,7 +581,6 @@
<script src="https://ltfl.librarything.com/forlibraries/widget.js?id=[% LibraryThingForLibrariesID | html %]&amp;systype=koha"></script>
[% END %]
[% IF ( OverDriveEnabled ) %][% Asset.js("js/overdrive.js") | $raw %][% END %]
[% IF ( RecordedBooksEnabled ) %][% Asset.js("js/recordedbooks.js") | $raw %][% END %]
[% Asset.js("js/authtoresults.js") | $raw %]
[% Asset.js("lib/hc-sticky.js") | $raw %]
[% IF ( OpacHighlightedWords ) %]
@ -836,23 +834,6 @@
}
} );
[% END # /IF OverDriveEnabled %]
[% IF ( RecordedBooksEnabled ) %]
var $recordedbooks_results = $( '<div id="recordedbooks-results">' + MSG_SEARCHING.format('RecordedBooks') + ' <img class="throbber" src="[% interface | html %]/[% theme | html %]/images/spinner-small.gif" /></div>' );
$( '#numresults' ) .after( $recordedbooks_results );
KOHA.RecordedBooks.search( querystring, [% OPACnumSearchResults || "null" | html %], null, function( data ) {
if ( data.error ) {
$recordedbooks_results.html( MSG_ERROR_SEARCHING_COLLECTION.format('RecordedBooks') + ': ' + data.error);
return;
}
// data.total can be either 42 or "60+"
if ( typeof(data.total) === 'string' && data.total.charAt(0) > 0 || typeof(data.total) === 'number' && data.total > 0 ) {
$recordedbooks_results.html( '<a href="/cgi-bin/koha/opac-recordedbooks-search.pl?q=' + encodeURIComponent( querystring ) + '">' + MSG_RESULTS_FOUND_IN_COLLECTION.format(data.total, 'RecordedBooks') + '</a>' );
} else {
$recordedbooks_results.remove();
}
} );
[% END # /IF RecordedBooksEnabled %]
[% IF ( OpenLibrarySearch ) %]
var $openlibrary_results = $( '<div id="openlibrary-results">' + MSG_SEARCHING.format('OpenLibrary' ) + ' <img class="throbber" src="[% interface | html %]/[% theme | html %]/images/spinner-small.gif" /></div>' );
$( '#numresults' ) .after( $openlibrary_results );

View file

@ -312,18 +312,11 @@
<a class="nav-link" id="opac-user-overdrive-tab" data-toggle="tab" role="tab" aria-controls="opac-user-overdrive" aria-selected="false" href="#opac-user-overdrive">OverDrive account</a>
</li>
[% END %]
[% IF ( RecordedBooksCirculation ) %]
<li class="nav-item" role="presentation">
<a class="nav-link" id="opac-user-recordedbooks-tab" data-toggle="tab" role="tab" aria-controls="opac-user-recordedbooks" aria-selected="false" href="#opac-user-recordedbooks">RecordedBooks account</a>
</li>
[% END %]
</ul>
<div class="tab-content">
<div id="opac-user-overdrive" class="tab-pane" role="tabpanel" aria-labelledby="opac-user-overdrive-tab">
</div>
<div id="opac-user-recordedbooks" class="tab-pane" role="tabpanel" aria-labelledby="opac-user-recordedbooks-tab">
</div>
<div id="opac-user-checkouts" class="tab-pane active" role="tabpanel" aria-labelledby="opac-user-checkouts-tab">
[% IF ( issues_count ) %]
<form id="renewselected" action="/cgi-bin/koha/opac-renew.pl" method="post">
@ -1070,9 +1063,6 @@
[% INCLUDE 'overdrive-login.inc' %]
[% END %]
[% END %]
[% IF ( RecordedBooksCirculation ) %]
[% INCLUDE 'recordedbooks-checkout.inc' %]
[% END %]
[% INCLUDE 'opac-bottom.inc' %]
[% BLOCK jsinclude %]
@ -1437,20 +1427,4 @@
});
</script>
[% END %]
[% IF RecordedBooksCirculation %]
[% Asset.js("js/recordedbooks.js") | $raw %]
<script>
$(document).ready(function() {
[% IF ( recordedbooks_error ) %]
KOHA.RecordedBooks.display_error("#opac-user-recordedbooks", "[% recordedbooks_error.dquote | html %]");
[% END %]
[% IF ( recordedbooks_tab ) %]
$("#opac-user-views a[href='#opac-user-recordedbooks']").tab("show");
[% END %]
$("#opac-user-recordedbooks").each( function() {
KOHA.RecordedBooks.display_account_details(this);
} );
});
</script>
[% END %]
[% END %]

View file

@ -1,334 +0,0 @@
if ( typeof KOHA == "undefined" || !KOHA ) {
var KOHA = {};
}
KOHA.RecordedBooks = new function() {
var svc_url = '/cgi-bin/koha/svc/recordedbooks';
var error_div = $('<div class="recordedbooks-error">');
function display_error ( error ) {
error_div.text(error);
}
var details = null;
function is_identified() {
return details ? details.is_identified : false;
}
var checkout_popup = null;
$( document ).ready(function() {
checkout_popup = $("#recordedbooks-checkout");
});
function display_account (container, data) {
if (!data.is_identified) {
return;
}
if (data.checkouts) {
var checkouts_div = $('<div class="recordedbooks-div">').html('<h3>' + MSG_CHECKOUTS + '</h3>');
var items = data.checkouts.items;
var checkouts_list;
if (items.length == 0) {
checkouts_list = MSG_NO_CHECKOUTS;
} else {
checkouts_list = $('<ul class="recordedbooks-list">');
data.checkouts.items.forEach(function(item) {
item_line(checkouts_list, item);
});
}
checkouts_div.append(checkouts_list);
$(container).append(checkouts_div);
}
if (data.holds) {
var holds_div = $('<div class="recordedbooks-div">').html('<h3>' + MSG_HOLDS + '</h3>');
var items = data.holds.items;
var holds_list;
if (items.length == 0) {
holds_list = MSG_NO_HOLDS;
} else {
holds_list = $('<ul class="recordedbooks-list">');
data.holds.items.forEach(function(item) {
item_line(holds_list, item);
});
}
holds_div.append(holds_list);
$(container).append(holds_div);
}
}
function item_line(ul_el, item) {
var line = $('<li class="recordedbooks-item">');
if (item.images) {
var thumb_url = item.images.small;
if (thumb_url) {
$('<img class="recordedbooks-item-thumbnail">')
.attr("src", thumb_url)
.appendTo(line);
}
}
$('<div class="recordedbooks-item-title">')
.text(item.title)
.appendTo(line);
$('<div class="recordedbooks-item-subtitle">')
.text(item.subtitle)
.appendTo(line);
$('<div class="recordedbooks-item-author">')
.text(item.author)
.appendTo(line);
if (item.files && item.files.length > 0) {
downloads = $('<div class="recordedbooks-item-author">')
.text("Downloads")
.appendTo(line);
render_downloads(downloads, item.files);
}
var actions = $('<span class="actions">');
display_actions(actions, item.isbn);
$('<div id="action_'+item.isbn+'" class="actions-menu">')
.append(actions)
.appendTo(line);
$('<span id="waiting_'+item.isbn+'" style="display:none;"><img class="throbber" src="' + SPINNER_THROBBER + '" /></span>').appendTo(line);
$(ul_el).append(line);
}
function render_downloads(el, files) {
if (files.length == 0) return;
var file_spec = files.shift();
if (/^https?:\/\/api\./.test(file_spec.url)) {
$.ajax({
dataType: "json",
url: file_spec.url,
success: function (data) {
append_download_link(el, data.url, data.id);
render_downloads(el, files);
},
error: function(jqXHR, textStatus, errorThrown) {
display_error(errorThrown);
}
});
} else {
append_download_link(el, file_spec.url, file_spec.filename);
render_downloads(el, files);
}
}
function append_download_link(el, url, text) {
var p = $("<p>");
$( '<a href="' + url + '" target="recordedbooks">' )
.text(text)
.appendTo(p);
el.append(p);
}
function svc_ajax ( method, params, success_callback, callback_for_error_too ) {
// remove when jquery is upgraded
for (var key in params) {
if (params[key] === null) delete params[key];
}
return $.ajax({
method: method,
dataType: "json",
url: svc_url,
data: params,
success: function (data) {
if (data.error && !callback_for_error_too) {
display_error(data.error);
}
success_callback(data);
},
error: function(jqXHR, textStatus, errorThrown) {
if (callback_for_error_too) {
success_callback({error: errorThrown});
return;
}
display_error(errorThrown);
}
});
}
function load_account_details ( callback ) {
svc_ajax('get', { action: "account" }, function(data) {
details = data;
callback(data);
});
}
function item_action (params, el) {
var isbn = params.isbn;
$("#action_"+isbn).hide();
$("#waiting_"+isbn).show();
svc_ajax('post', params, function(data) {
if (data.checkouts) {
details.checkouts = data.checkouts;
}
if (data.holds) {
details.holds = data.holds;
}
display_actions(el, isbn);
$("#action_"+isbn).show();
$("#waiting_"+isbn).hide();
});
}
function item_is_checked_out (isbn) {
if ( !(details && details.checkouts) ) {
return null;
}
var isbn_uc = isbn.toUpperCase();
var items = details.checkouts.items;
for (var i = 0; i < items.length; i++) {
if ( items[i].isbn.toUpperCase() == isbn_uc ) {
return items[i];
}
}
return null;
}
function item_is_on_hold (isbn) {
if ( !(details && details.holds) ) {
return false;
}
var isbn_uc = isbn.toUpperCase();
var items = details.holds.items;
for (var i = 0; i < items.length; i++) {
if ( items[i].isbn.toUpperCase() == isbn_uc ) {
return items[i];
}
}
return null;
}
function display_actions(el, isbn) {
$(el).empty();
if (is_identified()) {
var item = item_is_checked_out(isbn);
if (item) {
var expires = new Date(item.expires);
$('<span class="recordedbooks-item-status">')
.text(MSG_CHECKED_OUT_UNTIL.format(expires.toLocaleString()))
.appendTo(el);
$(el).append(" ");
if (item.url) {
var download = $('<a href="'+item.url+'">').appendTo(el);
decorate_button(download, MSG_DOWNLOAD);
$(el).append(" ");
}
$(el).append( ajax_button(MSG_CHECK_IN, function() {
if( confirm(MSG_CHECK_IN_CONFIRM) ) {
item_action({action: "return", isbn: isbn}, el);
}
}) );
return item;
}
item = item_is_on_hold(isbn);
if (item) {
$('<span class="recordedbooks-status">')
.text(MSG_ON_HOLD)
.appendTo(el);
$(el).append(" ");
}
if(checkout_popup) {
$(el).append( ajax_button(MSG_CHECK_OUT, function() {
if( confirm(MSG_CHECK_OUT_CONFIRM) ) {
$("#action_"+isbn).hide();
$("#waiting_"+isbn).show();
svc_ajax('post', {action: "checkout", isbn: isbn}, function(data) {
if (data.checkouts) {
details.checkouts = data.checkouts;
}
if (data.holds) {
details.holds = data.holds;
}
item = display_actions(el, isbn);
$("#action_"+isbn).show();
$("#waiting_"+isbn).hide();
});
}
}) );
}
if (!item) {
$(el).append( ajax_button(MSG_PLACE_HOLD, function() {
item_action({action: "place_hold", isbn: isbn}, el);
}) );
}
if (item) {
$(el).append( ajax_button(MSG_CANCEL_HOLD, function() {
if( confirm(MSG_CANCEL_HOLD_CONFIRM) ) {
item_action({action: "remove_hold", isbn: isbn}, el);
}
}) );
}
return item;
}
}
function ajax_button(label, on_click) {
var button = $('<a href="#">')
.click(function(e) {
e.preventDefault();
on_click();
});
decorate_button(button, label);
return button;
}
function decorate_button(button, label) {
$(button)
.addClass("btn btn-primary btn-mini")
.css("color","white")
.text(label);
}
this.with_account_details = function( el, callback ) {
$(el).append(error_div);
load_account_details( callback );
}
this.display_account_details = function( el ) {
$(el).empty().append(error_div);
load_account_details(function(data) {
display_account(el, data);
});
};
this.display_error = function( el, error ) {
$(el).empty().append(error_div);
display_error(error);
};
this.is_identified = is_identified;
this.add_actions = function(el, isbn) {
var actions = $('<span class="actions">');
display_actions(actions, isbn);
$('<div id="action_'+isbn+'" class="actions-menu">')
.append(actions)
.appendTo(el);
$("#action_"+isbn).before('<span id="waiting_'+isbn+'" style="display:none;"><img class="throbber" src="' + SPINNER_THROBBER + '" /></span>');
};
this.search = function( q, page_size, page, callback ) {
svc_ajax('get', { action: "search", q: q, page_size: page_size, page: page }, function (data) {
var results;
if (data.results) {
results = data.results;
if (!results.total) {
var total = results.items.length;
if ( total == results.page_size ) total = total + "+";
results.total = total;
}
}
else results = {};
results.error = data.error;
callback(results);
}, true);
};
}

View file

@ -1,43 +0,0 @@
#!/usr/bin/perl
# Copyright 2013 ByWater
#
# 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 3 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, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use CGI qw( -utf8 );
use C4::Auth qw( get_template_and_user );
use C4::Output qw( output_html_with_http_headers );
my $cgi = CGI->new;
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{
template_name => "opac-recordedbooks-search.tt",
query => $cgi,
type => "opac",
authnotrequired => 1,
}
);
$template->param(
q => scalar $cgi->param('q'),
limit => C4::Context->preference('OPACnumSearchResults'),
);
output_html_with_http_headers $cgi, $cookie, $template->output;

View file

@ -373,7 +373,6 @@ $template->param(
OverDriveCirculation => C4::Context->preference('OverDriveCirculation') || 0,
overdrive_error => scalar $query->param('overdrive_error') || undef,
overdrive_tab => scalar $query->param('overdrive_tab') || 0,
RecordedBooksCirculation => C4::Context->preference('RecordedBooksClientSecret') && C4::Context->preference('RecordedBooksLibraryID'),
);
my $patron_messages = Koha::Patron::Messages->search(

View file

@ -1,148 +0,0 @@
#!/usr/bin/perl
# Copyright 2016 Catalyst IT
# 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 3 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, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use CGI qw ( -utf8 );
use JSON qw(encode_json);
use C4::Auth qw(checkauth);
use C4::Output qw( output_with_http_headers );
use Koha::Logger;
use Koha::ExternalContent::RecordedBooks;
our $cgi = CGI->new;
my $logger = Koha::Logger->get({ interface => 'opac' });
my $page_url = $cgi->referer();
my ( $user, $cookie, $sessionID, $flags ) = checkauth( $cgi, 1, {}, 'opac' );
my $action = $cgi->param('action') or response_bad_request("No 'action' specified");
($user && $sessionID) || $action eq 'search' or response_bad_request("User not logged in");
local $@;
my $rb = eval { Koha::ExternalContent::RecordedBooks->new({ koha_session_id => $sessionID }) };
unless ($rb) {
$logger->error($@) if $@;
response({
error => $@,
is_identified => JSON::false,
});
}
my $is_identified = $rb->is_identified;
my %data = (
is_identified => $is_identified ? JSON::true : JSON::false,
);
response(\%data) unless $is_identified || $action eq 'search';
eval {
{
$action eq 'search' && do {
my $query = $cgi->param('q');
my $page = $cgi->param('page');
my $page_size = $cgi->param('page_size');
my $sort = $cgi->param('sort');
my $res = $rb->search({
query => $query,
page => $page,
page_size => $page_size,
sort => $sort,
});
$data{results} = $res;
last;
};
$action eq 'account' && do {
eval {
$data{account} = $rb->patron;
$data{checkouts} = $rb->checkouts;
$data{holds} = $rb->holds;
};
response_bad_request($rb->error_message($@)) if $@;
last;
};
$action eq 'checkout' && do {
my $isbn = $cgi->param('isbn')
or response_bad_request("No 'isbn' specified");
my $format = $cgi->param('format');
$data{action} = eval { $rb->checkout($isbn, $format) };
response_bad_request($rb->error_message($@)) if $@;
eval {
$data{checkouts} = $rb->checkouts;
$data{holds} = $rb->holds;
};
$data{error} = $rb->error_message($@) if $@;
last;
};
$action eq 'return' && do {
my $isbn = $cgi->param('isbn')
or response_bad_request("No 'isbn' specified");
$data{action} = eval { $rb->return($isbn) };
response_bad_request($rb->error_message($@)) if $@;
$data{checkouts} = eval { $rb->checkouts };
$data{error} = $rb->error_message($@) if $@;
last;
};
$action eq 'place_hold' && do {
my $isbn = $cgi->param('isbn')
or response_bad_request("No 'isbn' specified");
$data{action} = eval { $rb->place_hold($isbn) };
response_bad_request($rb->error_message($@)) if $@;
$data{holds} = eval { $rb->holds };
$data{error} = $rb->error_message($@) if $@;
last;
};
$action eq 'remove_hold' && do {
my $isbn = $cgi->param('isbn')
or response_bad_request("No 'isbn' specified");
$data{action} = eval { $rb->remove_hold($isbn) };
response_bad_request($rb->error_message($@)) if $@;
$data{holds} = eval { $rb->holds };
$data{error} = $rb->error_message($@) if $@;
last;
};
response_bad_request("Invalid 'action': $action");
}
};
if ($@) {
$logger->error($@);
$data{error} = $rb->error_message("$@");
}
response(\%data);
sub response_bad_request {
my ($error) = @_;
response({error => $error}, "400 $error");
}
sub response {
my ($data, $status_line) = @_;
$status_line ||= "200 OK";
output_with_http_headers $cgi, undef, encode_json($data), 'json', $status_line;
exit;
}

View file

@ -1,55 +0,0 @@
use Modern::Perl;
use t::lib::Mocks;
use t::lib::TestBuilder;
use Test::More tests => 3; # last test to print
use C4::Auth qw( get_session );
use Koha::Database;
use Module::Load::Conditional qw( can_load );
SKIP: {
skip "cannot filnd WebService::ILS::RecordedBooks::PartnerPatron", 3
unless can_load( modules => {'WebService::ILS::RecordedBooks::PartnerPatron' => undef} );
use_ok('Koha::ExternalContent::RecordedBooks');
my $ocd_user_email = $ENV{RECORDEDBOOKS_TEST_USER_EMAIL};
SKIP: {
skip "Env RECORDEDBOOKS_TEST_USER_EMAIL not set", 2 unless $ocd_user_email;
my $ocd_secret = $ENV{RECORDEDBOOKS_TEST_CLIENT_SECRET}
|| C4::Context->preference('RecordedBooksClientSecret');
my $ocd_library_id = $ENV{RECORDEDBOOKS_TEST_LIBRARY_ID}
|| C4::Context->preference('RecordedBooksLibraryID');
my $ocd_domain = $ENV{RECORDEDBOOKS_TEST_DOMAIN}
|| C4::Context->preference('RecordedBooksDomain');
skip "Env RECORDEDBOOKS_TEST_CLIENT_SECRET RECORDEDBOOKS_TEST_LIBRARY_ID RECORDEDBOOKS_TEST_DOMAIN not set", 2
unless $ocd_secret && $ocd_library_id && $ocd_domain;
my $schema = Koha::Database->schema;
$schema->storage->txn_begin;
my $builder = t::lib::TestBuilder->new();
t::lib::Mocks::mock_preference('RecordedBooksClientSecret', $ocd_secret);
t::lib::Mocks::mock_preference('RecordedBooksLibraryID', $ocd_library_id);
t::lib::Mocks::mock_preference('RecordedBooksDomain', $ocd_domain);
my $patron = $builder->build({
source => 'Borrower',
value => {
email => $ocd_user_email,
}
});
my $session = C4::Auth::get_session("");
$session->param('number', $patron->{borrowernumber});
$session->flush;
my $client = Koha::ExternalContent::RecordedBooks->new({koha_session_id => $session->id});
my $user_agent_string = $client->user_agent->agent();
ok ($user_agent_string =~ m/^Koha/, 'User Agent string is set')
or diag("User Agent string: $user_agent_string");
ok ($client->search({query => "school"}), 'search()');
}
}