hypweb.net
XOOPSマニア  最新情報のRSS(サイト全体)
[ 自宅サーバーWebRing |ID=54 前後5表示乱移動サイト一覧 ]

17年9月25日(Mon) 10時09分
Counter: 13900, today: 2, yesterday: 0

総ページ数が増えるとAutoLinkが原因で正常にページが表示されなくなる この見出しの固定リンク

  • ページ: PukiWikiMod/BugTrack
  • 投稿者: nao-pon
  • 優先順位: 低
  • 状態: 完了
  • カテゴリー: 本体バグ
  • 投稿日: 2005-06-25 (土) 23:17:09
  • バージョン:

メッセージ この見出しの固定リンク

総ページ数が増えると、AutoLink の正規表現のサイズが大きくなりすぎ make_link() が正常に機能しなくなるのが原因でページそのものが正常に表示されなくなります。

参考
PukiWiki開発:BugTrack2/81

とりあえず、AutoLink の処理を他のインライン処理とは別に分けて処理するようにしてみました。

func.php この見出しの固定リンク

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);
}

make_link.php この見出しの固定リンク

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ページごとに分割して作っておき、分割して置換処理しています。

ただ、現状で次のような問題があります。

  • ページ数の増加によりコンバートスピードがだんだん遅くなる。
  • modPukiWiki との互換性がなくなる。
  • ページリンク情報の作成・更新時にAutoLinkしているページを収集しているので、その処理を修正する必要がある。

  • なにか、もっといい方法はないものでしょうか? -- nao-pon 2005-06-25 (土) 23:18:15
  • 新しいリンクのうちいくつかだけ有効とか設定があるといいなと個人的に思っています。話が違うかもしれませんが。(^_^;) -- GuymHaga 2005-07-31 (日) 21:08:22
  • PHP4.4.0で最新版のPukiwikiをつかっていますが、総ページ1200ページで、autolink.datが32Kで、同じような現象になりました。 -- 通りすがりさん 2005-08-07 (日) 14:15:46
  • 約30kbで正規表現を分割する get_autolink_pattern_sub() 関数を考えてみました。 -- nao-pon♦iq8llSWq9g 2005-11-14 (月) 22:27:21
    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;
    }
    
  • 最近、autolink2.dat の容量が肥大化してきたのか、また表示が乱れる現象がおこるようになってきましたが、なぜか原因はつまけていません。とりあえず、autolink は無効としましたが、どうしたものかな?たぶん、autolink2.dat の中の正規表現が何らかの原因でおかしくなっているような気がするのですが…。 -- matio 2006-08-28 (月) 18:10:03
  • ページ数が1000超えると発生します。対応お願いします。 -- 通りすがりさん 2006-09-20 (水) 04:00:05

お名前:
付箋機能(wema) メニュー 
付箋の編集
文字色: 背景色:
お名前:  線接続id:

id.2:
nao-pon♦iq8llSWq9g : 05/11/15 13:37

要修正・メモ この見出しの固定リンク

AutoLink関連 この見出しの固定リンク

  • file.php
  • make_link.php
  • func.php

リンク情報DB関連 この見出しの固定リンク

  • link.php
  • db_func.php


添付ファイル: filefusen.dat 458件 [詳細]

ページコメント
投稿された内容の著作権はコメントの投稿者に帰属します。

トラックバック [ トラックバック(0) ]
トラックバック URL: https://xoops.hypweb.net/wiki/tb/1962

このページのTopへ
ログイン
ユーザ名:

パスワード:

オートログイン

Basic 認証

新規登録 | パスワード紛失



メインメニュー
最新のページ
ブックマーク
オンサイトブックマークは
ログインするとご利用になれます
[ログインする]
新着トラックバック
サイト内 Wiki
☆ 検索 ☆



高度な検索(サイト内)
FireFox検索プラグイン
オンライン状況
合計 52 人がオンライン中 :-)
(Wiki [自由帳] : 1 人)

登録ユーザ: 0 & ゲスト: 52

もっと...
サイト情報
管理人

nao-pon
 

登録ユーザ数: 4459


Web Services by Yahoo! JAPAN
楽天ウェブサービスセンター
Amazon.co.jpアソシエイト
現在ページのQRコード
現在ページのQRコード
[携帯対応]
参照元情報