#overdrive-results,
+#recordedbooks-results,
#openlibrary-results {
font-weight: bold;
padding-left: 1em;
--- /dev/null
+<div id="recordedbooks-checkout" class="modal hide" tabindex="-1" role="dialog" aria-labelledby="recordedbooks-checkout-label" aria-hidden="true">
+ <div class="modal-header">
+ <button type="button" class="closebtn" 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-primary 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 -->
--- /dev/null
+[% USE Koha %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>[% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › RecordedBooks search for '[% q | html %]'</title>
+[% INCLUDE 'doc-head-close.inc' %]
+[% BLOCK cssinclude %]
+<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/jquery.rating.css" />
+<style>
+.actions a.addtocart {
+ display: inline;
+}
+</style>
+[% END %]
+</head>
+[% INCLUDE 'bodytag.inc' bodyid='recordedbooks-results-page' bodyclass='scrollto' %]
+[% INCLUDE 'masthead.inc' %]
+
+ <div class="main">
+ <ul class="breadcrumb">
+ <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">›</span></li>
+ <li><a href="#">RecordedBooks search for '[% q | html %]'</a></li>
+ </ul>
+
+ <div class="container-fluid">
+ <div class="row-fluid">
+ <div class="span2">
+ [% IF ( OpacNav || OpacNavBottom ) %]
+ [% INCLUDE 'navigation.inc' %]
+ [% END %]
+ </div>
+ <div class="span10">
+ <div id="recordedbooks-results-content" class="maincontent searchresults">
+ <h1>RecordedBooks search for '[% q | html %]'</h1>
+ <div id="breadcrumbs">
+ <p></p>
+ </div>
+
+ <div id="top-pages">
+ <div class="pagination pagination-small">
+ </div>
+ </div>
+
+ <table id="recordedbooks-results-list" class="table table-striped">
+ <tbody>
+ </tbody>
+ </table>
+
+ <div id="bottom-pages">
+ <div class="pagination pagination-small">
+ </div>
+ </div>
+
+ </div> <!-- / #recordedbooks-results-content -->
+ </div> <!-- / .span10 -->
+ </div> <!-- / .row-fluid -->
+ </div> <!-- / .container-fluid -->
+ </div> <!-- / .main -->
+
+[% INCLUDE 'recordedbooks-checkout.inc' %]
+
+[% INCLUDE 'opac-bottom.inc' %]
+[% BLOCK jsinclude %]
+<script type="text/javascript" src="[% interface %]/[% theme %]/js/recordedbooks.js"></script>
+<script type="text/javascript" src="[% interface %]/[% theme %]/lib/jquery/plugins/jquery.rating.js"></script>
+<script type="text/javascript">
+var querystring = "[% q |replace( "'", "\'" ) |replace( '\n', '\\n' ) |replace( '\r', '\\r' ) |html %]";
+var results_per_page = [% OPACnumSearchResults || 20 %];
+
+function search( page ) {
+ $( '#recordedbooks-status' ).html( _("Searching RecordedBooks...") + ' <img class="throbber" src="[% interface %]/lib/jquery/plugins/themes/classic/throbber.gif" /></span>' );
+
+ KOHA.RecordedBooks.search( querystring, results_per_page, page, function( data ) {
+ if ( data.error ) {
+ $( '#recordedbooks-status' ).html( '<strong class="unavailable">' + _("Error searching RecordedBooks collection") + ': ' + data.error + '</strong>' );
+ return;
+ }
+
+ if ( !data.total ) {
+ $( '#recordedbooks-status' ).html( '<strong>' + _("No results found in the library's RecordedBooks collection.") + '</strong>' );
+ return;
+ }
+
+ $( '#recordedbooks-results-list tbody' ).empty();
+
+ $( '#recordedbooks-status' ).html( '<strong>' + _("Found") + ' ' + data.total + ' ' + _("results in the library's RecordedBooks collection.") + '</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>' + _("by") + ' ', prod.author, '</p>' );
+ if (prod.description) results.push( '<p>' + prod.description, '</p>' );
+ results.push( '<span class="results_summary mediatype"><span class="label">' + _("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><a class="od-nav" href="#" data-page="' + (page - 1) + '">« ' + _("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="active"><a href="#">' + ( p + 1 ) + '</a></li>' );
+ } else {
+ pages.push( ' <li><a class="od-nav" href="#" data-page="' + p + '">' + p + '</a></li>' );
+ }
+ }
+
+ if ( page < max_page ) {
+ pages.push( ' <li><a class="od-nav" href="#" data-page="' + (page + 1) + '">' + _("Next") + ' »</a></li>' );
+ }
+
+ if ( pages.length > 1 ) $( '#top-pages, #bottom-pages' ).find( '.pagination' ).html( '<ul>' + pages.join( '' ) + '</ul>');
+
+ $( '#recordedbooks-results-list input.star' ).rating();
+ } );
+}
+
+$( 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 ( loggedinusername ) %]
+ KOHA.RecordedBooks.with_account_details("#breadcrumbs", function() {
+ search( 1 );
+ });
+ [% ELSE %]
+ search( 1 );
+ [% END %]
+} );
+</script>
+[% END %]
[% END %]
[% IF ( OpacStarRatings == 'all' || Koha.Preference('Babeltheque') ) %][% Asset.js("lib/jquery/plugins/jquery.rating.js") | $raw %][% END %]
[% IF ( OverDriveEnabled ) %][% Asset.js("js/overdrive.js") | $raw %][% END %]
+[% IF ( RecordedBooksEnabled ) %][% Asset.js("js/recordedbooks.js") | $raw %][% END %]
[% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") | $raw %]
[% Asset.js("js/authtoresults.js") | $raw %]
[% IF ( OpacHighlightedWords ) %][% Asset.js("lib/jquery/plugins/jquery.highlight-3.js") | $raw %]
}
} );
[% END %]
+ [% IF ( RecordedBooksEnabled ) %]
+ var $recordedbooks_results = $( '<div id="recordedbooks-results">' + _( 'Searching RecordedBooks...' ) + ' <img class="throbber" src="[% interface %]/lib/jquery/plugins/themes/classic/throbber.gif" /></div>' );
+ $( '#numresults' ) .append( ' ' )
+ .append( $recordedbooks_results );
+ KOHA.RecordedBooks.search( querystring, [% OPACnumSearchResults || "null" %], null, function( data ) {
+ if ( data.error ) {
+ $recordedbooks_results.html( _( 'Error searching RecordedBooks collection' ) + ': ' + data.error);
+ return;
+ }
+
+ if ( data.total > 0 ) {
+ $recordedbooks_results.html( _( 'Found' ) + ' <a href="/cgi-bin/koha/opac-recordedbooks-search.pl?q=' + escape( querystring ) + '">' + data.total + ' ' + _( 'results' ) + '</a> ' + _( 'in RecordedBooks collection' ) );
+ } else {
+ $recordedbooks_results.remove();
+ }
+ } );
+ [% END %]
[% IF ( OpenLibrarySearch ) %]
var $openlibrary_results = $( '<div id="openlibrary-results">' + _( 'Searching Open Library...' ) + ' <img class="throbber" src="[% interface | html %]/lib/jquery/plugins/themes/classic/throbber.gif" /></div>' );
$( '#numresults' ) .append( ' ' )
[% IF ( OverDriveCirculation ) %]
<li><a href="#opac-user-overdrive">OverDrive Account</a></li>
[% END %]
+ [% IF ( RecordedBooksCirculation ) %]
+ <li><a href="#opac-user-recordedbooks">RecordedBooks Account</a></li>
+ [% END %]
</ul>
<div id="opac-user-overdrive">
</div>
+ <div id="opac-user-recordedbooks">
+ </div>
<div id="opac-user-checkouts">
[% IF ( issues_count ) %]
<form id="renewselected" action="/cgi-bin/koha/opac-renew.pl" method="post">
[% IF ( OverDriveCirculation ) %]
[% INCLUDE 'overdrive-checkout.inc' %]
[% END %]
+[% IF ( RecordedBooksCirculation ) %]
+[% INCLUDE 'recordedbooks-checkout.inc' %]
+[% END %]
[% INCLUDE 'opac-bottom.inc' %]
});
</script>
[% END %]
+ [% IF RecordedBooksCirculation %]
+ <script type="text/javascript" src="[% interface %]//[% theme %]/js/recordedbooks.js"></script>
+ <script type="text/JavaScript">
+ $(document).ready(function() {
+ [% IF ( recordedbooks_error ) %]
+ KOHA.RecordedBooks.display_error("#opac-user-recordedbooks", "[% recordedbooks_error.dquote %]");
+ [% END %]
+ [% IF ( recordedbooks_tab ) %]
+ $("#opac-user-views").tabs("select", "#opac-user-recordedbooks");
+ [% END %]
+ $("#opac-user-recordedbooks").each( function() {
+ KOHA.RecordedBooks.display_account_details(this);
+ } );
+ });
+ [% END %]
+ </script>
[% END %]
--- /dev/null
+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>' + _("Checkouts") + '</h3>');
+ var items = data.checkouts.items;
+ var checkouts_list;
+ if (items.length == 0) {
+ checkouts_list = _("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>' + _("Holds") + '</h3>');
+ var items = data.holds.items;
+ var holds_list;
+ if (items.length == 0) {
+ holds_list = _("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);
+
+ $(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;
+ svc_ajax('post', params, function(data) {
+ if (data.checkouts) {
+ details.checkouts = data.checkouts;
+ }
+ if (data.holds) {
+ details.holds = data.holds;
+ }
+ display_actions(el, isbn);
+ });
+ }
+
+ 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(_("Checked out until") + " " + expires.toLocaleString())
+ .appendTo(el);
+ $(el).append(" ");
+
+ if (item.url) {
+ var download = $('<a href="'+item.url+'">').appendTo(el);
+ decorate_button(download, _("Download"));
+ $(el).append(" ");
+ }
+
+ $(el).append( ajax_button(_("Check in"), function() {
+ if( confirm(_("Are you sure you want to return this item?")) ) {
+ item_action({action: "return", isbn: isbn}, el);
+ }
+ }) );
+
+ return item;
+ }
+
+ item = item_is_on_hold(isbn);
+ if (item) {
+ $('<span class="recordedbooks-status">')
+ .text(_("On hold"))
+ .appendTo(el);
+ $(el).append(" ");
+ }
+
+ if(checkout_popup) {
+ $(el).append( ajax_button(_("Check out"), function() {
+ if( confirm(_("Are you sure you want to checkout this item?")) ) {
+ 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);
+ });
+ }
+ }) );
+ }
+ if (!item) {
+ $(el).append( ajax_button(_("Place hold"), function() {
+ item_action({action: "place_hold", isbn: isbn}, el);
+ }) );
+ }
+
+ if (item) {
+ $(el).append( ajax_button(_("Cancel"), function() {
+ if( confirm(_("Are you sure you want to cancel this hold?")) ) {
+ 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);
+ };
+
+ 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);
+ };
+}
--- /dev/null
+#!/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 strict;
+use warnings;
+
+use CGI qw ( -utf8 );
+
+use C4::Auth qw(:DEFAULT);
+use C4::Output;
+
+my $cgi = new CGI;
+
+# Getting the template and auth
+my ($template, $loggedinuser, $cookie)
+= get_template_and_user({template_name => "opac-recordedbooks-search.tt",
+ query => $cgi,
+ type => "opac",
+ debug => 1,
+ authnotrequired => 1,
+ });
+
+$template->{'VARS'}->{'q'} = $cgi->param('q');
+$template->{'VARS'}->{'limit'} = C4::Context->preference('OPACnumSearchResults');
+
+output_html_with_http_headers $cgi, $cookie, $template->output;
$template->{VARS}->{IDreamBooksReadometer} = C4::Context->preference('IDreamBooksReadometer');
$template->{VARS}->{IDreamBooksResults} = C4::Context->preference('IDreamBooksResults');
-if ($offset == 0 && IsOverDriveEnabled()) {
- $template->param(OverDriveEnabled => 1);
- $template->param(OverDriveLibraryID => C4::Context->preference('OverDriveLibraryID'));
+if ($offset == 0) {
+ if (IsOverDriveEnabled()) {
+ $template->param(OverDriveEnabled => 1);
+ $template->param(OverDriveLibraryID => C4::Context->preference('OverDriveLibraryID'));
+ }
+ $template->param(RecordedBooksEnabled => C4::Context->preference( 'RecordedBooksClientSecret' ) && C4::Context->preference( 'RecordedBooksLibraryID' ));
}
$template->param( borrowernumber => $borrowernumber);
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(
--- /dev/null
+#!/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;
+use Koha::Logger;
+use Koha::ExternalContent::RecordedBooks;
+
+our $cgi = new CGI;
+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;
+}