From de166b38da819c2c676daecee32e88a67cc0e437 Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Thu, 7 Jan 2021 08:50:43 -0300
Subject: [PATCH] Bug 27358: Add GET /public/biblios/:biblio_id/items

This patch introduces a route to fetch items belonging to a biblio. It
is expected to return the 'public' representation of the Koha::Item
objects.

It is also enforcing the visibility rules, by using
Koha::Items->filter_by_visible_in_opac.

To test:
1. Apply this patches
2. Run:
   $ kshell
  k$ prove t/db_dependent/api/v1/biblios.t
=> SUCCESS: Test pass and they cover all the cases!
3. Try your favourite REST tool against the new route.
4. Sign off :-D
---
 Koha/REST/V1/Biblios.pm           | 37 ++++++++++++
 api/v1/swagger/paths.json         |  3 +
 api/v1/swagger/paths/biblios.json | 93 +++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+)

diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm
index efe7c5dfe8..aee31fc74e 100644
--- a/Koha/REST/V1/Biblios.pm
+++ b/Koha/REST/V1/Biblios.pm
@@ -268,4 +268,41 @@ sub get_items {
     };
 }
 
+=head3 get_items_public
+
+Controller function that handles retrieving biblio's items, for unprivileged
+access.
+
+=cut
+
+sub get_items_public {
+    my $c = shift->openapi->valid_input or return;
+
+    my $biblio = Koha::Biblios->find( { biblionumber => $c->validation->param('biblio_id') }, { prefetch => ['items'] } );
+
+    unless ( $biblio ) {
+        return $c->render(
+            status  => 404,
+            openapi => {
+                error => "Object not found."
+            }
+        );
+    }
+
+    return try {
+
+        my $patron = $c->stash('koha.user');
+
+        my $items_rs = $biblio->items->filter_by_visible_in_opac({ patron => $patron });
+        my $items    = $c->objects->search( $items_rs );
+        return $c->render(
+            status  => 200,
+            openapi => $items
+        );
+    }
+    catch {
+        $c->unhandled_exception($_);
+    };
+}
+
 1;
diff --git a/api/v1/swagger/paths.json b/api/v1/swagger/paths.json
index e871e54ed4..50b0a9ee2b 100644
--- a/api/v1/swagger/paths.json
+++ b/api/v1/swagger/paths.json
@@ -128,6 +128,9 @@
   "/public/biblios/{biblio_id}": {
     "$ref": "paths/biblios.json#/~1public~1biblios~1{biblio_id}"
   },
+  "/public/biblios/{biblio_id}/items": {
+    "$ref": "paths/biblios.json#/~1public~1biblios~1{biblio_id}~1items"
+  },
   "/public/patrons/{patron_id}/password": {
     "$ref": "paths/public_patrons.json#/~1public~1patrons~1{patron_id}~1password"
   },
diff --git a/api/v1/swagger/paths/biblios.json b/api/v1/swagger/paths/biblios.json
index 0b95576204..31a259a3e0 100644
--- a/api/v1/swagger/paths/biblios.json
+++ b/api/v1/swagger/paths/biblios.json
@@ -296,5 +296,98 @@
         }
       }
     }
+  },
+  "/public/biblios/{biblio_id}/items": {
+    "get": {
+      "x-mojo-to": "Biblios#get_items_public",
+      "operationId": "getBiblioItemsPublic",
+      "tags": [
+        "biblios",
+        "items"
+      ],
+      "parameters": [
+        {
+          "$ref": "../parameters.json#/biblio_id_pp"
+        },
+        {
+          "$ref": "../parameters.json#/match"
+        },
+        {
+          "$ref": "../parameters.json#/order_by"
+        },
+        {
+          "$ref": "../parameters.json#/page"
+        },
+        {
+          "$ref": "../parameters.json#/per_page"
+        },
+        {
+          "$ref": "../parameters.json#/q_param"
+        },
+        {
+          "$ref": "../parameters.json#/q_body"
+        },
+        {
+          "$ref": "../parameters.json#/q_header"
+        }
+      ],
+      "consumes": [
+        "application/json"
+      ],
+      "produces": [
+        "application/json"
+      ],
+      "responses": {
+        "200": {
+          "description": "A list of the items attached to the record",
+          "schema": {
+            "type": "array",
+            "items": {
+              "$ref": "../definitions.json#/item"
+            }
+          }
+        },
+        "401": {
+          "description": "Authentication required",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "403": {
+          "description": "Access forbidden",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "404": {
+          "description": "Biblio not found",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "406": {
+          "description": "Not acceptable",
+          "schema": {
+            "type": "array",
+            "description": "Accepted content-types",
+            "items": {
+                "type": "string"
+            }
+          }
+        },
+        "500": {
+          "description": "Internal server error",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        },
+        "503": {
+          "description": "Under maintenance",
+          "schema": {
+            "$ref": "../definitions.json#/error"
+          }
+        }
+      }
+    }
   }
 }
-- 
2.30.0