<?php

// h-source, a web software to build a community of people that want to share their hardware information.
// Copyright (C) 2010  Antonio Gallo (h-source-copyright.txt)
//
// This file is part of h-source
//
// h-source is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// h-source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with h-source.  If not, see <http://www.gnu.org/licenses/>.

if (!defined('EG')) die('Direct access not allowed!');

class WikiModel extends Model_Map {

	public $id_user = 0;
	public $lastId = 0; //the id of the last record inserted
	public $lastTitle = null; //the title of the last page inserted
	public $lastTitleClean = null; //the cleaned title of the last page inserted

	public $diffFields = array();
	public $fieldsWithBreaks = array();
	
	public function __construct() {
		$this->_tables='wiki,regusers,wiki_users';
		$this->_idFields='id_wiki,id_user';
		$this->_where=array(
			'username'			=>	'regusers',
			'id_user'			=>	'regusers',
			'has_confirmed'		=>	'regusers',
			'deleted'			=>	'regusers',
			'-deleted'			=>	'wiki',
			'-blocked'			=>	'wiki',
		);
		
		$this->printAssError = "no";

		$this->diffFields = array(
			'title' 		=>	gtext("the title"),
			'page'		 	=>	gtext('the text of the wiki page'),
		);

		$this->fieldsWithBreaks = array(gtext('the text of the wiki page'));

		$this->strongConditions['insert'] = array(
			"checkNotEmpty"		=>	'title',
			"checkLength|99"	=>	'title|'.gtext('title is too long'),
			"+checkNotEmpty"	=>	'page',
			"+checkLength|49900"	=>	'page|'.gtext('the page text is too long'),
		);

		$this->strongConditions['update'] = array(
			"checkNotEmpty"		=>	'title',
			"checkLength|99"	=>	'title|'.gtext('title is too long'),
			"+checkNotEmpty"	=>	'page',
			"+checkLength|49900"	=>	'page|'.gtext('the page text is too long'),
		);

		$this->databaseConditions['insert'] = array(
			"checkUnique"		=>	'title|'.gtext('a page with the same title already exists'),
		);

		$this->databaseConditions['update'] = array(
			"checkUniqueCompl"	=>	'title|'.gtext('a page with the same title already exists'),
		);
		
		parent::__construct();
	}

	public function pUpdate($id)
	{
		return parent::update($id);
	}

	public function insert()
	{
		$this->values['created_by'] = (int)$this->id_user;
		$this->values['update_date'] = date('Y-m-d H:i:s');
		
		//random ID
		$randomId = md5(uniqid(mt_rand(),true));
		$this->values["title_clean"] = $randomId;

		parent::insert();
		
		//associate the user to the record
		if ($this->queryResult)
		{
			$resId =  $this->select()->where(array('title_clean'=>$randomId))->send();
			$clean['id'] = $resId[0]['wiki']['id_wiki'];
			$this->lastId = $clean['id'];
			$this->lastTitle = $resId[0]['wiki']['title'];
			$this->lastTitleClean = titleForRedirect($resId[0]['wiki']['title']);
			$this->db->update('wiki','title_clean',array(encodeUrl(sanitizeDb($resId[0]['wiki']['title']))),'id_wiki='.$clean['id']);

			//update the history table
			$this->updateHistory('insert');
			
			$this->associate($clean['id']);
		}
		 
	}

	public function update($id)
	{
		$clean['id'] = (int)$id;

		$this->values['created_by'] = (int)$this->id_user;
		$this->values['update_date'] = date('Y-m-d H:i:s');
		$this->values['title_clean'] = encodeUrl($this->values['title']);
		
		//save the old fields in the revisions table
		$this->setWhereQueryClause(array('id_wiki'	=>	$clean['id']));
		$oldStruct = $this->getFields($this->fields.',title_clean,created_by,update_date,id_wiki');
		
		if (count($oldStruct > 0))
		{
			$oldValues = $oldStruct[0]['wiki'];

			$revisions = new WikirevisionsModel();
			$revisions->values = $oldValues;
			
			$revisions->sanitize();
			
			if ($revisions->insert())
			{
				
				if ($this->isMain($clean['id']))
				{
					$this->values['title'] = 'Main Page';
					$this->values['title_clean'] = 'Main-Page';
				}
				
				parent::update($clean['id']);
				if ($this->queryResult)
				{
					$this->lastId = $clean['id'];
					$this->lastTitle = $this->values['title'];
					$this->lastTitleClean = html_entity_decode($this->values['title_clean'],ENT_QUOTES,DEFAULT_CHARSET);
					
					//update the history table
					$this->updateHistory('update');

					if (!$this->checkAssociation($clean['id'],(int)$this->id_user))
					{
						$this->associate($clean['id']);
					}
				}
			}
		}
	}

