From 83f676f5930f08d58b2583ab13854ec6bf973cc0 Mon Sep 17 00:00:00 2001
From: Tomas Cohen Arazi <tomascohen@theke.io>
Date: Thu, 26 Sep 2019 16:23:41 -0300
Subject: [PATCH] Bug 23677: Controller method and dependencies tweak

Signed-off-by: Arthur Suzuki <arthur.suzuki@biblibre.com>
---
 C4/Installer/PerlDependencies.pm |   5 ++
 Koha/REST/V1/Biblios.pm          | 165 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 169 insertions(+), 1 deletion(-)

diff --git a/C4/Installer/PerlDependencies.pm b/C4/Installer/PerlDependencies.pm
index f7244744d9..3c130d05d6 100644
--- a/C4/Installer/PerlDependencies.pm
+++ b/C4/Installer/PerlDependencies.pm
@@ -477,6 +477,11 @@ our $PERL_DEPS = {
         'required' => '1',
         'min_ver'  => '1.86'
     },
+    'MARC::Record::MiJ' => {
+        'usage'    => 'Core',
+        'required' => '1',
+        'min_ver'  => '0.04'
+    },
     'MARC::File::XML' => {
         'usage'    => 'Core',
         'required' => '1',
diff --git a/Koha/REST/V1/Biblios.pm b/Koha/REST/V1/Biblios.pm
index 6e8da01f82..b3cba7c8d3 100644
--- a/Koha/REST/V1/Biblios.pm
+++ b/Koha/REST/V1/Biblios.pm
@@ -22,14 +22,89 @@ use Mojo::Base 'Mojolicious::Controller';
 use Koha::Biblios;
 use C4::Biblio qw(DelBiblio);
 
+use MARC::Record::MiJ;
+
 use Try::Tiny;
 
 =head1 API
 
-=head2 Class Methods
+=head2 Class methods
+
+=head3 get
+
+Controller function that handles retrieving a single biblio object
+
+=cut
+
+sub get {
+    my $c = shift->openapi->valid_input or return;
+
+    my $attributes;
+    $attributes = { prefetch => [ 'metadata' ] } # don't prefetch metadata if not needed
+        unless $c->req->headers->accept =~ m/application\/json/;
+
+    my $biblio = Koha::Biblios->find( { biblionumber => $c->validation->param('biblio_id') }, $attributes );
+
+    unless ( $biblio ) {
+        return $c->render(
+            status  => 404,
+            openapi => {
+                error => "Object not found."
+            }
+        );
+    }
+
+    return try {
+
+        if ( $c->req->headers->accept =~ m/application\/json/ ) {
+            return $c->render(
+                status => 200,
+                json   => $c->build_json_biblio( { biblio => $biblio } )
+            );
+        }
+        else {
+            my $record = $biblio->metadata->record;
+
+            $c->respond_to(
+                marcxml => {
+                    status => 200,
+                    format => 'marcxml',
+                    text   => $record->as_xml_record
+                },
+                mij => {
+                    status => 200,
+                    format => 'mij',
+                    text   => $record->to_mij
+                },
+                marc => {
+                    status => 200,
+                    format => 'marc',
+                    text   => $record->as_usmarc
+                },
+                any => {
+                    status  => 406,
+                    openapi => [
+                        "application/json",
+                        "application/marcxml+xml",
+                        "application/marc-in-json",
+                        "application/marc"
+                    ]
+                }
+            );
+        }
+    }
+    catch {
+        return $c->render(
+            status  => 500,
+            openapi => { error => "Something went wrong, check the logs ($_)" }
+        );
+    };
+}
 
 =head3 delete
 
+Controller function that handles deleting a biblio object
+
 =cut
 
 sub delete {
@@ -73,4 +148,92 @@ sub delete {
     };
 }
 
+=head2 Internal methods
+
+
+=head3 _to_api
+
+Helper function that maps unblessed Koha::Patron objects into REST api
+attribute names.
+
+=cut
+
+sub _to_api {
+    my $biblio = shift;
+
+    # Rename attributes
+    foreach my $column ( keys %{$Koha::REST::V1::Biblios::to_api_mapping} ) {
+        my $mapped_column = $Koha::REST::V1::Biblios::to_api_mapping->{$column};
+        if ( exists $biblio->{$column}
+            && defined $mapped_column )
+        {
+            # key != undef
+            $biblio->{$mapped_column} = delete $biblio->{$column};
+        }
+        elsif ( exists $biblio->{$column}
+            && !defined $mapped_column )
+        {
+            # key == undef
+            delete $biblio->{$column};
+        }
+    }
+
+    return $biblio;
+}
+
+
+=head3 build_json_biblio
+
+Internal method that returns all the attributes from the biblio and biblioitems tables
+
+=cut
+
+sub build_json_biblio {
+    my ( $c, $args ) = @_;
+
+    my $biblio = $args->{biblio};
+
+    my $response = $biblio->TO_JSON;
+    my $biblioitem = $biblio->biblioitem->TO_JSON;
+
+    foreach my $key ( keys %{ $biblioitem } ) {
+        $response->{$key} = $biblioitem->{$key};
+    }
+
+    return _to_api($response);
+}
+
+
+=head2 Global variables
+
+=head3 $to_api_mapping
+
+=cut
+
+our $to_api_mapping = {
+    agerestriction   => 'age_restriction',
+    biblioitemnumber => undef, # meaningless
+    biblionumber     => 'biblio_id',
+    collectionissn   => 'collection_issn',
+    collectiontitle  => 'collection_title',
+    collectionvolume => 'collection_volume',
+    copyrightdate    => 'copyright_date',
+    datecreated      => 'creation_date',
+    editionresponsibility => undef, # obsolete, not mapped
+    editionstatement => 'edition_statement',
+    frameworkcode    => 'framework_id',
+    illus            => 'illustrations',
+    itemtype         => 'item_type',
+    lccn             => 'lc_control_number',
+    place            => 'publication_place',
+    publicationyear  => 'publication_year',
+    publishercode    => 'publisher',
+    seriestitle      => 'series_title',
+    size             => 'material_size',
+    totalissues      => 'serial_total_issues',
+    unititle         => 'uniform_title',
+    volumedate       => 'volume_date',
+    volumedesc       => 'volume_description',
+};
+
 1;
-- 
2.11.0