{
$Yukki::Web::Controller::Page::VERSION
=
'0.140290'
;
}
use
5.12.1;
sub
fire {
my
(
$self
,
$ctx
) =
@_
;
given
(
$ctx
->request->path_parameters->{action}) {
when
(
'view'
) {
$self
->view_page(
$ctx
) }
when
(
'edit'
) {
$self
->edit_page(
$ctx
) }
when
(
'history'
) {
$self
->view_history(
$ctx
) }
when
(
'diff'
) {
$self
->view_diff(
$ctx
) }
when
(
'preview'
) {
$self
->preview_page(
$ctx
) }
when
(
'attach'
) {
$self
->upload_attachment(
$ctx
) }
when
(
'rename'
) {
$self
->rename_page(
$ctx
) }
when
(
'remove'
) {
$self
->remove_page(
$ctx
) }
default
{
http_throw(
'That page action does not exist.'
, {
status
=>
'NotFound'
,
});
}
}
}
sub
repo_name_and_path {
my
(
$self
,
$ctx
) =
@_
;
my
$repo_name
=
$ctx
->request->path_parameters->{repository};
my
$path
=
$ctx
->request->path_parameters->{page};
if
(not
defined
$path
) {
my
$repo_config
=
$self
->app->settings->repositories->{
$repo_name
};
my
$path_str
=
$repo_config
->default_page;
$path
= [
split
m{/},
$path_str
];
}
return
(
$repo_name
,
$path
);
}
sub
lookup_page {
my
(
$self
,
$repo_name
,
$page
) =
@_
;
my
$repository
=
$self
->model(
'Repository'
, {
name
=>
$repo_name
});
my
$final_part
=
pop
@$page
;
my
$filetype
;
if
(
$final_part
=~ s/\.(?<filetype>[a-z0-9]+)$//) {
$filetype
= $+{filetype};
}
my
$path
=
join
'/'
,
@$page
,
$final_part
;
return
$repository
->file({
path
=>
$path
,
filetype
=>
$filetype
});
}
sub
view_page {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
my
$body
;
if
(not
$page
->
exists
) {
my
@files
=
$page
->list_files;
$body
=
$self
->view(
'Page'
)->blank(
$ctx
, {
title
=>
$page
->file_name,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
files
=> \
@files
,
});
}
else
{
$body
=
$self
->view(
'Page'
)->view(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
file
=>
$page
,
});
}
$ctx
->response->body(
$body
);
}
sub
edit_page {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
if
(
$ctx
->request->method eq
'POST'
) {
my
$new_content
=
$ctx
->request->parameters->{yukkitext};
my
$position
=
$ctx
->request->parameters->{yukkitext_position};
my
$comment
=
$ctx
->request->parameters->{comment};
if
(
my
$user
=
$ctx
->session->{user}) {
$page
->author_name(
$user
->{name});
$page
->author_email(
$user
->{email});
}
$page
->store({
content
=>
$new_content
,
comment
=>
$comment
,
});
$ctx
->response->redirect(
join
'/'
,
'/page/edit'
,
$repo_name
,
$page
->full_path,
'?yukkitext_position='
.
$position
);
return
;
}
my
@attachments
=
grep
{
$_
->filetype ne
'yukki'
}
$page
->list_files;
my
$position
=
$ctx
->request->parameters->{yukkitext_position} // -1;
$ctx
->response->body(
$self
->view(
'Page'
)->edit(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
position
=>
$position
,
file
=>
$page
,
attachments
=> \
@attachments
,
})
);
}
sub
rename_page {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
if
(
$ctx
->request->method eq
'POST'
) {
my
$new_name
=
$ctx
->request->parameters->{yukkiname_new};
my
$part
=
qr{[_a-z0-9-.]+(?:\.[_a-z0-9-]+)*}
i;
if
(
$new_name
=~ m{^
$part
(?:/
$part
)*$}) {
if
(
my
$user
=
$ctx
->session->{user}) {
$page
->author_name(
$user
->{name});
$page
->author_email(
$user
->{email});
}
$page
->
rename
({
full_path
=>
$new_name
,
comment
=>
'Renamed '
.
$page
->full_path .
' to '
.
$new_name
,
});
$ctx
->response->redirect(
join
'/'
,
'/page/edit'
,
$repo_name
,
$new_name
);
return
;
}
else
{
$ctx
->add_errors(
'the new name must contain only letters, numbers, underscores, dashes, periods, and slashes'
);
}
}
$ctx
->response->body(
$self
->view(
'Page'
)->
rename
(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
file
=>
$page
,
})
);
}
sub
remove_page {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
my
$confirmed
=
$ctx
->request->body_parameters->{confirmed};
if
(
$ctx
->request->method eq
'POST'
and
$confirmed
) {
my
$return_to
=
$page
->parent //
$page
->repository->default_file;
if
(
$return_to
->full_path ne
$page
->full_path) {
if
(
my
$user
=
$ctx
->session->{user}) {
$page
->author_name(
$user
->{name});
$page
->author_email(
$user
->{email});
}
$page
->remove({
comment
=>
'Removing '
.
$page
->full_path .
' from repository.'
,
});
$ctx
->response->redirect(
join
'/'
,
'/page/view'
,
$repo_name
,
$return_to
->full_path);
return
;
}
else
{
$ctx
->add_errors(
'you may not remove the top-most page of a repository'
);
}
}
$ctx
->response->body(
$self
->view(
'Page'
)->remove(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
file
=>
$page
,
return_link
=>
join
(
'/'
,
'/page/view'
,
$repo_name
,
$page
->full_path),
})
);
}
sub
view_history {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
$ctx
->response->body(
$self
->view(
'Page'
)->history(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
revisions
=> [
$page
->history ],
})
);
}
sub
view_diff {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
my
$r1
=
$ctx
->request->query_parameters->{r1};
my
$r2
=
$ctx
->request->query_parameters->{r2};
try
{
my
$diff
=
''
;
for
my
$chunk
(
$page
->diff(
$r1
,
$r2
)) {
given
(
$chunk
->[0]) {
when
(
' '
) {
$diff
.=
$chunk
->[1] }
when
(
'+'
) {
$diff
.=
sprintf
'<ins markdown="1">%s</ins>'
,
$chunk
->[1] }
when
(
'-'
) {
$diff
.=
sprintf
'<del markdown="1">%s</del>'
,
$chunk
->[1] }
default
{
warn
"unknown chunk type $chunk->[0]"
}
}
}
my
$file_preview
=
$page
->file_preview(
content
=>
$diff
,
);
$ctx
->response->body(
$self
->view(
'Page'
)->diff(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
file
=>
$file_preview
,
})
);
}
catch
{
my
$ERROR
=
$_
;
if
(
"$_"
=~ /usage: git diff/) {
http_throw
'Diffs will not work with git versions before 1.7.2. Please use a newer version of git. If you are using a newer version of git, please file a support issue.'
;
}
die
$ERROR
;
};
}
sub
preview_page {
my
(
$self
,
$ctx
) =
@_
;
my
(
$repo_name
,
$path
) =
$self
->repo_name_and_path(
$ctx
);
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
$breadcrumb
=
$self
->breadcrumb(
$page
->repository,
$path
);
my
$content
=
$ctx
->request->body_parameters->{yukkitext};
my
$position
=
$ctx
->request->parameters->{yukkitext_position};
my
$file_preview
=
$page
->file_preview(
content
=>
$content
,
position
=>
$position
,
);
$ctx
->response->body(
$self
->view(
'Page'
)->preview(
$ctx
, {
title
=>
$page
->title,
breadcrumb
=>
$breadcrumb
,
repository
=>
$repo_name
,
page
=>
$page
->full_path,
file
=>
$file_preview
,
})
);
}
sub
upload_attachment {
my
(
$self
,
$ctx
) =
@_
;
my
$repo_name
=
$ctx
->request->path_parameters->{repository};
my
$path
=
delete
$ctx
->request->path_parameters->{page};
my
$page
=
$self
->lookup_page(
$repo_name
,
$path
);
my
@file
=
split
m{/},
$page
->path;
push
@file
,
$ctx
->request->uploads->{file}->filename;
$ctx
->request->path_parameters->{action} =
'upload'
;
$ctx
->request->path_parameters->{file} = \
@file
;
$self
->controller(
'Attachment'
)->fire(
$ctx
);
}
sub
breadcrumb {
my
(
$self
,
$repository
,
$path_parts
) =
@_
;
my
@breadcrumb
;
my
@path_acc
;
push
@breadcrumb
, {
label
=>
$repository
->title,
href
=>
join
(
'/'
,
'/page/view/'
,
$repository
->name),
};
for
my
$path_part
(
@$path_parts
) {
push
@path_acc
,
$path_part
;
my
$file
=
$repository
->file({
path
=>
join
(
'/'
,
@path_acc
),
filetype
=>
'yukki'
,
});
push
@breadcrumb
, {
label
=>
$file
->title,
href
=>
join
(
'/'
,
'/page/view'
,
$repository
->name,
$file
->full_path),
};
}
return
\
@breadcrumb
;
}
1;
Hide Show 78 lines of Pod