페이지 별로 조회수 출력
- 하단 편집 가이드에 해당 페이지의 조회수를 출력하게 함
- 필수 요구 사항 : 없음
- 선택 요구 사항 : 없음
- 페이지 조회수를 증가시키는 조건은 다음과 같다. 한 마디로 표현하면 "마지막으로 고친 사람이 자기 자신인 페이지를 볼 때는 조회수가 늘어나지 않는다"인데, 같은 IP 에서 둘 이상이 서로 로긴할 수도 있고, 유동 IP 를 쓰는 경우 등을 고려해서 다음과 같이 결정한다.
- 로그인하지 않은 상태에서 페이지를 수정한 경우
- 로그인하지 않고 볼 때는 IP 주소가 다르면 증가. 같으면 증가하지 않음
- 로그인한 사용자가 볼 때는 카운터 증가
- 로그인한 사용자가 페이지를 수정한 경우
- 로그인하지 않고 볼 때는 IP 주소가 수정자와 다르면 증가.
- 로그인하고 볼 때는 동일한 username 이면 증가하지 않고 다르면 증가함.
- 부작용 :
- 각 페이지의 카운터를 "페이지이름.cnt" 라는 화일을 만들어 기록한다. 매번 페이지를 볼 때마다 해당 화일을 열고 쓰고 닫아야 한다. 이 홈에서 테스트할 때는 milisecond 단위로도 거의 차이가 없는 것으로 봐서 화일 입출력 시간 자체는 문제가 아닌데, 일관성 유지를 위해서 기록하는 순간에 lock 을 걸기 때문에 동시 방문자 수가 매우 많은 사이트의 경우 대문이나 최근변경내역 같은 페이지를 볼 때는 lock 을 경쟁하느라 문제가 생길 수 있다. 이 소스에서는 lock 을 얻는 데 실패할 경우, "단 한 번 재시도. 재시도 하기 전에 1초 대기. 재시도가 실패하면 조회수 갱신을 포기"하도록 인자를 주었기 때문에 별 탈이 없을 거라 희망하지만... 모르는 일이다.
- 가끔 어느 페이지의 카운트가 0으로 리셋되어 버리는 경우가 발생한다. 즉 그다지 신뢰성이 없는 카운터 -_-;;;
- config.pl 에 카운터 화일들이 저장될 디렉토리를 지정한다.
$CountDir = "$DataDir/count";
- wiki.pl
...
use vars qw(
$UserGotoBar $UserGotoBar2 $UserGotoBar3 $UserGotoBar4
...
$LogoPage $CheckTime $LinkDir $IconDir $CountDir # $CountDir 추가
);
...
use vars qw(%RevisionTs $FS_lt $FS_gt $StartTime $Sec_Revision $Sec_Ts
$ViewCount);
...
-
sub BrowsePage {
my ($id) = @_;
my ($fullHtml, $oldId, $allDiff, $showDiff, $openKept);
my ($revision, $goodRevision, $diffRevision, $newText);
&OpenPage($id);
&OpenDefaultText();
if (-f &GetPageFile($id)) {
$ViewCount = &GetPageCount($id) if (-f &GetPageFile($id));
}
$openKept = 0;
...
}
-
sub GetEditGuide {
...
if ($UseDiff) {
$result .= ' ' . &ScriptLinkDiff(4, $id, T('(diff)'), $rev);
}
$result .= '<br>';
$result .= Ts('%s hit' . (($ViewCount > 1)?'s':'') , $ViewCount)." | " if ($ViewCount ne "");
$result .= &GetHistoryLink($id, T('History'));
if ($rev ne '') {
...
}
-
sub DeletePage {
...
&UnlinkHtmlCache($page);
$fname = &GetCountFile($page);
unlink ($fname) if (-f $fname);
...
}
-
sub RenamePage {
...
&UnlinkHtmlCache($old);
my ($oldcnt, $newcnt);
$oldcnt = &GetCountFile($old);
if (-f $oldcnt) {
$newcnt = &GetCountFile($new);
&CreatePageDir($CountDir, $new);
rename($oldcnt, $newcnt) || die "error while renaming count file";
}
...
}
-
sub GetCountFile {
my ($id) = @_;
return $CountDir . "/" . &GetPageDirectory($id) . "/$id.cnt";
}
sub GetPageCount {
my ($id) = @_;
my ($pagecount, $countfile, $status);
my ($edit_user, $edit_ip, $view_user, $view_ip, $add)
= ($Section{'username'}, $Section{'ip'},
&GetParam('username', ""), $ENV{REMOTE_ADDR}, 0);
&CreatePageDir($CountDir, $id);
$countfile = &GetCountFile($id);
($status, $pagecount) = &ReadFile($countfile);
$pagecount = 0 if ($status == 0);
if ($view_user eq "") {
if ($edit_ip ne $view_ip) {
$add = 1;
}
} elsif ($edit_user ne $view_user) {
$add = 1;
}
if (&GetParam('InFrame',"") ne "") {
$add = 0;
}
$pagecount += $add;
if ($add == 1) {
&RequestLockDir('count', 1, 1, 0) || return $pagecount;
&WriteStringToFile($countfile, $pagecount);
&ReleaseLockDir('count');
}
return $pagecount;
}
&DoWikiRequest() if ($RunCGI && ($_ ne 'nocgi'));
1;
- action=maintain 을 하면, 현재 조회수 화일이 만들어지지 않은 페이지들에 대해 조회수를 "0"으로 세팅해준다.
sub DoMaintain {
...
foreach $name (&AllPagesList()) {
&OpenPage($name);
&OpenDefaultText();
&ExpireKeepFile();
&SaveLinkFile($name);
if (!(-f &GetCountFile($name))) {
&CreatePageDir($CountDir, $name);
&WriteStringToFile(&GetCountFile($name), "0");
}
print ".... " if ($name =~ m|/|);
print &GetPageLink($name), "<br>\n";
}
...
}
Notes
번역 화일에서 "15 hits" 를 "조회수 : 15" 같이 순서를 바꾸는 것을 위해서... T('hits') 를 Ts('%s hits', $ViewCount) 로 바꿨습니다.
조회수가 0 또는 1일 때는 hits 대신 hit 라고 나오게 다시 고쳤습니다.
$result .= Ts('%s hit' . (($ViewCount > 1)?'s':'') , $ViewCount)." | " if ($ViewCount ne "");
위키위키분류