総ページ数が増えると、AutoLink の正規表現のサイズが大きくなりすぎ make_link() が正常に機能しなくなるのが原因でページそのものが正常に表示されなくなります。
とりあえず、AutoLink の処理を他のインライン処理とは別に分けて処理するようにしてみました。
function get_autolink_pattern(& $pages)
{
global $WikiName, $autolink, $nowikiname;
$config = &new Config('AutoLink');
$config->read();
$ignorepages = $config->get('IgnoreList');
$forceignorepages = $config->get('ForceIgnoreList');
unset($config);
$auto_pages = array_merge($ignorepages, $forceignorepages);
foreach ($pages as $page) {
if (preg_match("/^$WikiName$/", $page) ?
$nowikiname : strlen($page) >= $autolink)
$auto_pages[] = strip_bracket($page);
}
if (count($auto_pages) == 0) {
return $nowikiname ? '(?!)' : $WikiName;
}
$auto_pages = array_unique($auto_pages);
sort($auto_pages, SORT_STRING);
//$auto_pages_a = array_values(preg_grep('/^[A-Z]+$/i', $auto_pages));
//$auto_pages = array_values(array_diff($auto_pages, $auto_pages_a));
//$result_a = get_autolink_pattern_sub($auto_pages_a, 0, count($auto_pages_a), 0);
//$result_a = get_autolink_pattern_sub($result_a, 0, 0, 0);
$result = array();
$start = 0;
$max = 3000;
$count = count($auto_pages);
while($count > $start)
{
$pages = array_slice($auto_pages,$start,$max);
$result[] = get_autolink_pattern_sub($pages, 0, count($pages), 0);
$start = $start + $max;
}
return array(join("\t",$result), '(?!)', $forceignorepages);
}
class InlineConverter
{
var $converters; // as array()
var $pattern;
var $pos;
var $result;
function InlineConverter($converters=NULL,$excludes=NULL)
{
if ($converters === NULL)
{
$converters = array(
'plugin', // インラインプラグイン
'note', // 注釈
'url', // URL
'url_interwiki', // URL (interwiki definition)
'mailto', // mailto:
'interwikiname', // InterWikiName
//'autolink', // AutoLink
'bracketname', // BracketName
'wikiname', // WikiName
//'autolink_a', // AutoLink(アルファベット)
//'eword',
//'escape', // escape
);
}
if ($excludes !== NULL)
{
$converters = array_diff($converters,$excludes);
}
$this->converters = array();
$patterns = array();
$start = 1;
foreach ($converters as $name)
{
$classname = "Link_$name";
$converter = new $classname($start);
$pattern = $converter->get_pattern();
if ($pattern === FALSE)
{
continue;
}
$patterns[] = "(\n$pattern\n)";
$this->converters[$start] = $converter;
$start += $converter->get_count();
$start++;
}
+ $this->pattern = join('|',$patterns);
! $this->pattern = join('|',$patterns);
}
function convert($string,$page)
{
$this->page = $page;
$this->result = array();
$string = preg_replace_callback("/{$this->pattern}/x",array(&$this,'replace'),$string);
$arr = explode("\x08",make_line_rules(htmlspecialchars($string)));
//$arr = explode("\x08",make_line_rules($string));
$retval = '';
while (count($arr))
{
$retval .= array_shift($arr).array_shift($this->result);
}
// オートリンク by nao-pon
// InlineConverter による一括処理では、
// ページ数増加(約5000ページ以上)時に正常に処理できない。
$retval = $this->auto_link($retval);
return $retval;
}
function replace($arr)
{
$obj = $this->get_converter($arr);
$this->result[] = ($obj !== NULL and $obj->set($arr,$this->page) !== FALSE) ?
$obj->toString() : make_line_rules(htmlspecialchars($arr[0]));
return "\x08"; //処理済みの部分にマークを入れる
}
function get_objects($string,$page)
{
preg_match_all("/{$this->pattern}/x",$string,$matches,PREG_SET_ORDER);
$arr = array();
foreach ($matches as $match)
{
$obj = $this->get_converter($match);
if ($obj->set($match,$page) !== FALSE)
{
$arr[] = $obj; // copy
if ($obj->body != '')
{
$arr = array_merge($arr,$this->get_objects($obj->body,$page));
}
}
}
return $arr;
}
function &get_converter(&$arr)
{
foreach (array_keys($this->converters) as $start)
{
if ($arr[$start] == $arr[0])
{
return $this->converters[$start];
}
}
return NULL;
}
// 別処理でのオートリンク by nao-pon
function auto_link(&$str)
{
global $autolink;
if (!$autolink) return $str;
static $auto;
static $auto_a;
static $forceignorepages;
if (!$auto && !$auto_a)
{
@list($auto,$auto_a,$forceignorepages) = file(CACHE_DIR.'autolink.dat');
$auto = trim($auto);
$auto_a = trim($auto_a);
$forceignorepages = trim($forceignorepages);
}
// ページ数が多い場合は、セパレータ \t で複数パターンに分割されている
foreach(explode("\t",$auto) as $pat)
{
+ $pattern = "/(<(?:a|A).*?<\/(?:a|A)>|<[^>]*>|&(?:#[0-9]+|#x[0-9a-f]+|[0-9a-zA-Z]+);)|($pat)/s";
! $pattern = "/(<(?:a|A).*?<\/(?:a|A)>|<[^>]*>|&(?:#[0-9]+|#x[0-9a-f]+|[0-9a-zA-Z]+);)|($pat)/s";
$str = preg_replace_callback($pattern,array(&$this,'auto_link_replace'),$str);
}
return $str;
}
function auto_link_replace($match)
{
global $pagename_aliases;
if (!empty($match[1])) return $match[1];
$alias = $name = $match[2];
// ページが存在しない場合
if (!is_page($name))
{
// ページ名エイリアスを探す
if (array_key_exists($name,$pagename_aliases))
{
$name = $pagename_aliases[$name];
}
else
{
// 共通リンクディレクトリを探す
if (!$name = get_real_pagename($name)) return $match[1];
}
}
return make_pagelink($name,$alias,'',$name);
}
}
AutoLink の正規表現を3000ページごとに分割して作っておき、分割して置換処理しています。
ただ、現状で次のような問題があります。
function get_autolink_pattern_sub(& $pages, $start, $end, $pos)
{
static $lev = 0;
static $limit = 0;
static $full = false;
static $psize = 0;
if ($end == 0) return '(?!)';
$lev ++;
if (!$limit) $limit = 30 * 1024; //マージンを持たせて 30kb で分割
$result = '';
$count = 0;
$x = (mb_strlen($pages[$start]) <= $pos);
if ($x) { ++$start; }
for ($i = $start; $i < $end; $i = $j) // What is the initial state of $j?
{
$full = (strlen($result) - $psize > $limit);
$char = mb_substr($pages[$i], $pos, 1);
for ($j = $i; $j < $end; $j++)
{
if (mb_substr($pages[$j], $pos, 1) != $char || $full) { break; }
}
if ($i != $start && $psize != strlen($result)) { $result .= '|'; }
if ($i >= ($j - 1))
{
$result .= str_replace(' ', '\\ ', preg_quote(mb_substr($pages[$i], $pos), '/'));
}
else
{
$result .= str_replace(' ', '\\ ', preg_quote($char, '/')) .
get_autolink_pattern_sub($pages, $i, $j, $pos + 1);
}
if ($lev === 1 && $full)
{
$result .= ")\t(?:";
$psize = strlen($result);
$j++; //これでいいのか?
}
++$count;
}
if ($x or $count > 1) { $result = '(?:' . $result . ')'; }
if ($x) { $result .= '?'; }
$lev --;
return $result;
}
| Page name: | PukiWikiMod/BugTrack/30 [ Sended pings(5) ] | |
| Author: | nao-pon | - 2006/08/28 18:10:03 JST(691d) |
| Last edit: | 通りすがりさん | - 2006/09/20 04:00:05 JST(669d) |
| Editers: | 登録ユーザー | |
| Back Link: | 通りすがりさん(15d) PukiWikiMod(59d) nao-pon(103d) PukiWiki(117d) modPukiWikiの組み込み(492d) 通りすがりさん(647d) テスト(737d) matio(954d) GuymHaga(1009d) nao-pon(1017d) PHP(1018d) BugTrack(1041d) | |
ログイン
アクティブメニュー
"ぽちっ"としてね☆
最新のページ
ブックマーク
新着トラックバック
サイト内 Wiki
☆ 検索 ☆
オンライン状況
サイト情報
現在ページのQRコード
参照元情報