############################################################ # # 検索を実行して結果を表示するアクションプラグイン # BugTrack-plugin/396 # 2009-01-09 版 # ############################################################ package plugin::search::SearchHandler; use strict; #=========================================================== # コンストラクタ #=========================================================== sub new { my $class = shift; my $self = {}; return bless $self,$class; } #=========================================================== # アクションの実行 #=========================================================== sub do_action { my $self = shift; my $wiki = shift; my $cgi = $wiki->get_CGI; my $word = Util::trim($cgi->param("word")); my $buf = ""; my $or_search = $cgi->param('t') eq 'or'; my $with_content = $cgi->param('c') eq 'true'; $wiki->set_title("検索"); $buf .= "<form method=\"GET\" action=\"".$wiki->create_url()."\">\n". "キーワード <input type=\"text\" name=\"word\" size=\"20\" value=\"".&Util::escapeHTML($word)."\"> "; $buf .= "<input type=\"radio\" name=\"t\" id=\"and\" value=\"and\""; $buf .= " checked" if (not $or_search); $buf .= "><label for=\"and\">AND</label>\n"; $buf .= "<input type=\"radio\" name=\"t\" id=\"or\" value=\"or\""; $buf .= " checked" if ($or_search); $buf .= "><label for=\"or\">OR</label>\n"; $buf .= "<input type=\"checkbox\" id=\"contents\" name=\"c\" value=\"true\""; $buf .= " checked" if ($with_content); $buf .= "><label for=\"contents\">ページ内容も含める</label>\n"; $buf .= "<input type=\"submit\" value=\" 検 索 \">". "<input type=\"hidden\" name=\"action\" value=\"SEARCH\">". "</form>\n"; my $ignore_case = 1; my $conv_upper_case = ($ignore_case and $word =~ /[A-Za-z]/); $word = uc $word if ($conv_upper_case); my @words = grep { $_ ne '' } split(/ +| +/, $word); return $buf unless (@words); #--------------------------------------------------------------------------- # 検索実行 my @list = $wiki->get_page_list({-permit=>'show'}); my $res = ''; PAGE: foreach my $name (@list){ # ページ名も検索対象にする my $page = $name; $page .= "\n".$wiki->get_page($name) if ($with_content); my $pageref = ($conv_upper_case) ? \(my $page2 = uc $page) : \$page; my $index; if ($or_search) { # OR検索 ------------------------------------------------------- WORD: foreach(@words){ next WORD if (($index = index $$pageref, $_) == -1); $res .= "<li>". "<a href=\"".$wiki->create_page_url($name)."\">".Util::escapeHTML($name)."</a>". " - ". Util::escapeHTML(&get_match_content($wiki, $page, $index)). "</li>\n"; next PAGE; } } else { # AND検索 ------------------------------------------------------ WORD: foreach(@words){ next PAGE if (($index = index $$pageref, $_) == -1); } $res .= "<li>". "<a href=\"".$wiki->create_page_url($name)."\">".Util::escapeHTML($name)."</a>". " - ". Util::escapeHTML(&get_match_content($wiki, $page, $index)). "</li>\n"; } } return "$buf<ul>\n$res</ul>\n" if ($res ne ''); return $buf; } #=========================================================== # 検索にマッチした行を取り出す関数 #=========================================================== sub get_match_content { my $wiki = shift; my $content = shift; my $index = shift; # 検索にマッチした行の先頭文字の位置を求める。 # ・$content の $index 番目の文字から先頭方向に改行文字を探す。 # ・$index の位置を含む行の先頭文字の位置は改行文字の次なので +1 する。 # ・先頭方向に改行文字が無かったら最初の行なので、結果は 0(先頭)。 # (見つからないと rindex() = -1 になるので、+1 してちょうど 0) my $pre_index = rindex($content, "\n", $index) + 1; # 検索にマッチした行の末尾文字の位置を求める。 # ・$content の $index 番目の文字から末尾方向に改行文字を探す。 my $post_index = index($content, "\n", $index); # 末尾方向に改行文字がなかったら最終行なので $pre_index 以降全てを返却。 return substr($content, $pre_index) if ($post_index == -1); # 見つかった改行文字に挟まれた文字列を返却。 return substr($content, $pre_index, $post_index - $pre_index); } 1;