From 24a2d7a1f2d365c9a99fde33d157517c1d66324e Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Tue, 17 May 2022 15:05:01 +0200 Subject: [PATCH] Bug 30790: Add REST API route to list biblios Examples: GET /api/v1/biblios GET /api/v1/biblios?q={"title": "foo"} GET /api/v1/biblios?q={"isbn": "1-23-456789-0"} GET /api/v1/biblios?_order_by=title Test plan: 1. Try requesting this endpoint with your favorite API tool 2. Run `prove t/db_dependent/api/v1/biblios/list.t` --- Koha/REST/V1/Biblios.pm | 24 ++++++++ api/v1/swagger/paths/biblios.yaml | 40 +++++++++++++ api/v1/swagger/swagger.yaml | 2 + t/db_dependent/api/v1/biblios/list.t | 89 ++++++++++++++++++++++++++++ t/lib/TestBuilder.pm | 7 +++ 5 files changed, 162 insertions(+) create mode 100644 t/db_dependent/api/v1/biblios/list.t diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm index c74f5180c6..4403e3ffbb 100644 --- a/Koha/REST/V1/Biblios.pm +++ b/Koha/REST/V1/Biblios.pm @@ -32,6 +32,30 @@ use Try::Tiny qw( catch try ); =head2 Methods +=head3 list + +Retrieves a list of biblios + +=cut + +sub list { + my $c = shift->openapi->valid_input or return; + + return try { + + my $biblios_rs = Koha::Biblios->new->search(undef, { join => 'biblioitem' }); + my $biblios = $c->objects->search( $biblios_rs ); + + return $c->render( + status => 200, + openapi => $biblios, + ); + } + catch { + $c->unhandled_exception($_); + }; +} + =head3 get Controller function that handles retrieving a single biblio object diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml index 60e4e951a4..85172e53c0 100644 --- a/api/v1/swagger/paths/biblios.yaml +++ b/api/v1/swagger/paths/biblios.yaml @@ -1,4 +1,44 @@ --- +"/biblios": + get: + x-mojo-to: Biblios#list + operationId: listBiblios + tags: + - biblios + summary: List biblios + parameters: + - $ref: "../swagger.yaml#/parameters/match" + - $ref: "../swagger.yaml#/parameters/order_by" + - $ref: "../swagger.yaml#/parameters/page" + - $ref: "../swagger.yaml#/parameters/per_page" + - $ref: "../swagger.yaml#/parameters/q_param" + produces: + - application/json + responses: + "200": + description: A biblio + "401": + description: Authentication required + schema: + $ref: "../swagger.yaml#/definitions/error" + "403": + description: Access forbidden + schema: + $ref: "../swagger.yaml#/definitions/error" + "500": + description: | + Internal server error. Possible `error_code` attribute values: + + * `internal_server_error` + schema: + $ref: "../swagger.yaml#/definitions/error" + "503": + description: Under maintenance + schema: + $ref: "../swagger.yaml#/definitions/error" + x-koha-authorization: + permissions: + catalogue: "1" "/biblios/{biblio_id}": get: x-mojo-to: Biblios#get diff --git a/api/v1/swagger/swagger.yaml b/api/v1/swagger/swagger.yaml index 1ec3a5687d..98ba7a3823 100644 --- a/api/v1/swagger/swagger.yaml +++ b/api/v1/swagger/swagger.yaml @@ -93,6 +93,8 @@ paths: $ref: "./paths/advancededitormacros.yaml#/~1advanced_editor~1macros~1{advancededitormacro_id}" "/article_requests/{article_request_id}": $ref: "./paths/article_requests.yaml#/~1article_requests~1{article_request_id}" + "/biblios": + $ref: "./paths/biblios.yaml#/~1biblios" "/biblios/{biblio_id}": $ref: "./paths/biblios.yaml#/~1biblios~1{biblio_id}" "/biblios/{biblio_id}/checkouts": diff --git a/t/db_dependent/api/v1/biblios/list.t b/t/db_dependent/api/v1/biblios/list.t new file mode 100644 index 0000000000..ce298810fb --- /dev/null +++ b/t/db_dependent/api/v1/biblios/list.t @@ -0,0 +1,89 @@ +#!/usr/bin/env perl + +# 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 . + +use Modern::Perl; + +use utf8; +use Encode; + +use Test::More tests => 1; +use Test::MockModule; +use Test::Mojo; +use Test::Warn; +use JSON; + +use t::lib::Mocks; +use t::lib::TestBuilder; + +use C4::Auth; + +use Koha::Biblios; +use Koha::Database; + +my $schema = Koha::Database->new->schema; +my $builder = t::lib::TestBuilder->new; + +t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 ); + +my $t = Test::Mojo->new('Koha::REST::V1'); + +subtest 'get() tests' => sub { + plan tests => 13; + + $schema->storage->txn_begin; + $schema->resultset('Biblio')->delete(); + + my $patron = $builder->build_object( + { + class => 'Koha::Patrons', + value => { flags => 0 } + } + ); + my $password = 'thePassword123'; + $patron->set_password( { password => $password, skip_validation => 1 } ); + $patron->discard_changes; + my $userid = $patron->userid; + + my $biblio = $builder->build_sample_biblio({ + title => 'The unbearable lightness of being', + author => 'Milan Kundera', + isbn => '0-06-093213-9', + }); + $t->get_ok("//$userid:$password@/api/v1/biblios") + ->status_is(403); + + $patron->flags(4)->store; + + $t->get_ok("//$userid:$password@/api/v1/biblios") + ->status_is(200) + ->json_is( '/0/title', 'The unbearable lightness of being' ) + ->json_is( '/0/author', 'Milan Kundera' ) + ->json_is( '/0/isbn', '0-06-093213-9' ); + + # Test the ability to filter using biblioitems columns + my $api_filter = encode_json({'isbn' => '123'}); + $t->get_ok("//$userid:$password@/api/v1/biblios?q=$api_filter") + ->status_is(200) + ->json_hasnt('/0'); + + $api_filter = encode_json({'isbn' => '0-06-093213-9'}); + $t->get_ok("//$userid:$password@/api/v1/biblios?q=$api_filter") + ->status_is(200) + ->json_is('/0/isbn', '0-06-093213-9'); + + $schema->storage->txn_rollback; +}; diff --git a/t/lib/TestBuilder.pm b/t/lib/TestBuilder.pm index bf25c89693..6b8913e2aa 100644 --- a/t/lib/TestBuilder.pm +++ b/t/lib/TestBuilder.pm @@ -166,6 +166,13 @@ sub build_sample_biblio { MARC::Field->new( $tag, ' ', ' ', $subfield => $author ), ); + if ($args->{isbn}) { + ( $tag, $subfield ) = $marcflavour eq 'UNIMARC' ? ( '010', 'a' ) : ( '020', 'a' ); + $record->append_fields( + MARC::Field->new( $tag, ' ', ' ', $subfield => $args->{isbn} ), + ); + } + ( $tag, $subfield ) = $marcflavour eq 'UNIMARC' ? ( 995, 'r' ) : ( 942, 'c' ); $record->append_fields( MARC::Field->new( $tag, ' ', ' ', $subfield => $itemtype ) -- 2.30.2