	public function makeCurrent($id_rev)
	{
		
		$clean['id_rev'] = (int)$id_rev;
		
		$revisions = new WikirevisionsModel();
		
		$clean['id_wiki'] = (int)$revisions->getIdPage($clean['id_rev']);
		
		//save the old fields in the revisions table
		$this->where(array('id_wiki'=>$clean['id_wiki']));
		$oldStruct = $this->getFields($this->fields.',title_clean,created_by,update_date,id_wiki');
		
		if (count($oldStruct > 0))
		{
			//get the values of the revision
			$revisions->where(array('id_rev'=>$clean['id_rev']));
			$newStruct = $revisions->getFields($this->fields.',title_clean,created_by,update_date');

			if (count($newStruct > 0))
			{
				$revisions->values = $oldStruct[0]['wiki'];
				$revisions->sanitize();
				
				$this->values = $newStruct[0]['wiki_revisions'];
				$this->values['created_by'] = (int)$this->id_user;
				$this->values['update_date'] = date('Y-m-d H:i:s');

				$this->sanitize();
				
				if ($this->isMain($clean['id_wiki']))
				{
					$this->values['title'] = 'Main Page';
					$this->values['title_clean'] = 'Main-Page';
				}
				
				if ($revisions->insert())
				{
					if (parent::update($clean['id_wiki']))
					{
						$this->lastId = $clean['id_wiki'];
						$this->lastTitle = $this->values['title'];
						$this->lastTitleClean = html_entity_decode($this->values['title_clean'],ENT_QUOTES,DEFAULT_CHARSET);
						
						//update the history table
						$this->updateHistory('update');

						if (!$this->checkAssociation($clean['id_wiki'],(int)$this->id_user))
						{
							$this->associate($clean['id_wiki']);
						}
					}
				}
			}
		}
		
	}

	public function associate($id_record)
	{
		return parent::associate((int)$id_record,(int)$this->id_user);
	}

	//get the model name
	public function getTheModelName($id, $cleaned = false)
	{
		$clean['id'] = (int)$id;
		$this->setWhereQueryClause(array('id_wiki' => $clean['id']));
		$res = $this->getFields('title,title_clean');
		$name = '';
		if (count($res) > 0)
		{
			if ($cleaned)
			{
				$name = $res[0]['wiki']['title_clean'];
			}
			else
			{
				$name = $res[0]['wiki']['title'];
			}
		}
		return $name;
	}

	//save in the history all the action carried out by users
	protected function updateHistory($action)
	{
		$translations = array(
			'insert'		=>	'inserted',
			'update'		=>	'updated',
		);

		$allowedActions = array('insert','update');

		if (in_array($action,$allowedActions))
		{
			$users = new UsersModel();

			$clean['user'] = sanitizeAll($users->getUser($this->id_user));
			
			$history = new HistoryModel();
			$history->values = array(
				'created_by' 	=>	$this->id_user,
				'type'			=>	'wiki',
				'action'		=>	$action,
				'id'			=>	$this->lastId,
				'message'		=>	'The wiki page having id='.$this->lastId.' has been '.$translations[$action].' by the user ' . $clean['user'] . ' (id_user='.$this->id_user.') ',
				'gr'			=>	'registered',
			);
			$history->insert();
		}
	}

	public function isMain($id)
	{
		$clean['id'] = (int)$id;
		$res = $this->select('is_main')->where(array('id_wiki'=>$clean['id']))->send();
		if ( count($res) > 0 )
		{
			return strcmp($res[0]['wiki']['is_main'],'no') === 0 ? false : true;
		}
		return false;
	}

	public function isDeleted($id)
	{
		$clean['id'] = (int)$id;
		$res = $this->select('wiki.deleted')->where(array('id_wiki'=>$clean['id']))->send();
		if ( count($res) > 0 )
		{
			return strcmp($res[0]['wiki']['deleted'],'no') === 0 ? false : true;
		}
		return false;
	}

	public function isBlocked($id)
	{
		$clean['id'] = (int)$id;
		$res = $this->select('blocked')->where(array('id_wiki'=>$clean['id']))->send();
		if ( count($res) > 0 )
		{
			return strcmp($res[0]['wiki']['blocked'],'no') === 0 ? false : true;
		}
		return false;
	}

	public function toWikiPage($id)
	{
		$clean['id'] = (int)$id;
		$title = $this->getTheModelName($clean['id'], true);
		return "http://".DOMAIN_NAME."/wiki/page/".Lang::$current."/".$title;
	}

	public function getDiffArray($oldArray, $newArray)
	{
		return getDiffArray($this->diffFields, $oldArray, $newArray);
	}
}