File Coverage

blib/lib/Yukki/Web/Controller/Attachment.pm
Criterion Covered Total %
statement 38 91 41.7
branch 7 24 29.1
condition 0 9 0.0
subroutine 10 14 71.4
pod 7 7 100.0
total 62 145 42.7


line stmt bran cond sub pod time code
1             package Yukki::Web::Controller::Attachment;
2             $Yukki::Web::Controller::Attachment::VERSION = '0.991_002'; # TRIAL
3              
4 1     1   1196 $Yukki::Web::Controller::Attachment::VERSION = '0.991002';use v5.24;
  1         3  
5 1     1   5 use utf8;
  1         2  
  1         8  
6 1     1   22 use Moo;
  1         2  
  1         6  
7              
8             with 'Yukki::Web::Controller';
9              
10 1     1   755 use JSON;
  1         5996  
  1         6  
11 1     1   475 use Yukki::Error qw( http_throw );
  1         3  
  1         4  
12              
13 1     1   195 use namespace::clean;
  1         1  
  1         6  
14              
15             # ABSTRACT: Controller for uploading, downloading, and viewing attachments
16              
17              
18             sub fire {
19 2     2 1 259 my ($self, $ctx) = @_;
20              
21 2         31 my $action = $ctx->request->path_parameters->{action};
22 2 100       52 if ($action eq 'download') { $self->download_file($ctx) }
  1 50       5  
    50          
    50          
    50          
23 0         0 elsif ($action eq 'upload') { $self->upload_file($ctx) }
24 0         0 elsif ($action eq 'view') { $self->view_file($ctx) }
25 0         0 elsif ($action eq 'rename') { $self->rename_file($ctx) }
26 0         0 elsif ($action eq 'remove') { $self->remove_file($ctx) }
27             else {
28 1         15 http_throw('That attachment action does not exist.', {
29             status => 'NotFound',
30             });
31             }
32             }
33              
34              
35             sub lookup_file {
36 1     1 1 3 my ($self, $repo_name, $file) = @_;
37              
38 1         17 my $repository = $self->model('Repository', { name => $repo_name });
39              
40 1         41 my $final_part = pop @$file;
41 1         2 my $filetype;
42 1 50       5 if ($final_part =~ s/\.(?<filetype>[a-z0-9]+)$//) {
43 1     1   706 $filetype = $+{filetype};
  1         280  
  1         718  
  0         0  
44             }
45              
46 1         5 my $path = join '/', @$file, $final_part;
47 1         6 return $repository->file({ path => $path, filetype => $filetype });
48             }
49              
50              
51             sub download_file {
52 1     1 1 3 my ($self, $ctx) = @_;
53              
54 1         14 my $repo_name = $ctx->request->path_parameters->{repository};
55 1         32 my $path = $ctx->request->path_parameters->{file};
56              
57 1         21 my $file = $self->lookup_file($repo_name, $path);
58              
59 1         30 $ctx->response->content_type('application/octet');
60 1         323 $ctx->response->body([ scalar $file->fetch ]);
61             }
62              
63              
64             sub view_file {
65 0     0 1   my ($self, $ctx) = @_;
66              
67 0           my $repo_name = $ctx->request->path_parameters->{repository};
68 0           my $path = $ctx->request->path_parameters->{file};
69              
70 0           my $file = $self->lookup_file($repo_name, $path);
71              
72 0           $ctx->response->content_type($file->media_type);
73 0           $ctx->response->body([ scalar $file->fetch ]);
74             }
75              
76              
77             sub rename_file {
78 0     0 1   my ($self, $ctx) = @_;
79              
80 0           my $repo_name = $ctx->request->path_parameters->{repository};
81 0           my $path = $ctx->request->path_parameters->{file};
82              
83 0           my $file = $self->lookup_file($repo_name, $path);
84              
85 0 0         if ($ctx->request->method eq 'POST') {
86 0           my $new_name = $ctx->request->parameters->{yukkiname_new};
87              
88 0           my $part = qr{[_a-z0-9-.]+(?:\.[_a-z0-9-]+)*}i;
89 0 0         if ($new_name =~ m{^$part(?:/$part)*$}) {
90 0 0         if (my $user = $ctx->session->{user}) {
91 0           $file->author_name($user->{name});
92 0           $file->author_email($user->{email});
93             }
94              
95 0           my $new_file = $file->rename({
96             full_path => $new_name,
97             comment => 'Renamed ' . $file->full_path . ' to ' . $new_name,
98             });
99              
100 0   0       my $parent = $new_file->parent // $file->repository->default_file;
101              
102 0           $ctx->response->redirect(join '/',
103             '/page/edit', $repo_name, $parent->full_path);
104 0           return;
105             }
106             else {
107 0           $ctx->add_errors('the new name must contain only letters, numbers, underscores, dashes, periods, and slashes');
108             }
109             }
110              
111             $ctx->response->body(
112 0           $self->view('Attachment')->rename($ctx, {
113             title => $file->title,
114             repository => $repo_name,
115             page => $file->full_path,
116             file => $file,
117             })
118             );
119             }
120              
121              
122             sub remove_file {
123 0     0 1   my ($self, $ctx) = @_;
124              
125 0           my $repo_name = $ctx->request->path_parameters->{repository};
126 0           my $path = $ctx->request->path_parameters->{file};
127              
128 0           my $file = $self->lookup_file($repo_name, $path);
129              
130 0   0       my $return_to = $file->parent // $file->repository->default_file;
131              
132 0           my $confirmed = $ctx->request->body_parameters->{confirmed};
133 0 0 0       if ($ctx->request->method eq 'POST' and $confirmed) {
134              
135 0 0         if (my $user = $ctx->session->{user}) {
136 0           $file->author_name($user->{name});
137 0           $file->author_email($user->{email});
138             }
139              
140             $file->remove({
141 0           comment => 'Removing ' . $file->full_path . ' from repository.',
142             });
143              
144 0           $ctx->response->redirect(join '/', '/page/view', $repo_name, $return_to->full_path);
145 0           return;
146             }
147              
148             $ctx->response->body(
149 0           $self->view('Attachment')->remove($ctx, {
150             title => $file->title,
151             repository => $repo_name,
152             page => $file->full_path,
153             file => $file,
154             return_link => join('/', '/page/view', $repo_name, $return_to->full_path),
155             })
156             );
157             }
158              
159              
160             sub upload_file {
161 0     0 1   my ($self, $ctx) = @_;
162              
163 0           my $repo_name = $ctx->request->path_parameters->{repository};
164 0           my $path = $ctx->request->path_parameters->{file};
165              
166 0           my $file = $self->lookup_file($repo_name, $path);
167              
168 0 0         if (my $user = $ctx->session->{user}) {
169 0           $file->author_name($user->{name});
170 0           $file->author_email($user->{email});
171             }
172              
173 0           my $upload = $ctx->request->uploads->{file};
174 0           $file->store({
175             filename => $upload->tempname,
176             comment => 'Uploading file ' . $upload->filename,
177             });
178              
179 0           $ctx->response->content_type('application/json');
180 0           $ctx->response->body(
181             encode_json({
182             viewable => 1,
183             repository_path => join('/', $repo_name, $file->full_path),
184             })
185             );
186             }
187              
188             1;
189              
190             __END__
191              
192             =pod
193              
194             =encoding UTF-8
195              
196             =head1 NAME
197              
198             Yukki::Web::Controller::Attachment - Controller for uploading, downloading, and viewing attachments
199              
200             =head1 VERSION
201              
202             version 0.991_002
203              
204             =head1 DESCRIPTION
205              
206             Handles uploading, downloading, and viewing attachments.
207              
208             =head1 METHODS
209              
210             =head2 fire
211              
212             Maps download requests to L</download_file>, upload requests to L</upload_file>, and view requestst to L</view_file>.
213              
214             =head2 lookup_file
215              
216             my $file = $self->lookup_file($repository, $path);
217              
218             This is a helper for locating and returning a L<Yukki::Model::File> for the
219             requested repository and path.
220              
221             =head2 download_file
222              
223             Returns the file in the response with a MIME type of "application/octet". This
224             should force the browser to treat it like a download.
225              
226             =head2 view_file
227              
228             Returns the file in the response with a MIME type reported by
229             L<Yukki::Model::File/media_type>.
230              
231             =head2 rename_file
232              
233             Handles attachment renaming via the page rename controller.
234              
235             =head2 remove_file
236              
237             Displays the remove confirmation.
238              
239             =head2 upload_file
240              
241             This uploads the file given into the wiki.
242              
243             =head1 AUTHOR
244              
245             Andrew Sterling Hanenkamp <hanenkamp@cpan.org>
246              
247             =head1 COPYRIGHT AND LICENSE
248              
249             This software is copyright (c) 2017 by Qubling Software LLC.
250              
251             This is free software; you can redistribute it and/or modify it under
252             the same terms as the Perl 5 programming language system itself.
253              
254             =cut