Bug 30719: DB and API
[koha.git] / Koha / REST / V1 / Authorities.pm
1 package Koha::REST::V1::Authorities;
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Mojo::Base 'Mojolicious::Controller';
21
22 use Koha::Authorities;
23 use C4::AuthoritiesMarc qw( DelAuthority AddAuthority FindDuplicateAuthority ModAuthority);
24
25 use List::MoreUtils qw( any );
26 use MARC::Record::MiJ;
27
28 use Try::Tiny qw( catch try );
29
30 =head1 API
31
32 =head2 Methods
33
34 =head3 get
35
36 Controller function that handles retrieving a single authority object
37
38 =cut
39
40 sub get {
41     my $c = shift->openapi->valid_input or return;
42
43     my $authority = Koha::Authorities->find( { authid => $c->param('authority_id') } );
44     unless ( $authority ) {
45         return $c->render(
46             status  => 404,
47             openapi => {
48                 error => "Object not found."
49             }
50         );
51     }
52
53     return try {
54
55         if ( $c->req->headers->accept =~ m/application\/json/ ) {
56             return $c->render(
57                 status => 200,
58                 json   => $authority->to_api
59             );
60         }
61         else {
62             my $record = $authority->record;
63
64             $c->respond_to(
65                 marcxml => {
66                     status => 200,
67                     format => 'marcxml',
68                     text   => $record->as_xml_record
69                 },
70                 mij => {
71                     status => 200,
72                     format => 'mij',
73                     data   => $record->to_mij
74                 },
75                 marc => {
76                     status => 200,
77                     format => 'marc',
78                     text   => $record->as_usmarc
79                 },
80                 txt => {
81                     status => 200,
82                     format => 'text/plain',
83                     text   => $record->as_formatted
84                 },
85                 any => {
86                     status  => 406,
87                     openapi => [
88                         "application/json",
89                         "application/marcxml+xml",
90                         "application/marc-in-json",
91                         "application/marc",
92                         "text/plain"
93                     ]
94                 }
95             );
96         }
97     }
98     catch {
99         $c->unhandled_exception($_);
100     };
101 }
102
103 =head3 delete
104
105 Controller function that handles deleting an authority object
106
107 =cut
108
109 sub delete {
110     my $c = shift->openapi->valid_input or return;
111
112     my $authority = Koha::Authorities->find( { authid => $c->param('authority_id') } );
113
114     if ( not defined $authority ) {
115         return $c->render(
116             status  => 404,
117             openapi => { error => "Object not found" }
118         );
119     }
120
121     return try {
122         DelAuthority( { authid => $authority->authid } );
123
124         return $c->render( status => 204, openapi => q{} );
125     }
126     catch {
127         $c->unhandled_exception($_);
128     };
129 }
130
131 =head3 add
132
133 Controller function that handles creating an authority object
134
135 =cut
136
137 sub add {
138     my $c = shift->openapi->valid_input or return;
139
140     try {
141         my $headers   = $c->req->headers;
142         my $overrides = $c->stash('koha.overrides');
143
144         my $flavour =
145             C4::Context->preference('marcflavour') eq 'UNIMARC'
146             ? 'UNIMARCAUTH'
147             : 'MARC21';
148
149         my $record;
150
151         my $authtypecode = $headers->header('x-authority-type');
152         my $content_type = $headers->content_type;
153
154         if ( $content_type =~ m/application\/marcxml\+xml/ ) {
155             $record = MARC::Record->new_from_xml( $c->req->body, 'UTF-8', $flavour );
156         } elsif ( $content_type =~ m/application\/marc-in-json/ ) {
157             $record = MARC::Record->new_from_mij_structure( $c->req->json );
158         } elsif ( $content_type =~ m/application\/marc/ ) {
159             $record = MARC::Record->new_from_usmarc( $c->req->body );
160         } else {
161             return $c->render(
162                 status  => 406,
163                 openapi => [
164                     "application/marcxml+xml",
165                     "application/marc-in-json",
166                     "application/marc"
167                 ]
168             );
169         }
170
171         unless ( $overrides->{any} || $overrides->{duplicate} ) {
172             my ( $duplicateauthid, $duplicateauthvalue ) = C4::AuthoritiesMarc::FindDuplicateAuthority( $record, $authtypecode );
173
174             return $c->render(
175                 status  => 409,
176                 openapi => {
177                     error      => "Duplicate record ($duplicateauthid)",
178                     error_code => 'duplicate',
179                 }
180             ) unless !$duplicateauthid;
181         }
182
183         my $authid = AddAuthority( $record, undef, $authtypecode );
184
185         $c->res->headers->location($c->req->url->to_string . '/' . $authid);
186         $c->render(
187             status  => 201,
188             openapi => q{},
189         );
190     }
191     catch {
192         $c->unhandled_exception($_);
193     };
194 }
195
196
197 =head3 update
198
199 Controller function that handles modifying an authority object
200
201 =cut
202
203 sub update {
204     my $c = shift->openapi->valid_input or return;
205
206     my $authid = $c->param('authority_id');
207     my $authority = Koha::Authorities->find( { authid => $authid } );
208
209     if ( not defined $authority ) {
210         return $c->render(
211             status  => 404,
212             openapi => { error => "Object not found" }
213         );
214     }
215
216     try {
217         my $headers = $c->req->headers;
218
219         my $flavour =
220             C4::Context->preference('marcflavour') eq 'UNIMARC'
221             ? 'UNIMARCAUTH'
222             : 'MARC21';
223
224         my $record;
225         my $authtypecode = $headers->header('x-authority-type') || $authority->authtypecode;
226         if ( $c->req->headers->content_type =~ m/application\/marcxml\+xml/ ) {
227             $record = MARC::Record->new_from_xml( $c->req->body, 'UTF-8', $flavour );
228         } elsif ( $c->req->headers->content_type =~ m/application\/marc-in-json/ ) {
229             $record = MARC::Record->new_from_mij_structure( $c->req->json );
230         } elsif ( $c->req->headers->content_type =~ m/application\/marc/ ) {
231             $record = MARC::Record->new_from_usmarc( $c->req->body );
232         } else {
233             return $c->render(
234                 status  => 406,
235                 openapi => [
236                     "application/json",
237                     "application/marcxml+xml",
238                     "application/marc-in-json",
239                     "application/marc"
240                 ]
241             );
242         }
243
244         my $authid = ModAuthority( $authid, $record, $authtypecode );
245
246         $c->render(
247             status  => 200,
248             openapi => { id => $authid }
249         );
250     }
251     catch {
252         $c->unhandled_exception($_);
253     };
254 }
255
256 =head3 list
257
258 Controller function that handles retrieving a list of authorities
259
260 =cut
261
262 sub list {
263     my $c = shift->openapi->valid_input or return;
264
265     my $authorities = $c->objects->search_rs( Koha::Authorities->new );
266
267     return try {
268
269         if ( $c->req->headers->accept =~ m/application\/json(;.*)?$/ ) {
270             return $c->render(
271                 status => 200,
272                 json   => $authorities->to_api
273             );
274         }
275         elsif (
276             $c->req->headers->accept =~ m/application\/marcxml\+xml(;.*)?$/ )
277         {
278             $c->res->headers->add( 'Content-Type', 'application/marcxml+xml' );
279             return $c->render(
280                 status => 200,
281                 text   => $authorities->print_collection('marcxml')
282             );
283         }
284         elsif (
285             $c->req->headers->accept =~ m/application\/marc-in-json(;.*)?$/ )
286         {
287             $c->res->headers->add( 'Content-Type', 'application/marc-in-json' );
288             return $c->render(
289                 status => 200,
290                 data   => $authorities->print_collection('mij')
291             );
292         }
293         elsif ( $c->req->headers->accept =~ m/application\/marc(;.*)?$/ ) {
294             $c->res->headers->add( 'Content-Type', 'application/marc' );
295             return $c->render(
296                 status => 200,
297                 text   => $authorities->print_collection('marc')
298             );
299         }
300         elsif ( $c->req->headers->accept =~ m/text\/plain(;.*)?$/ ) {
301             return $c->render(
302                 status => 200,
303                 text   => $authorities->print_collection('txt')
304             );
305         }
306         else {
307             return $c->render(
308                 status  => 406,
309                 openapi => [
310                     "application/json",         "application/marcxml+xml",
311                     "application/marc-in-json", "application/marc",
312                     "text/plain"
313                 ]
314             );
315         }
316     }
317     catch {
318         $c->unhandled_exception($_);
319     };
320 }
321
322 1;