<?php
/*
 * $Id: fuzzylink.inc.php,v 1.1 2005/02/26 07:16:20 youka Exp $
 */



/**
 * あいまいリンクのための正規表現を管理するクラス。シングルトンのように振舞う。
 */
class FuzzyLink
{
	/** あいまいリンクの正規表現 */
	protected static $expression;
	/** あいまいリンク対象外のページ */
	protected static $ignorelist;
	/** あいまいリンク対象外を列挙するページの名前 */
	const ignorelistpage = ':config/AutoLink/ignore';
	
	
	/**
	 * インスタンスを取得する。
	 */
	static function getinstance()
	{
		return new self;
	}
	
	
	/**
	 * コンストラクタ。
	 */
	protected function __construct()
	{
		if(empty(self::$ignorelist)){
			$this->makeignorelist();
		}
	}
	
	
	/**
	 * ignoreリストを構築する。
	 */
	protected function makeignorelist()
	{
		self::$ignorelist = array();
		$page = Page::getinstance(self::ignorelistpage);
		$lines = explode("\n", $page->getsource());
		foreach($lines as $str){
			if(mb_ereg('^-\[\[(.+)\]\]', $str, $m)){
				self::$ignorelist[] = $m[1];
			}
		}
	}
	
	
	/**
	 * あいまいリンク用正規表現を取得する。
	 * 
	 * @return	string	正規表現。
	 */
	function getexpression()
	{
		if(empty(self::$expression)){
			$db = DataBase::getinstance();
			
			$result = $db->query("SELECT exp FROM fuzzylink_exp");
			$row = $db->fetch($result);
			if($row == false){
				$exp = makelinkexp($this->listup());
				$_exp = $db->escape($exp);
				$db->query("INSERT INTO fuzzylink_exp (exp) VALUES('$_exp')");
				self::$expression = $exp;
			}
			else{
				self::$expression = $row['exp'];
			}
		}
		return self::$expression;
	}
	
	
	/**
	 * あいまいリンクの対象となるページのキーワードを列挙する。
	 * 
	 * @return	array(string)	相対パス。
	 */
	protected function listup()
	{
		$db = DataBase::getinstance();
		$result = $db->query("SELECT DISTINCT key FROM fuzzylink_list");
		$list = array();
		while($row = $db->fetch($result)){
			$list[] = $row['key'];
		}
		return $list;
	}
	
	
	/**
	 * 無視ページかどうかを確認する。
	 * 
	 * @param	string	$pagename	ページ名。
	 * @return	bool	無視ページの場合true。
	 */
	protected function isignored($pagename)
	{
		return in_array($pagename, self::$ignorelist);
	}
	
	
	/**
	 * キーワードからページを取得する。
	 * 
	 * @param	string	$key	キーワード
	 * @return	array(Page)
	 */
	function getpagelist($key)
	{
		$db = DataBase::getinstance();
		$_key = $db->escape($key);
		$result = $db->query("SELECT pagename FROM fuzzylink_list WHERE key LIKE '$_key'");
		$list = array();
		while($row = $db->fetch($result)){
			$list[] = Page::getinstance($row['pagename']);
		}
		return $list;
	}
	
	
	/**
	 * ページ更新と同時にあいまいリンク用正規表現を更新する。
	 */
	function update($page)
	{
		if($page->isexist() && !$page->isexist(1)){
			$this->addpage($page);
		}
		else if(!$page->isexist() && $page->isexist(1)){
			$this->delpage($page);
		}
		
		if($page->getpagename() == self::ignorelistpage){
			$this->makeignorelist();
		}
		self::getinstance()->refresh();
	}
	
	
	/**
	 * あいまいリンク用正規表現を作り直す。
	 */
	function refresh()
	{
		$db = DataBase::getinstance();
		$db->query("DELETE FROM fuzzylink_exp");
		self::$expression = array();
	}
	
	
	/**
	 * あいまいリンク用ページリストを作り直す。
	 */
	function restruct()
	{
		$db = DataBase::getinstance();
		$db->begin();
		
		if($db->istable('fuzzylink_list')){
			$db->query("DELETE FROM fuzzylink_list");
		}
		else{
			$query = explode(';', file_get_contents(CMD_DIR . 'fuzzylink/sql.txt'));
			foreach($query as $q){
				$q = trim($q);
				if($q != ''){
					$db->query($q);
				}
			}
		}
		
		$result = $db->query("SELECT pagename FROM page");
		while($row = $db->fetch($result)){
			$this->addpage(Page::getinstance($row['pagename']));
		}
		$this->refresh();
		
		$db->commit();
	}
	
	
	/**
	 * あいまいリンク用リストにページを加える。
	 */
	protected function addpage($page)
	{
		if(mb_ereg('/([^/]+?)$', $page->getpagename(), $m)){
			$key = $m[1];
		}
		else{
			$key = $page->getpagename();
		}
		
		$db = DataBase::getinstance();
		$_key = $db->escape($key);
		$_pagename = $db->escape($page->getpagename());
		$db->query("INSERT INTO fuzzylink_list (key, pagename) VALUES('$_key', '$_pagename')");
	}
	
	
	/**
	 * あいまいリンク用リストからページを削除する。
	 */
	protected function delpage($page)
	{
		$db = DataBase::getinstance();
		$_pagename = $db->escape($page->getpagename());
		$db->query("DELETE FROM fuzzylink_list WHERE pagename = '$_pagename'");
	}
}

?>