<?php


/**
 * Pageにバックアップを付加したクラス。
 */
class BackupedPage extends Page
{
	/**
	 * 存在するPageならばTrueを返す。
	 */
	function isexist($num = 0)
	{
		return $this->getsource($num) != '';
	}
	
	
	/**
	 * バックアップを取りつつ保存する。
	 */
	function write($source, $notimestamp = false)
	{
		$db = DataBase::getinstance($this->wikiid);
		$db->begin();
		
		$old = $this->getsource();
		$timestamp = $this->gettimestamp();
		$num = $this->getbackupnumber();
		if($old != '' || $num != 0){
			$pagename = $db->escape($this->pagename);
			$_old = $db->escape($old);
			$query  = "INSERT INTO pagebackup (number, pagename, source, timestamp)";
			$query .= " VALUES(NULL, '$pagename', '$_old', '$timestamp')";
			$db->query($query);
			//指定件数以上のバックアップデータの削除
			$max = BACKUP_MAX;
			$query  = "DELETE FROM pagebackup";
			$query .= " WHERE number IN (SELECT number FROM pagebackup ";
			$query .= "  WHERE pagename = '$pagename'";
			$query .= "  ORDER BY number DESC LIMIT -1 OFFSET $max)";
			$db->query($query);
		}
		parent::write($source, $notimestamp);
		$db->commit();
	}
	
	
	/**
	 * ソースを取得する。
	 * 
	 * @param	int	$num	0の時は現在のソースを、１以上の場合はバックアップを取得する。
	 * @return	string	ソース。無い場合は空文字列。
	 */
	function getsource($num = 0)
	{
		if($num == 0){
			return parent::getsource();
		}
		
		$num -= 1;
		$db = DataBase::getinstance($this->wikiid);
		$pagename = $db->escape($this->pagename);
		$query  = "SELECT source FROM pagebackup";
		$query .= " WHERE pagename = '$pagename'";
		$query .= " ORDER BY number DESC LIMIT 1 OFFSET $num";
		$row = $db->fetch($db->query($query));
		return $row != false ? $row['source'] : '';
	}
	
	
	/**
	 * タイムスタンプを取得する。
	 * 
	 * @param	int	$num	0の時は現在のものを、1以上の時はバックアップのものを取得する。
	 * @return	int	タイムスタンプ。無い場合は現在の時刻を返す。
	 */
	function gettimestamp($num = 0)
	{
		if($num == 0){
			return parent::gettimestamp();
		}
		
		$num -= 1;
		$db = DataBase::getinstance($this->wikiid);
		$pagename = $db->escape($this->pagename);
		$query  = "SELECT timestamp FROM pagebackup";
		$query .= " WHERE pagename = '$pagename'";
		$query .= " ORDER BY number DESC LIMIT 1 OFFSET $num";
		$row = $db->fetch($db->query($query));
		return $row != false ? $row['timestamp'] : TIME;
	}
	
	
	/**
	 * バックアップ一覧を取得する。
	 * 
	 * @return	array(int $timestamp)	タイムスタンプはソート済み。
	 */
	function getbackuplist()
	{
		$db = DataBase::getinstance($this->wikiid);
		
		$pagename = $db->escape($this->pagename);
		$query  = "SELECT timestamp FROM pagebackup";
		$query .= " WHERE pagename = '$pagename'";
		$query .= " ORDER BY number DESC";
		
		$result = $db->query($query);
		$ret = array();
		while($row = $db->fetch($result)){
			$ret[] = $row['timestamp'];
		}
		return $ret;
	}
	
	
	/**
	 * 差分をとる。
	 * 
	 * @param	int	$num1	比較するバックアップの番号。
	 * @param	int	$num2	比較するバックアップの番号。
	 * @return	Text_Diff
	 */
	function diff($num1, $num2)
	{
		$source = $this->getsource($num1);
		$backup = $this->getsource($num2);
		return new Text_Diff(explode("\n", $backup), explode("\n", $source));
	}
	
	
	/**
	 * バックアップを削除する。
	 */
	function deletebackup()
	{
		$db = DataBase::getinstance($this->wikiid);
		
		$pagename = $db->escape($this->pagename);
		$query  = "DELETE FROM pagebackup";
		$query .= " WHERE pagename = '$pagename'";
		
		$db->query($query);
	}
	
	
	/**
	 * （このページの）バックアップの数を取得する。
	 * 
	 * @return	int
	 */
	function getbackupnumber()
	{
		$db = DataBase::getinstance($this->wikiid);
		
		$pagename = $db->escape($this->pagename);
		$query  = "SELECT count(*) FROM pagebackup";
		$query .= " WHERE pagename = '$pagename'";
		
		$row = $db->fetch($db->query($query));
		return $row[0];
	}
}



/**
 * Wikiにバックアップを付加したクラス。
 */
class BackupedWiki extends Wiki
{
	/**
	 * バックアップページ一覧を取得する。
	 * 
	 * @return	array(string $pagename)	ページ名はソート済み。
	 */
	function getbackuplist()
	{
		$db = DataBase::getinstance($this->wikiid);
		
		$query  = "SELECT DISTINCT pagename FROM pagebackup ORDER BY pagename ASC";
		$result = $db->query($query);
		$ret = array();
		while($row = $db->fetch($result)){
			$ret[] = $row['pagename'];
		}
		return $ret;
	}
}



?>