File Coverage

blib/lib/Museum/Rijksmuseum/Object.pm
Criterion Covered Total %
statement 27 59 45.7
branch 0 12 0.0
condition n/a
subroutine 9 14 64.2
pod 3 3 100.0
total 39 88 44.3


line stmt bran cond sub pod time code
1             package Museum::Rijksmuseum::Object;
2              
3 1     1   105828 use strictures 2;
  1         1609  
  1         42  
4              
5 1     1   187 use Carp;
  1         2  
  1         50  
6 1     1   527 use JSON::MaybeXS;
  1         7927  
  1         59  
7 1     1   789 use LWP::UserAgent;
  1         52600  
  1         54  
8 1     1   691 use Moo;
  1         6899  
  1         8  
9 1     1   1525 use URI;
  1         3  
  1         28  
10 1     1   499 use URI::Encode qw( uri_encode );
  1         16590  
  1         76  
11 1     1   437 use URI::QueryParam;
  1         95  
  1         31  
12              
13 1     1   474 use namespace::clean;
  1         13883  
  1         6  
14              
15             =head1 NAME
16              
17             Museum::Rijksmuseum::Object - Access the Rijksmuseum object metadata API
18              
19             =head1 VERSION
20              
21             Version 0.03
22              
23             =cut
24              
25             our $VERSION = '0.03';
26              
27              
28             =head1 SYNOPSIS
29              
30             Access the collection, collection details, and collection image endpoints of the Rijksmuseum "Rijksdata" API.
31              
32             use Museum::Rijksmuseum::Object;
33              
34             my $api = Museum::Rijksmuseum::Object->new( key => 'abc123xyz', culture => 'en' );
35             my $search_result = $api->search( involvedMaker => 'Rembrandt van Rijn' );
36             die $search_result->{error} if $search_result->{error};
37             print "Results: $search_result->{count}\n";
38             for my $item ( $search_result->{artObjects}->@* ) {
39             print "Id: $item->{id}\n";
40             }
41              
42             Refer to the L<Rijksmuseum API documentation|https://data.rijksmuseum.nl/object-metadata/api/>
43             for information on query and response formats. Be aware that the API expects
44             camelCase on its parameters and this module follows this convention.
45              
46             =head1 SUBROUTINES/METHODS
47              
48             =head2 new
49              
50             my $api = Museum::Rijksmuseum::Object->new(
51             key => 'abc123xyz', # the API key supplied by the Rijksmuseum
52             culture => 'en', # the 'culture' parameter, determines the
53             # language for searching and results
54             );
55              
56             Creates a new object instance. The C<key> and C<culture> parameters are required.
57              
58             =cut
59              
60             =head2 search
61              
62             my $result = $api->search(
63             p => 3, # page 3
64             ps => 10, # 10 results per page
65             q => 'vermeer', # a general search term
66             imgonly => 1, # image only?
67             );
68              
69             Searches the collection. See the API documentation for parameter details.
70              
71             =cut
72              
73             sub search {
74 0     0 1   my ( $self, %params ) = @_;
75              
76 0           my $url = $self->_build_url( {}, \%params );
77 0           return $self->_fetch_url($url);
78             }
79              
80             =head2 fetch
81              
82             my $result = $api->fetch('SK-C-5');
83              
84             Fetches an individual item from the collection. The parameter is the
85             C<objectNumber> as returned by the C<search> call.
86              
87             =cut
88              
89             sub fetch {
90 0     0 1   my ( $self, $object_number ) = @_;
91              
92 0 0         carp "An object number must be provided to 'fetch'" unless defined $object_number;
93 0           my $url = $self->_build_url( { object_number => $object_number }, {} );
94 0           return $self->_fetch_url($url);
95             }
96              
97             =head2 image_info
98              
99             my $result = $api->image_info('SK-C-5');
100              
101             Fetches the information required to build the image tiles for a particular
102             C<objectNumber>.
103              
104             =cut
105              
106             sub image_info {
107 0     0 1   my ( $self, $object_number ) = @_;
108              
109 0 0         carp "An object number must be provided to 'image_info'" unless defined $object_number;
110 0           my $url = $self->_build_url(
111             {
112             object_number => $object_number,
113             tiles => 1,
114             },
115             {}
116             );
117 0           return $self->_fetch_url($url);
118             }
119              
120             sub _build_url {
121 0     0     my ( $self, $path, $params ) = @_;
122              
123             # Determine which URL form we need
124 0           my $url;
125 0 0         if ( $path->{tiles} ) {
    0          
126             $url = sprintf(
127             'https://www.rijksmuseum.nl/api/%s/collection/%s/tiles',
128             uri_encode( $self->culture ),
129             uri_encode( $path->{object_number} )
130 0           );
131             } elsif ( $path->{object_number} ) {
132             $url = sprintf(
133             'https://www.rijksmuseum.nl/api/%s/collection/%s',
134             uri_encode( $self->culture ),
135             uri_encode( $path->{object_number} )
136 0           );
137             } else {
138 0           $url =
139             sprintf( 'https://www.rijksmuseum.nl/api/%s/collection', uri_encode( $self->culture ) );
140             }
141 0           $url = URI->new($url);
142              
143             # Add query parameters
144 0           $url->query_param( key => $self->key );
145 0 0         if ($params) {
146 0           for my $p ( keys %$params ) {
147 0           $url->query_param( $p => $params->{$p} );
148             }
149             }
150              
151 0           return $url->as_string;
152             }
153              
154             sub _fetch_url {
155 0     0     my ( $self, $url ) = @_;
156              
157 0           my $ua = LWP::UserAgent->new;
158 0           $ua->agent("Museum::Rijksmuseum::Object/$VERSION");
159              
160 0           my $req = HTTP::Request->new( GET => $url );
161              
162 0           my $res = $ua->request($req);
163 0 0         if ( $res->is_success ) {
164 0           my $json = JSON::MaybeXS->new();
165 0           return $json->decode( $res->content );
166             } else {
167 0           return { error => $res->status_line };
168             }
169             }
170              
171             =head1 ATTRIBUTES
172              
173             =head2 key
174              
175             The API key provided by the Rijksmuseum.
176              
177             =cut
178              
179             has key => (
180             is => 'rw',
181             required => 1,
182             );
183              
184             =head2 culture
185              
186             The 'culture' that the API will return data to you in, and perform searches in.
187             Typically 'en' or 'nl'.
188              
189             =cut
190              
191             has culture => (
192             is => 'rw',
193             required => 1
194             );
195              
196             =head1 SEE ALSO
197              
198             For bulk-ingestion of data using the Rijksmuseum OAI-PMH API, see
199             L<Museum::Rijksmuseum::Object::Harvester>.
200              
201             =head1 AUTHOR
202              
203             Robin Sheat, C<< <rsheat at cpan.org> >>
204              
205             =head1 TODO
206              
207             =over 4
208              
209             =item Make a heavier interface
210              
211             At the moment this is a very thin interface over the Rijksmuseum API. It could
212             be improved by having helpers to do things, for example optionally
213             automatically fetching and stitching images.
214              
215             =back
216              
217             =cut
218              
219             =head1 BUGS
220              
221             Please report any bugs or feature requests to C<bug-museum-rijksmuseum-object at rt.cpan.org>, or through
222             the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Museum-Rijksmuseum-Object>. I will be notified, and then you'll
223             automatically be notified of progress on your bug as I make changes.
224              
225             Alternately, use the tracker on the repository page at L<https://gitlab.com/eythian/museum-rijksmuseum-object>.
226              
227              
228             =head1 SUPPORT
229              
230             You can find documentation for this module with the perldoc command.
231              
232             perldoc Museum::Rijksmuseum::Object
233              
234              
235             You can also look for information at:
236              
237             =over 4
238              
239             =item * Repository page (report bugs here)
240              
241             L<https://gitlab.com/eythian/museum-rijksmuseum-object>
242              
243             =item * RT: CPAN's request tracker (or here)
244              
245             L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Museum-Rijksmuseum-Object>
246              
247             =item * CPAN Ratings
248              
249             L<https://cpanratings.perl.org/d/Museum-Rijksmuseum-Object>
250              
251             =item * Search CPAN
252              
253             L<https://metacpan.org/release/Museum-Rijksmuseum-Object>
254              
255              
256             =back
257              
258              
259             =head1 ACKNOWLEDGEMENTS
260              
261              
262             =head1 LICENSE AND COPYRIGHT
263              
264             This software is Copyright (c) 2023 by Robin Sheat.
265              
266             This is free software, licensed under:
267              
268             The Artistic License 2.0 (GPL Compatible)
269              
270              
271             =cut
272              
273             1; # End of Museum::Rijksmuseum::Object