File Coverage

blib/lib/WebService/MusicBrainz.pm
Criterion Covered Total %
statement 55 58 94.8
branch 20 24 83.3
condition 5 6 83.3
subroutine 5 5 100.0
pod 1 2 50.0
total 86 95 90.5


line stmt bran cond sub pod time code
1             package WebService::MusicBrainz;
2              
3 5     5   398939 use strict;
  5         59  
  5         196  
4 5     5   2651 use Mojo::Base -base;
  5         759772  
  5         47  
5 5     5   4416 use WebService::MusicBrainz::Request;
  5         18  
  5         47  
6              
7             our $VERSION = '1.0.4';
8              
9             has 'request';
10             has valid_resources =>
11             sub { [ 'area', 'artist', 'discid', 'label', 'recording', 'release', 'release_group' ] };
12             has relationships => sub {
13             my $rels = [
14             'area-rels', 'artist-rels', 'event-rels', 'instrument-rels',
15             'label-rels', 'place-rels', 'recording-rels', 'release-rels',
16             'release-group-rels', 'series-rels', 'url-rels', 'work-rels'
17             ];
18             return $rels;
19             };
20              
21             # inc subqueries
22             our %subquery_map = (
23             _modifiers => [qw(discids media isrcs artist-credits various-artists)],
24             _misc => [qw(aliases annotation tags ratings user-tags user-ratings)],
25             artist => [qw(recordings releases release-groups works)],
26             discid => [qw(artists artist-credits collections labels recordings release-groups)],
27             label => [qw(releases)],
28             recording => [qw(artists releases)],
29             release => [qw(artists collections labels recordings release-groups)],
30             release_group => [qw(artists releases)],
31             );
32              
33             has search_fields_by_resource => sub {
34             my %search_fields;
35              
36             $search_fields{area} = [
37             'aid', 'alias', 'area', 'begin', 'comment', 'end', 'ended', 'sortname',
38             'iso', 'iso1', 'iso2', 'iso3', 'type'
39             ];
40             $search_fields{artist} = [
41             'area', 'beginarea', 'endarea', 'arid', 'artist', 'artistaccent',
42             'alias', 'begin', 'comment', 'country', 'end', 'ended',
43             'gender', 'ipi', 'sortname', 'tag', 'type'
44             ];
45             $search_fields{discid} = ['discid'];
46             $search_fields{label} = [
47             'alias', 'area', 'begin', 'code', 'comment', 'country',
48             'end', 'ended', 'ipi', 'label', 'labelaccent', 'laid',
49             'sortname', 'type', 'tag'
50             ];
51             $search_fields{recording} = [
52             'arid', 'artist', 'artistname', 'creditname',
53             'comment', 'country', 'date', 'dur',
54             'format', 'isrc', 'number', 'position',
55             'primarytype', 'puid', 'qdur', 'recording',
56             'recordingaccent', 'reid', 'release', 'rgid',
57             'rid', 'secondarytype', 'status', 'tid',
58             'trnum', 'tracks', 'tracksrelease', 'tag',
59             'type', 'video'
60             ];
61             $search_fields{release_group} = [
62             'arid', 'artist', 'comment', 'creditname',
63             'primarytype', 'rgid', 'releasegroup', 'releasegroupaccent',
64             'releases', 'release', 'reid', 'secondarytype',
65             'status', 'tag', 'type'
66             ];
67             $search_fields{release} = [
68             'arid', 'artist', 'artistname', 'asin',
69             'barcode', 'catno', 'comment', 'country',
70             'creditname', 'date', 'discids', 'discidsmedium',
71             'format', 'laid', 'label', 'lang',
72             'mediums', 'primarytype', 'puid', 'quality',
73             'reid', 'release', 'releaseaccent', 'rgid',
74             'script', 'secondarytype', 'status', 'tag',
75             'tracks', 'tracksmedium', 'type'
76             ];
77             $search_fields{work}
78             = [ 'alias', 'arid', 'artist', 'comment', 'iswc', 'lang', 'tag', 'type', 'wid', 'work',
79             'workaccent' ];
80              
81             return \%search_fields;
82             };
83              
84             sub is_valid_subquery {
85 6     6 0 20 my $self = shift;
86 6         18 my $resource = shift;
87 6         16 my $subqueries = shift;
88              
89 6 50       23 return unless ($resource);
90              
91 6         29 my $resource_map = $subquery_map{$resource};
92 6 50       23 return if ( !$resource_map );
93              
94 162         528 my %valid_fields = map { $_ => 1 } (
95             @$resource_map,
96 6         37 @{ $subquery_map{_modifiers} },
97 6         26 @{ $subquery_map{_misc} },
98 6         21 @{ $self->relationships }
  6         37  
99             );
100              
101 6         35 foreach my $subquery (@$subqueries) {
102 7 100       44 return if ( !$valid_fields{$subquery} );
103             }
104              
105 5         39 return 1;
106             }
107              
108             sub search {
109 24     24 1 19026839 my $self = shift;
110 24         96 my $search_resource = shift;
111 24         83 my $search_query = shift;
112              
113 24         374 $self->request( WebService::MusicBrainz::Request->new() );
114              
115 24 50       14094 if ( !grep /^$search_resource$/, @{ $self->valid_resources() } ) {
  24         139  
116 0         0 die "Not a valid resource for search ($search_resource)";
117             }
118              
119 24         570 $self->request()->search_resource($search_resource);
120              
121 24 100       387 if ( exists $search_query->{mbid} ) {
122 11         48 $self->request()->mbid( $search_query->{mbid} );
123 11         135 delete $search_query->{mbid};
124             }
125              
126 24 50       113 if ( exists $search_query->{discid} ) {
127 0         0 $self->request()->discid( $search_query->{discid} );
128 0         0 delete $search_query->{discid};
129             }
130              
131 24         82 my $inc_subqueries = delete $search_query->{inc};
132             # only use "inc" parameters when a specific MBID or DISCID is given
133 24 100 66     92 if ( ( $self->request()->mbid() or $self->request()->discid() ) and $inc_subqueries ) {
      100        
134 6 100       126 $inc_subqueries = [$inc_subqueries] if ( !ref $inc_subqueries );
135              
136 6 100       39 if ( $self->is_valid_subquery( $search_resource, $inc_subqueries ) ) {
137 5         24 $self->request()->inc($inc_subqueries);
138             } else {
139 1         7 my $subquery_str = join ", ", @$inc_subqueries;
140 1         19 die "Not a valid \"inc\" subquery ($subquery_str) for resource: $search_resource";
141             }
142             }
143              
144 23 100       505 if ( exists $search_query->{fmt} ) {
145 3         13 $self->request()->format( $search_query->{fmt} );
146 3         39 delete $search_query->{fmt};
147             }
148              
149 23 100       114 if ( exists $search_query->{offset} ) {
150 1         4 $self->request()->offset( $search_query->{offset} );
151 1         10 delete $search_query->{offset};
152             }
153              
154 23         52 foreach my $search_field ( keys %{$search_query} ) {
  23         115  
155 20 100       190 if ( !grep /^$search_field$/, @{ $self->search_fields_by_resource->{$search_resource} } ) {
  20         88  
156 1         59 die "Not a valid search field ($search_field) for resource \"$search_resource\"";
157             }
158             }
159              
160 22         441 $self->request->query_params($search_query);
161              
162 22         296 my $request_result = $self->request()->result();
163              
164 22         148 return $request_result;
165             }
166              
167             =head1 NAME
168              
169             WebService::MusicBrainz
170              
171             =head1 SYNOPSIS
172              
173             use WebService::MusicBrainz;
174              
175             my $mb = WebService::MusicBrainz->new();
176              
177             my $result = $mb->search($resource => { $search_key => 'search value' });
178             my $result = $mb->search($resource => { $search_key => 'search value', fmt => 'json' }); # fmt => 'json' is default
179              
180             my $result_dom = $mb->search($resource => { $search_key => 'search value', fmt => 'xml' });
181              
182             =head1 DESCRIPTION
183              
184             API to search the musicbrainz.org database
185              
186             =head1 VERSION
187              
188             Version 1.0 and future releases are not backward compatible with pre-1.0 releases. This is a complete re-write using version 2.0 of the MusicBrainz API and Mojolicious.
189              
190             =head1 METHODS
191              
192             =head2 new
193              
194             my $mb = WebService::MusicBrainz->new();
195              
196             =head2 search
197              
198             my $result_list = $mb->search($resource => { param1 => 'value1' });
199              
200             my $result = $mb->search($resource => { mbid => 'mbid' });
201              
202             my $result_more = $mb->search($resource => { mbid => 'mbid', inc => 'extra stuff' });
203              
204             Valid values for $resource are: area, artist, event, instrument, label, recording, release, release-group, series, work, url
205             The default is to return decoded JSON as a perl data structure. Specify format => 'xml' to return the results as an instance of Mojo::DOM.
206              
207             =head3 Search by MBID
208              
209             my $result = $mb->search($resource => { mbid => 'xxxxxx' });
210              
211             The "inc" search parameter is only allowed when searching for any particular "mbid".
212              
213             =head3 Search area
214              
215             my $area_list_results = $mb_ws->search(area => { iso => 'US-OH' });
216             my $area_list_results = $mb_ws->search(area => { area => 'cincinnati' });
217             my $area_list_results = $mb_ws->search(area => { alias => 'new york' });
218             my $area_list_results = $mb_ws->search(area => { sortname => 'new york' });
219             my $area_list_results = $mb_ws->search(area => { area => 'new york', type => 'city' });
220              
221             my $area_result = $mb_ws->search(area => { mbid => '0573177b-9ff9-4643-80bc-ed2513419267' });
222             my $area_result = $mb_ws->search(area => { mbid => '0573177b-9ff9-4643-80bc-ed2513419267', inc => 'area-rels' });
223              
224             =head3 Search artist
225              
226             # JSON example
227             my $artists = $mb->search(artist => { artist => 'Ryan Adams' });
228             my $artists = $mb->search(artist => { artist => 'Ryan Adams', type => 'person' });
229              
230             my $artist_country = $artists->{artists}->[0]->{country};
231              
232             # XML example
233             my $artists = $mb->search(artist => { artist => 'Ryan Adams', type => 'person', fmt => 'xml' });
234              
235             my $artist_country = $artists->at('country')->text;
236              
237             # find this particular artist
238             my $artist = $mb->search(artist => { mbid => '5c2d2520-950b-4c78-84fc-78a9328172a3' });
239              
240             # find this particular artist and include release and artist relations (members of the band)
241             my $artist = $mb->search(artist => { mbid => '5c2d2520-950b-4c78-84fc-78a9328172a3', inc => ['releases','artist-rels'] });
242              
243             # artists that started in Cincinnati
244             my $artists = $mb->search(artist => { beginarea => 'Cincinnati' });
245              
246             =head3 Search label
247              
248             my $labels = $mb->search(label => { label => 'Death' });
249              
250             =head3 Search recording
251              
252             my $recordings = $mb->search(recording => { artist => 'Taylor Swift' });
253              
254             =head3 Search release
255              
256             my $releases = $mb->search(release => { release => 'Love Is Hell', status => 'official' });
257             print "RELEASE COUNT: ", $releases->{count}, "\n";
258              
259             =head1 DEBUG
260              
261             Set environment variable MUSICBRAINZ_DEBUG=1
262              
263             =over 1
264              
265             =item
266              
267             The URL that is generated for the search will output to STDOUT.
268              
269             =item
270              
271             The formatted output (JSON or XML) will be output to STDOUT
272              
273             =back
274              
275             =head1 AUTHOR
276              
277             =over 4
278              
279             =item Bob Faist
280              
281             =back
282              
283             =head1 COPYRIGHT AND LICENSE
284              
285             Copyright 2006-2017 by Bob Faist
286              
287             This library is free software; you can redistribute it and/or modify
288             it under the same terms as Perl itself.
289              
290             =head1 SEE ALSO
291              
292             http://musicbrainz.org/doc/Development/XML_Web_Service/Version_2
293              
294             =cut
295              
296             1;