Bivio::Biz::Action::WikiView
# Copyright (c) 2006-2009 bivio Software, Inc. All Rights Reserved. # $Id$ package Bivio::Biz::Action::WikiView; use strict; use Bivio::Base 'Biz.Action'; use Bivio::UI::ViewLanguageAUTOLOAD; my($_A) = b_use('IO.Alert'); my($_ARF) = b_use('Action.RealmFile'); my($_C) = b_use('FacadeComponent.Constant'); my($_E) = b_use('Model.Email'); my($_FP) = b_use('Type.FilePath'); my($_MRF) = b_use('Model.RealmFile'); my($_RO) = b_use('Model.RealmOwner'); my($_WDN) = b_use('Type.WikiDataName'); my($_WN) = b_use('Type.WikiName'); my($_WT) = b_use('XHTMLWidget.WikiText'); my($_T) = b_use('FacadeComponent.Text'); my($_NOT_FOUND) = b_use('Bivio.DieCode')->NOT_FOUND; b_use('IO.Config')->register(my $_CFG = { use_default_start_page => 0, default_start_page_realm => undef, }); sub execute { my($proto) = shift; return $proto->execute_prepare_html(@_) || do { my($req) = @_; my($self) = $req->get($proto->package_name); $self->put(html => $self->render_html($req)); 0; }; } sub execute_help { my($proto, $req) = @_; return $proto->execute($req, $_C->get_value('help_wiki_realm_id', $req)); } sub execute_load_history { my($proto, $req, $realm_id, $task_id) = @_; my($path) = $req->get('path_info'); $path =~ s{^@{[$_FP->VERSIONS_FOLDER]}}{}; $path =~ s{@{[$_FP->VERSION_REGEX]}}{}; $req->put(path_info => $path); my($name) = $_FP->get_tail($path); $proto->new()->put_on_request($req)->put( title => $name, is_start_page => _is_start_page($req, $name), ); return; } sub execute_not_found { my($proto, $req) = @_; return 'FORUM_WIKI_VIEW' if $_CFG->{use_default_start_page} && _create_default_start_page($proto, $req); my($t) = $req->get('task')->unsafe_get_attr_as_id('edit_task'); return unless $t && $req->can_user_execute_task($t) && $req->unsafe_get('path_info'); $proto->get_instance('Acknowledgement') ->save_label('FORUM_WIKI_NOT_FOUND', $req); return 'edit_task'; } sub execute_prepare_html { my($proto, $req, $realm_id, $task_id, $name) = @_; $realm_id ||= $req->get('auth_id'); $task_id ||= $req->get('task_id'); $name ||= $req->unsafe_get('path_info'); unless ($name) { # To avoid name space issues, there always needs to be a path_info $req->put(path_info => $_FP->to_absolute( b_use('FacadeComponent.Text')->get_value('WikiView.start_page', $req))); return { # should be able to handle realm_id and convert automatically realm => $req->with_realm($realm_id, sub {$req->get_nested(qw(auth_realm owner_name))}), task_id => $task_id, query => undef, carry_path_info => 1, }; } unless (_is_valid(\$name)) { $req->put(path_info => $_WDN->to_absolute($name)); return $_ARF->access_controlled_execute($req); #TODO: Test this thoroughly with all apps # my($die_code); # my($rf) = $proto->unsafe_load_wiki_data( # $req->get('auth_id'), # $_MRF->parse_path($req->get('path_info')), # $req, # \$die_code, # ); # $req->throw_die($die_code || 'DIE' => { # entity => $req->get('path_info'), # realm_id => $req->get('auth_id'), # }) unless $rf; # return $_ARF->set_output_for_get($rf); } my($self) = $proto->new->put_on_request($req)->put( name => $name, #TODO: Use is_versioned can_edit => ($name !~ /;/), exists => 0, ); my($wa) = $_WT->prepare_html($realm_id, $name, $task_id, $req); my($author) = ''; my($author_name) = ''; if ($req->unsafe_get_nested(qw(task want_author))) { my($e) = $_E->new($req) ->unauth_load_or_die({realm_id => $wa->{user_id}}); $author = $e->get('email'); $author_name = $_RO->new($req) ->unauth_load_or_die({realm_id => $e->get('realm_id')}) ->get('display_name'); } $self->put( wiki_args => $wa, title => $wa->{title}, modified_date_time => $wa->{modified_date_time}, author => $author, author_email => $author, author_name => $author_name, exists => 1, is_start_page => _is_start_page($req, $name), ); return 0; } sub get { my($self, @keys) = @_; $_A->warn_deprecated('use author_email in place of author') if grep($_ eq 'author', @keys); return shift->SUPER::get(@_); } sub handle_config { my(undef, $cfg) = @_; $_CFG = $cfg; return; } sub render_html { return $_WT->render_html(shift->get('wiki_args')); } sub unsafe_load_wiki_data { my($self, $path, $wiki_args, $die_code) = @_; $path = $_WDN->to_absolute($path, $wiki_args->{is_public}); if (my $res = $_ARF->access_controlled_load( $wiki_args->{realm_id}, $path, $wiki_args->{req}, $die_code, )) { return $res; } my($sid) = $_C->get_value('site_realm_id', $wiki_args->{req}); return if $sid eq $wiki_args->{realm_id}; my($rf) = $_MRF->new($wiki_args->{req}); return $rf if $rf->unauth_load({ realm_id => $sid, path => $_FP->to_public($path), is_public => 1, }); $$die_code ||= $_NOT_FOUND; return undef; } sub _create_default_start_page { my($proto, $req) = @_; my($path) = $req->unsafe_get('path_info'); return 0 unless $path && _is_valid(\$path) && _is_start_page($req, $path); my($rid) = b_use('Model.RealmOwner')->new($req) ->unauth_load_or_die({ name => $_CFG->{default_start_page_realm} || b_use('FacadeComponent.Constant') ->get_value('site_realm_name', $req), })->get('realm_id'); $path = $_WN->DEFAULT_START_PAGE_PATH; my($rf) = b_use('Model.RealmFile')->new($req); unless ( $rf->unauth_load({ path => $path, realm_id => $rid, }) ) { $_A->warn_exactly_once($path, ': missing from realm: ', $rid); return 0; } $rf->create_with_content( { path => $_WN->to_absolute($_WN->START_PAGE), user_id => $rf->get('user_id'), }, $rf->get_content, ); return 1; } sub _is_start_page { my($req, $name) = @_; return lc($_T->get_value('WikiView.start_page', $req)) eq lc($name) ? 1 : 0; } sub _is_valid { my($name) = @_; $$name =~ s{^/+}{}; return $_WN->is_valid($$name); } 1;