Kousuke Taniguchi
tinse****@u01*****
2003年 6月 18日 (水) 23:44:36 JST
tinsep19です。 At Wed, 18 Jun 2003 22:58:35 +0900, Naoki Takezoe wrote: > なるほど。data_dirを書き換えるよりキレイに実現できますね。 > 方向性は正しいと思います。実際にどのくらい実装されている > のでしょうか? > > 既にある程度できあがっているのであれば動かないものでも > 構わないのでコードを見せていただきたいのですが・・・。 ではDefaultFarmStorageとFarm.pmを添付します。 DefaultFarmStorageについては、現Wikiと互換性があります。 DefaultStorageと差し変えてもWiki本体の方は完全に動きます。 Farm部分については基本部分(新規Wiki、ページの編集など) についてはほぼ動いています。 プラグインもログとかを使わないものであれば動いています。 しかし各Wiki毎のユーザー情報もとれないですし 添付、アクセスログ、このあたりは厳しいところです。 あとはどのWikiもログが全部同じファイルに吐かれていますし、 添付ファイルは上書きしほうだいです。 Wikiにattach,logのインターフェースが無いので 作ろうかというとこで添付のインターフェースのメールを出しました。 wiki.cgiは冒頭部のみ以下の変更です。 require "setup.pl"; my $cgi = CGI2->new(); my $proj = $cgi->path_info(); if(length($proj)>0){ if($proj =~ /^(\/\w+)+$/){ $main::script_name = basename($proj); }else{ die $!; } } my $wiki = Farm->new($cgi,$proj); -------------- next part -------------- ############################################################ # # デフォルトのFarmストレージプラグイン # DefaultStrageの全てのメソッドに$proj引数が加わっています。 # 形式は '/xxx/yyy/zzz' # ############################################################ package Wiki::DefaultFarmStorage; use File::Copy; use strict; #=========================================================== # コンストラクタ #=========================================================== sub new { my $class = shift; my $self = {}; return bless $self,$class; } #=========================================================== # ページを取得 #=========================================================== sub get_page { my $self = shift; my $page = shift; my $content = ""; my $proj = shift; my $filename = Util::make_filename($main::data_dir.$proj, Util::url_encode($page), "wiki"); if(-e $filename){ open(DATA,$filename) or die $!; binmode(DATA); while(<DATA>){ $content = $content.$_; } close(DATA); } #$content =~ s/\r\n/\n/g; #$content =~ s/\r/\n/g; return $content; } #============================================================================== # ページを保存 #============================================================================== sub save_page { my $self = shift; my $page = shift; my $content = shift; my $proj = shift; $content = '' if($content =~ /^[\r\n]+$/s); # added for opera # ページ名とページ内容の補正 $page = Util::trim($page); $content =~ s/\r\n/\n/g; $content =~ s/\r/\n/g; # バックアップ my $BACKUP = $self->get_page($page); if($BACKUP ne ""){ open(DATA,">".Util::make_filename($main::backup_dir.$proj, Util::url_encode($page), "bak")) or die $!; binmode(DATA); print DATA $BACKUP; close(DATA); } # 書き込む if($content eq ""){ unlink(Util::make_filename($main::data_dir.$proj, Util::url_encode($page), "wiki")); unlink(Util::make_filename($main::backup_dir.$proj, Util::url_encode($page), "bak")); } else { open(DATA,">".Util::make_filename($main::data_dir.$proj, Util::url_encode($page), "wiki")) or die $!; binmode(DATA); print DATA $content; close(DATA); } } #=========================================================== # ページの一覧を取得 #=========================================================== sub get_page_list { my $self = shift; my $proj = shift; opendir(DIR,$main::data_dir.$proj) or die $!; my ($entry, @ list); while($entry = readdir(DIR)){ my $name = substr($entry,0,rindex($entry,".")); my $type = substr($entry,rindex($entry,".")); if($type eq ".wiki"){ push(@list,Util::url_decode($name)); } } closedir(DIR); @list = sort { $a cmp $b } @list; return @list; } #============================================================================== # ページの最終更新時刻を取得 #============================================================================== sub get_last_modified { my $self = shift; my $page = shift; my $proj = shift; my @status = stat(Util::make_filename($main::data_dir.$proj, Util::url_encode($page), "wiki")); return @status[9]; } #=============================================================================== # ページが存在するかどうか調べる #=============================================================================== sub page_exists { my $self = shift; my $page = shift; my $proj = shift; return (-e Util::make_filename($main::data_dir.$proj, Util::url_encode($page), "wiki")); } #============================================================================== # バックアップタイプを取得(single|all) #============================================================================== sub backup_type { return "single"; } #============================================================================== # バックアップ時刻の一覧を取得します。 #============================================================================== sub get_backup_list { return undef; } #============================================================================== # バックアップを取得します。 # ※backup_type=allの場合は第二引数で世代(0〜)を指定します。 #============================================================================== sub get_backup { my $self = shift; my $page = shift; my $content = ""; my $proj = shift; my $filename = Util::make_filename($main::backup_dir.$proj, Util::url_encode($page), "bak"); if(-e $filename){ open(DATA,$filename) or die $!; binmode(DATA); while(<DATA>){ $content = $content.$_; } close(DATA); } #$content =~ s/\r\n/\n/g; #$content =~ s/\r/\n/g; return $content; } #============================================================================== # ページを凍結します #============================================================================== sub freeze_page { my $self = shift; my $pagename = shift; my $proj = shift; my $prefix = Util::url_encode($proj)."." if($proj ne ""); if(!$self->is_freeze($pagename)){ open(DATA,">>$main::log_dir/".$prefix.$main::freeze_file) or die $!; binmode(DATA); print DATA $pagename."\n"; close(DATA); } } #============================================================================== # ページの凍結を解除します #============================================================================== sub un_freeze_page { my $self = shift; my $pagename = shift; my $proj = shift; my $prefix = Util::url_encode($proj)."." if($proj ne ""); if($self->is_freeze($pagename)){ my $buf = ""; open(DATA,"$main::log_dir/".$prefix.$main::freeze_file) or die $!; while(<DATA>){ chomp $_; if($pagename ne $_){ $buf .= $_."\n"; } } close(DATA); open(DATA,">$main::log_dir/".$prefix.$main::freeze_file) or die $!; binmode(DATA); print DATA $buf; close(DATA); } } #============================================================================== # 凍結リストを取得 #============================================================================== sub get_freeze_list { my $self = shift; my $proj = shift; my $prefix = Util::url_encode($proj)."." if($proj ne ""); my @list; if(!-e "$main::log_dir/".$prefix.$main::freeze_file){ return @list; } open(DATA,"$main::log_dir/".$prefix.$main::freeze_file) or die $!; while(<DATA>){ chomp $_; push @list,$_; } close(DATA); return @list; } #============================================================================== # 引数で渡したページが凍結中かどうかしらべます #============================================================================== sub is_freeze { my $self = shift; my $pagename = shift; my $proj = shift; foreach($self->get_freeze_list($proj)){ if($_ eq $pagename){ return 1; } } return 0; } #============================================================================== # Wikiを作成します。 #============================================================================== sub create_wiki { my $self = shift; my $proj = shift; my $prefix = Util::url_encode($proj)."." if($proj ne ""); unless($self->wiki_exists($proj)){ mkdir($main::data_dir.$proj, 0777) or die $!; mkdir($main::backup_dir.$proj, 0777) or die $!; #configは掘るほどではないか copy("$main::config_dir/".$main::config_file, "$main::config_dir/".$prefix.$main::config_file) or die $!; copy("$main::config_dir/".$main::usercss_file, "$main::config_dir/".$prefix.$main::usercss_file) or die $!; copy("$main::config_dir/".$main::userdat_file, "$main::config_dir/".$prefix.$main::userdat_file) or die $!; copy("$main::config_dir/".$main::plugin_file, "$main::config_dir/".$prefix.$main::plugin_file) or die $!; mkdir($main::attach_dir.$proj,0777) or die $!; mkdir($main::pdf_dir.$proj,0777) or die $!; } } #============================================================================== # Wikiが存在するかどうかを調べます。 # backupなど全部調べた方がいいだろうか? #============================================================================== sub wiki_exists{ my $self = shift; my $proj = shift; return (-d $main::data_dir.$proj); } #================================================================= # 引数のWikiの子Wikiのリストを返します # 引数は""(空文字)もしくは/aaa/bbb/cccの形 # 戻り値は文字の配列です("xxx","yyy","zzz") #================================================================= sub get_wiki_list { my $self = shift; my $proj = shift; opendir(DIR,$main::data_dir.$proj) or die $!; my @list; while(my $entry = readdir(DIR)){ next if($entry =~ /^\.+$/); push(@list,$entry) if(-d $main::data_dir.$proj."/".$entry); } closedir(DIR); @list = sort {$a cmp $b} @list; return @list; } 1; -------------- next part -------------- ############################################################################## # # Farm API # ############################################################################## package Farm; use Wiki; use Wiki::DefaultFarmStorage; use vars qw(@ISA); use strict; @ISA = qw(Wiki); #============================================================================ # コンストラクタ #============================================================================ sub new { my $class = shift; my $cgi = shift; my $self = Wiki->new($cgi); my $proj = shift; my $storage = Wiki::DefaultFarmStorage->new(); $self->set_storage($storage); $self->{project} = $proj; return bless $self,$class; } #============================================================================== # 現在のWikiに子Wikiを作成します # 引数の$childは /^\w+$/ でチェックしてください #============================================================================== sub create_wiki{ my $self = shift; my $child = shift; my $proj = $self->{project}; $self->{storage}->create_wiki("$proj/$child"); } #============================================================================== # 子Wikiが存在するどうかを調べます child_exists かな ?? #============================================================================== sub wiki_exists{ my $self = shift; my $child = shift; my $proj = $self->{project}; return $self->{storage}->wiki_exists("$proj/$child"); } #============================================================================== # 子Wikiのリストを配列にして返します get_child_listかな ?? #============================================================================== sub get_wiki_list{ my $self = shift; my $proj = $self->{project}; return $self->{storage}->get_wiki_list($proj); } ############################################################################### # Wiki APIのオーバーライド # 基本的には引数の最後にprojectを加えます。 ############################################################################### sub is_freeze { my $self = shift; my $proj = $self->{project}; push(@_,$proj); return $self->{storage}->is_freeze(@_); } sub freeze_page { my $self = shift; my $proj = $self->{project}; push(@_,$proj); $self->{storage}->freeze_page(@_); } sub un_freeze_page { my $self = shift; my $proj = $self->{project}; push(@_,$proj); $self->{storage}->un_freeze_page(@_); } sub get_freeze_list{ my $self = shift; my $proj = $self->{project}; return $self->{storage}->get_freeze_list($proj); } sub get_page_list { my $self = shift; my $proj = $self->{project}; push(@_,$proj); return $self->{storage}->get_page_list(@_); } sub get_last_modified { my $self = shift; my $proj = $self->{project}; push(@_,$proj); return $self->{storage}->get_last_modified(@_); } sub get_page { my $self = shift; my $proj = $self->{project}; push(@_,$proj); return $self->{storage}->get_page(@_); } sub get_backup { my $self = shift; my $proj = $self->{project}; push(@_,$proj); return $self->{storage}->get_backup(@_); } sub save_page { my $self = shift; my $pagename = shift; my $content = shift; my $proj = $self->{project}; $self->do_hook("save_before"); $self->{"storage"}->save_page($pagename,$content,$proj); $self->get_CGI->param("page" ,$pagename); $self->get_CGI->param("content",$content); if($content ne ""){ $self->do_hook("save_after"); } else { $self->do_hook("delete"); } } sub page_exists{ my $self = shift; my $proj = $self->{project}; push(@_,$proj); return $self->{storage}->page_exists(@_); } 1;