| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package WebService::Mattermost::V4::API::Resource; | 
| 2 |  |  |  |  |  |  |  | 
| 3 |  |  |  |  |  |  |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 7 |  |  | 7 |  | 6208 | use List::MoreUtils 'all'; | 
|  | 7 |  |  |  |  | 52849 |  | 
|  | 7 |  |  |  |  | 57 |  | 
| 6 | 7 |  |  | 7 |  | 6800 | use Moo; | 
|  | 7 |  |  |  |  | 18 |  | 
|  | 7 |  |  |  |  | 44 |  | 
| 7 | 7 |  |  | 7 |  | 2513 | use Types::Standard qw(Bool HashRef Object Str); | 
|  | 7 |  |  |  |  | 15 |  | 
|  | 7 |  |  |  |  | 46 |  | 
| 8 |  |  |  |  |  |  |  | 
| 9 | 7 |  |  | 7 |  | 8968 | use WebService::Mattermost::Helper::Alias qw(v4 view); | 
|  | 7 |  |  |  |  | 21 |  | 
|  | 7 |  |  |  |  | 455 |  | 
| 10 | 7 |  |  | 7 |  | 3405 | use WebService::Mattermost::V4::API::Object::Channel; | 
|  | 7 |  |  |  |  | 26 |  | 
|  | 7 |  |  |  |  | 264 |  | 
| 11 | 7 |  |  | 7 |  | 3399 | use WebService::Mattermost::V4::API::Object::Icon; | 
|  | 7 |  |  |  |  | 48 |  | 
|  | 7 |  |  |  |  | 277 |  | 
| 12 | 7 |  |  | 7 |  | 3503 | use WebService::Mattermost::V4::API::Object::Status; | 
|  | 7 |  |  |  |  | 19 |  | 
|  | 7 |  |  |  |  | 281 |  | 
| 13 | 7 |  |  | 7 |  | 3483 | use WebService::Mattermost::V4::API::Object::Team; | 
|  | 7 |  |  |  |  | 21 |  | 
|  | 7 |  |  |  |  | 249 |  | 
| 14 | 7 |  |  | 7 |  | 3657 | use WebService::Mattermost::V4::API::Object::TeamMember; | 
|  | 7 |  |  |  |  | 23 |  | 
|  | 7 |  |  |  |  | 277 |  | 
| 15 | 7 |  |  | 7 |  | 3484 | use WebService::Mattermost::V4::API::Object::TeamStats; | 
|  | 7 |  |  |  |  | 23 |  | 
|  | 7 |  |  |  |  | 215 |  | 
| 16 | 7 |  |  | 7 |  | 3658 | use WebService::Mattermost::V4::API::Object::Plugins; | 
|  | 7 |  |  |  |  | 27 |  | 
|  | 7 |  |  |  |  | 243 |  | 
| 17 | 7 |  |  | 7 |  | 3497 | use WebService::Mattermost::V4::API::Object::Results; | 
|  | 7 |  |  |  |  | 21 |  | 
|  | 7 |  |  |  |  | 208 |  | 
| 18 | 7 |  |  | 7 |  | 3461 | use WebService::Mattermost::V4::API::Object::User; | 
|  | 7 |  |  |  |  | 21 |  | 
|  | 7 |  |  |  |  | 224 |  | 
| 19 | 7 |  |  | 7 |  | 3383 | use WebService::Mattermost::V4::API::Request; | 
|  | 7 |  |  |  |  | 23 |  | 
|  | 7 |  |  |  |  | 235 |  | 
| 20 | 7 |  |  | 7 |  | 3117 | use WebService::Mattermost::V4::API::Response; | 
|  | 7 |  |  |  |  | 33 |  | 
|  | 7 |  |  |  |  | 8212 |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | with qw( | 
| 23 |  |  |  |  |  |  | WebService::Mattermost::Role::Logger | 
| 24 |  |  |  |  |  |  | WebService::Mattermost::Role::Returns | 
| 25 |  |  |  |  |  |  | WebService::Mattermost::Role::UserAgent | 
| 26 |  |  |  |  |  |  | WebService::Mattermost::V4::API::Role::RequireID | 
| 27 |  |  |  |  |  |  | ); | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | has api        => (is => 'ro', isa => Object, required => 1); | 
| 32 |  |  |  |  |  |  | has base_url   => (is => 'ro', isa => Str,    required => 1); | 
| 33 |  |  |  |  |  |  | has resource   => (is => 'ro', isa => Str,    required => 1); | 
| 34 |  |  |  |  |  |  | has auth_token => (is => 'rw', isa => Str,    required => 1); | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | has DELETE  => (is => 'ro', isa => Str,     default => 'DELETE'); | 
| 37 |  |  |  |  |  |  | has GET     => (is => 'ro', isa => Str,     default => 'GET'); | 
| 38 |  |  |  |  |  |  | has headers => (is => 'ro', isa => HashRef, default => sub { {} }); | 
| 39 |  |  |  |  |  |  | has POST    => (is => 'ro', isa => Str,     default => 'POST'); | 
| 40 |  |  |  |  |  |  | has PUT     => (is => 'ro', isa => Str,     default => 'PUT'); | 
| 41 |  |  |  |  |  |  | has debug   => (is => 'ro', isa => Bool,    default => 0); | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | sub _delete { | 
| 46 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 47 | 0 |  |  |  |  | 0 | my $args = shift; | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 0 |  |  |  |  | 0 | $args->{method} = $self->DELETE; | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 0 |  |  |  |  | 0 | return $self->_call($args); | 
| 52 |  |  |  |  |  |  | } | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | sub _single_view_delete { | 
| 55 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 56 | 0 |  |  |  |  | 0 | my $args = shift; | 
| 57 |  |  |  |  |  |  |  | 
| 58 | 0 |  |  |  |  | 0 | $args->{single} = 1; | 
| 59 |  |  |  |  |  |  |  | 
| 60 | 0 |  |  |  |  | 0 | return $self->_delete($args); | 
| 61 |  |  |  |  |  |  | } | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | sub _get { | 
| 64 | 7 |  |  | 7 |  | 18 | my $self = shift; | 
| 65 | 7 |  |  |  |  | 14 | my $args = shift; | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 7 |  |  |  |  | 38 | $args->{method} = $self->GET; | 
| 68 |  |  |  |  |  |  |  | 
| 69 | 7 |  |  |  |  | 34 | return $self->_call($args); | 
| 70 |  |  |  |  |  |  | } | 
| 71 |  |  |  |  |  |  |  | 
| 72 |  |  |  |  |  |  | sub _single_view_get { | 
| 73 | 3 |  |  | 3 |  | 12 | my $self = shift; | 
| 74 | 3 |  |  |  |  | 7 | my $args = shift; | 
| 75 |  |  |  |  |  |  |  | 
| 76 | 3 |  |  |  |  | 11 | $args->{single} = 1; | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 3 |  |  |  |  | 16 | return $self->_get($args); | 
| 79 |  |  |  |  |  |  | } | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | sub _post { | 
| 82 | 2 |  |  | 2 |  | 7 | my $self = shift; | 
| 83 | 2 |  |  |  |  | 5 | my $args = shift; | 
| 84 |  |  |  |  |  |  |  | 
| 85 | 2 |  |  |  |  | 17 | $args->{method} = $self->POST; | 
| 86 |  |  |  |  |  |  |  | 
| 87 | 2 |  |  |  |  | 12 | return $self->_call($args); | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  |  | 
| 90 |  |  |  |  |  |  | sub _single_view_post { | 
| 91 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 92 | 0 |  |  |  |  | 0 | my $args = shift; | 
| 93 |  |  |  |  |  |  |  | 
| 94 | 0 |  |  |  |  | 0 | $args->{single} = 1; | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 0 |  |  |  |  | 0 | return $self->_post($args); | 
| 97 |  |  |  |  |  |  | } | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | sub _put { | 
| 100 | 1 |  |  | 1 |  | 2 | my $self = shift; | 
| 101 | 1 |  |  |  |  | 3 | my $args = shift; | 
| 102 |  |  |  |  |  |  |  | 
| 103 | 1 |  |  |  |  | 5 | $args->{method} = $self->PUT; | 
| 104 |  |  |  |  |  |  |  | 
| 105 | 1 |  |  |  |  | 6 | return $self->_call($args); | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | sub _single_view_put { | 
| 109 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 110 | 0 |  |  |  |  | 0 | my $args = shift; | 
| 111 |  |  |  |  |  |  |  | 
| 112 | 0 |  |  |  |  | 0 | $args->{method} = $self->PUT; | 
| 113 |  |  |  |  |  |  |  | 
| 114 | 0 |  |  |  |  | 0 | return $self->_put($args); | 
| 115 |  |  |  |  |  |  | } | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | sub _call { | 
| 118 | 10 |  |  | 10 |  | 23 | my $self = shift; | 
| 119 | 10 |  |  |  |  | 15 | my $args = shift; | 
| 120 |  |  |  |  |  |  |  | 
| 121 | 10 | 100 |  |  |  | 38 | if ($args->{required}) { | 
| 122 | 3 |  |  |  |  | 19 | my $validation = $self->_validate($args->{parameters}, $args->{required}); | 
| 123 |  |  |  |  |  |  |  | 
| 124 | 3 | 50 |  |  |  | 20 | return $validation unless $validation->{valid}; | 
| 125 |  |  |  |  |  |  | } | 
| 126 |  |  |  |  |  |  |  | 
| 127 | 10 |  |  |  |  | 42 | my %headers = ('Keep-Alive' => 1); | 
| 128 |  |  |  |  |  |  |  | 
| 129 | 10 | 50 |  |  |  | 229 | if ($self->auth_token) { | 
| 130 | 10 |  |  |  |  | 266 | $headers{Authorization} = $self->bearer($self->auth_token); | 
| 131 |  |  |  |  |  |  | } | 
| 132 |  |  |  |  |  |  |  | 
| 133 | 10 |  |  |  |  | 79 | my $request = $self->_as_request($args); | 
| 134 | 10 |  |  |  |  | 12041 | my $method  = lc $request->method; | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 10 |  |  |  |  | 21 | my $form_type; | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 10 | 100 |  |  |  | 76 | if (grep { $_ eq $request->method } ($self->PUT, $self->POST)) { | 
|  | 20 |  |  |  |  | 89 |  | 
| 139 | 3 |  |  |  |  | 9 | $form_type = 'json'; | 
| 140 |  |  |  |  |  |  | } else { | 
| 141 | 7 |  |  |  |  | 15 | $form_type = 'form'; | 
| 142 |  |  |  |  |  |  | } | 
| 143 |  |  |  |  |  |  |  | 
| 144 | 10 | 50 |  |  |  | 38 | $form_type = $args->{override_data_type} if $args->{override_data_type}; | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 10 |  |  |  |  | 209 | my $tx = $self->ua->$method( | 
| 147 |  |  |  |  |  |  | $request->url => \%headers, | 
| 148 |  |  |  |  |  |  | $form_type    => $request->parameters, | 
| 149 |  |  |  |  |  |  | ); | 
| 150 |  |  |  |  |  |  |  | 
| 151 | 10 | 50 |  |  |  | 2064 | if (my $error = $tx->req->error) { | 
| 152 | 0 |  |  |  |  | 0 | $self->logger->warn('No HTTP code was received from Mattermost. Is your server alive?'); | 
| 153 | 0 |  |  |  |  | 0 | $self->logger->warnf('The following may be useful: %s', $error->{message}); | 
| 154 |  |  |  |  |  |  | } | 
| 155 |  |  |  |  |  |  |  | 
| 156 | 10 |  |  |  |  | 371 | return $self->_as_response($tx->res, $args); | 
| 157 |  |  |  |  |  |  | } | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | sub _as_request { | 
| 160 | 10 |  |  | 10 |  | 27 | my $self = shift; | 
| 161 | 10 |  |  |  |  | 28 | my $args = shift; | 
| 162 |  |  |  |  |  |  |  | 
| 163 | 10 |  |  |  |  | 159 | $args->{auth_token} = $self->auth_token; | 
| 164 | 10 |  |  |  |  | 100 | $args->{base_url}   = $self->base_url; | 
| 165 | 10 |  |  |  |  | 63 | $args->{resource}   = $self->resource; | 
| 166 | 10 |  |  |  |  | 42 | $args->{debug}      = $self->debug; | 
| 167 |  |  |  |  |  |  |  | 
| 168 | 10 |  | 100 |  |  | 63 | $args->{endpoint}   ||= ''; | 
| 169 | 10 |  | 100 |  |  | 34 | $args->{parameters} ||= {}; | 
| 170 |  |  |  |  |  |  |  | 
| 171 | 10 |  |  |  |  | 166 | return WebService::Mattermost::V4::API::Request->new($args); | 
| 172 |  |  |  |  |  |  | } | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | sub _as_response { | 
| 175 | 10 |  |  | 10 |  | 81 | my $self = shift; | 
| 176 | 10 |  |  |  |  | 20 | my $res  = shift; | 
| 177 | 10 |  |  |  |  | 23 | my $args = shift; | 
| 178 |  |  |  |  |  |  |  | 
| 179 | 10 |  | 33 |  |  | 102 | my $view_name = $self->can('view_name') && $self->view_name; | 
| 180 |  |  |  |  |  |  |  | 
| 181 | 10 | 50 |  |  |  | 37 | if ($args->{view}) { | 
| 182 | 0 |  |  |  |  | 0 | $view_name = $args->{view}; | 
| 183 |  |  |  |  |  |  | } | 
| 184 |  |  |  |  |  |  |  | 
| 185 | 10 | 100 | 100 |  |  | 76 | if ($res->is_error && $self->debug) { | 
| 186 | 1 |  |  |  |  | 55 | $self->logger->warnf('An API error occurred: %s', $res->message); | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | return WebService::Mattermost::V4::API::Response->new({ | 
| 190 |  |  |  |  |  |  | auth_token  => $self->auth_token, | 
| 191 |  |  |  |  |  |  | base_url    => $self->base_url, | 
| 192 |  |  |  |  |  |  | code        => $res->code || 0, | 
| 193 |  |  |  |  |  |  | headers     => $res->headers, | 
| 194 |  |  |  |  |  |  | is_error    => $res->is_error   ? 1 : 0, | 
| 195 |  |  |  |  |  |  | is_success  => $res->is_success ? 1 : 0, | 
| 196 |  |  |  |  |  |  | message     => $res->message, | 
| 197 |  |  |  |  |  |  | prev        => $res, | 
| 198 |  |  |  |  |  |  | raw_content => $res->body, | 
| 199 |  |  |  |  |  |  | item_view   => $view_name, | 
| 200 |  |  |  |  |  |  | single_item => $args->{single}, | 
| 201 | 10 | 100 | 50 |  |  | 489 | }); | 
|  |  | 100 |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | } | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | sub _validate { | 
| 205 | 3 |  |  | 3 |  | 7 | my $self     = shift; | 
| 206 | 3 |  |  |  |  | 7 | my $args     = shift; | 
| 207 | 3 |  |  |  |  | 6 | my $required = shift; | 
| 208 |  |  |  |  |  |  |  | 
| 209 | 3 |  |  |  |  | 8 | my %slice; | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  |  | 
| 212 | 3 |  |  |  |  | 23 | @slice{@{$required}} = @{$args}{@{$required}}; | 
|  | 3 |  |  |  |  | 17 |  | 
|  | 3 |  |  |  |  | 11 |  | 
|  | 3 |  |  |  |  | 6 |  | 
| 213 |  |  |  |  |  |  |  | 
| 214 |  |  |  |  |  |  |  | 
| 215 | 3 | 50 |  | 5 |  | 82 | return { valid => 1 } if all { defined($_) } values %slice; | 
|  | 5 |  |  |  |  | 27 |  | 
| 216 |  |  |  |  |  |  |  | 
| 217 | 0 |  |  |  |  |  | my @missing; | 
| 218 |  |  |  |  |  |  |  | 
| 219 | 0 |  |  |  |  |  | foreach my $kx (@{$required}) { | 
|  | 0 |  |  |  |  |  |  | 
| 220 | 0 | 0 |  |  |  |  | push @missing, $kx unless $args->{$kx}; | 
| 221 |  |  |  |  |  |  | } | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | return { | 
| 224 | 0 |  |  |  |  |  | valid   => 0, | 
| 225 |  |  |  |  |  |  | missing => \@missing, | 
| 226 |  |  |  |  |  |  | error   => sprintf('Required parameters missing: %s', join(', ', @missing)), | 
| 227 |  |  |  |  |  |  | }; | 
| 228 |  |  |  |  |  |  | } | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  | sub _new_related_resource { | 
| 231 | 0 |  |  | 0 |  |  | my $self     = shift; | 
| 232 | 0 |  |  |  |  |  | my $base     = shift; | 
| 233 | 0 |  |  |  |  |  | my $resource = shift; | 
| 234 |  |  |  |  |  |  |  | 
| 235 | 0 |  |  |  |  |  | return v4($resource)->new({ | 
| 236 |  |  |  |  |  |  | auth_token => $self->auth_token, | 
| 237 |  |  |  |  |  |  | base_url   => $self->base_url, | 
| 238 |  |  |  |  |  |  | resource   => $base, | 
| 239 |  |  |  |  |  |  | }); | 
| 240 |  |  |  |  |  |  | } | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  |  | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | 1; | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | __END__ | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | =pod | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | =encoding UTF-8 | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | =head1 NAME | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | WebService::Mattermost::V4::API::Resource - Base class for API resources. | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | =head1 VERSION | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | version 0.26 | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | =head2 ATTRIBUTES | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | =over 4 | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | =item C<auth_token> | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | An auth token to use in the headers for every API call. Authentication is | 
| 269 |  |  |  |  |  |  | required to use the Mattermost API. | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | =item C<base_url> | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | The API's base URL. | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | =item C<resource> | 
| 276 |  |  |  |  |  |  |  | 
| 277 |  |  |  |  |  |  | The name of the API resource, for example L<WebService::Mattermost::V4::API::Brand>'s | 
| 278 |  |  |  |  |  |  | resource is 'brand'. | 
| 279 |  |  |  |  |  |  |  | 
| 280 |  |  |  |  |  |  | =back | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | =head1 AUTHOR | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | Mike Jones <mike@netsplit.org.uk> | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 287 |  |  |  |  |  |  |  | 
| 288 |  |  |  |  |  |  | This software is Copyright (c) 2020 by Mike Jones. | 
| 289 |  |  |  |  |  |  |  | 
| 290 |  |  |  |  |  |  | This is free software, licensed under: | 
| 291 |  |  |  |  |  |  |  | 
| 292 |  |  |  |  |  |  | The MIT (X11) License | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | =cut | 
| 295 |  |  |  |  |  |  |  |