File Coverage

blib/lib/Whelk/Role/Resource.pm
Criterion Covered Total %
statement 46 46 100.0
branch 10 12 83.3
condition 7 8 87.5
subroutine 9 9 100.0
pod 2 2 100.0
total 74 77 96.1


line stmt bran cond sub pod time code
1             package Whelk::Role::Resource;
2             $Whelk::Role::Resource::VERSION = '1.04';
3 21     21   46184 use Kelp::Base -attr;
  21         50  
  21         155  
4 21     21   5094 use Role::Tiny;
  21         73  
  21         151  
5              
6 21     21   6052 use Carp;
  21         77  
  21         1571  
7 21     21   11235 use Whelk::Endpoint;
  21         74  
  21         170  
8              
9             requires qw(api context);
10              
11             sub _whelk_config
12             {
13 468     468   4149 my ($self, $key) = @_;
14              
15 468         1150 return $self->context->app->whelk->resources->{ref $self}{$key};
16             }
17              
18             sub _whelk_adjust_pattern
19             {
20 117     117   257 my ($self, $pattern) = @_;
21              
22             # we don't handle regex
23 117 50       301 croak 'Regex patterns are disallowed in Whelk'
24             unless !ref $pattern;
25              
26             # glue up the route from base and used patterns
27 117         348 $pattern = $self->_whelk_config('base_route') . $pattern;
28 117         2389 $pattern =~ s{/$}{};
29 117         669 $pattern =~ s{/+}{/};
30              
31 117         287 return $pattern;
32             }
33              
34             sub _whelk_adjust_to
35             {
36 117     117   227 my ($self, $to) = @_;
37              
38 117         309 my $base = $self->context->app->routes->base;
39 117         2083 my $class = ref $self;
40 117 100       1332 if ($class !~ s/^${base}:://) {
41 1         5 $class = "+$class";
42             }
43              
44 117 100 100     392 if (!ref $to && $to !~ m{^\+|#|::}) {
45 9 50       38 my $join = $class =~ m{#} ? '#' : '::';
46 9         31 $to = join $join, $class, $to;
47             }
48              
49 117         278 return $to;
50             }
51              
52             sub request_body
53             {
54 10     10 1 866 my ($self) = @_;
55              
56             # this is set by wrapper when there is request body validation
57 10         23 return $self->context->req->stash->{request};
58             }
59              
60             sub add_endpoint
61             {
62 117     117 1 1933 my ($self, $pattern, $args, %meta) = @_;
63              
64             # remove meta we don't want to be passed to the constructor and which are
65             # not replaced by something else
66 117         312 delete $meta{response_schemas};
67              
68             # make sure we have hash (same as in Kelp)
69 117 100       454 $args = {
70             to => $args,
71             } unless ref $args eq 'HASH';
72              
73             # handle [METHOD => $pattern]
74 117 100       318 if (ref $pattern eq 'ARRAY') {
75 107         238 $args->{method} = $pattern->[0];
76 107         234 $pattern = $pattern->[1];
77             }
78              
79 117         394 $pattern = $self->_whelk_adjust_pattern($pattern);
80 117         379 $args->{to} = $self->_whelk_adjust_to($args->{to});
81 117   100     350 $args->{method} //= 'GET';
82 117         292 my $route = $self->context->app->add_route($pattern, $args)->parent;
83 117   66     135015 $route->dest->[0] //= ref $self; # makes sure plain subs work
84              
85 117         1460 my $endpoint = Whelk::Endpoint->new(
86             %meta,
87             resource => $self->_whelk_config('resource'),
88             formatter => $self->_whelk_config('formatter'),
89             wrapper => $self->_whelk_config('wrapper'),
90             route => $route,
91             );
92              
93 115         296 push @{$self->context->app->whelk->endpoints}, $endpoint;
  115         390  
94 115         2116 return $self;
95             }
96              
97             1;
98              
99             __END__
100              
101             =pod
102              
103             =head1 NAME
104              
105             Whelk::Role::Resource - Role for Whelk API resources
106              
107             =head1 SYNOPSIS
108              
109             package My::Custom::Resource;
110              
111             use Kelp::Base 'My::Custom::Controller';
112             use Role::Tiny::With;
113              
114             with qw(WhelK::Role::Resource);
115              
116             # required by the role
117             sub api
118             {
119             my ($self) = @_;
120              
121             # implement the api
122             ...;
123             }
124              
125             =head1 DESCRIPTION
126              
127             This is a role which implements Whelk resources. It must be applied to a Kelp
128             controller which is meant to be used as a resource for Whelk.
129             L<Whelk::Resource> is such controller, and is also a base controller for
130             L<Whelk> - there is no need to manually consume the role if you are extending
131             it. If you write your own Kelp application which uses Whelk, you most certainly
132             want to only apply it in a couple of your controllers and not the main
133             controller.
134              
135             This role requires you to implement C<api> method - it will not apply if this
136             prerequisite is not met. It also requires C<context> attribute to be present,
137             which is also a requirement made by Kelp.
138              
139             Whelk will reject any resources defined in its C<resources> configuration field
140             which do not consume this role.
141              
142             =head1 METHODS
143              
144             This role implements just a couple of helpful methods which you may use in
145             C<api> method and your route handler methods.
146              
147             =head2 request_body
148              
149             my $body = $self->request_body;
150              
151             A helper which returns the request body saved by the wrapper in stash key C<request>.
152              
153             =head2 add_endpoint
154              
155             Standard Whelk method to add endpoints, discussed at length in
156             L<Whelk::Manual/Adding endpoints>.
157