<?php
class Lucene
{
	static private $lucene = FALSE;
	
	static private $index = FALSE;
	
	private $path = FALSE;
	
	const ITEM	= '__ITEM__';
	const FILE 	= '__FILE__';
	const MEDIA = '__MEDIA__';
	
	private final function __construct ()
	{
		$array = Instance::singleton ()->getLucene ();
		
		if (!is_array ($array) || !array_key_exists ('index-path', $array))
			return;
		
		if (!class_exists ('Zend_Search_Lucene', FALSE))
			return;
		
		$this->path = $array ['index-path'];
		
		try
		{
			Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding ('iso-8859-1');
			
			if (file_exists ($this->getPath ()))
			{
				self::$index = new Zend_Search_Lucene ($this->getPath ());
				
				return;
			}
			
			set_time_limit (0);
			
			self::$index = new Zend_Search_Lucene ($this->getPath (), TRUE);
			
			$aSection = Business::singleton ()->getSection (Section::TCURRENT)->getName ();
			$aAction  = Business::singleton ()->getAction (Action::TCURRENT)->getName ();
			
			$db = Database::singleton ();
			
			set_error_handler ('logPhpError');
			
			while ($section = Business::singleton ()->getSection ())
			{
				$targetActions = array ();
				
				while ($aux = $section->getAction ())
				{
					$indexTo = trim ($aux->getIndex ());
					
					if ($indexTo == '' || !$section->actionExists ($indexTo) || in_array ($indexTo, $targetActions))
						continue;
					
					$targetActions [] = $indexTo;
					
					$action = $section->getAction ($indexTo);
					
					Business::singleton ()->setCurrent ($section->getName (), $action->getName ());
					
					$form = new Form (array ($action->getXmlPath (), $action->getName () .'.xml', $action->getEngine () .'.xml', 'all.xml'));
					
					try
					{
						$sql = "SELECT ". $form->getPrimary () ." FROM ". $form->getTable () ." WHERE _deleted = B'0'";
						
						$sth = $db->prepare ($sql);
						
						$sth->execute ();
					}
					catch (PDOException $e)
					{
						try
						{
							$sql = "SELECT ". $form->getPrimary () ." FROM ". $form->getTable ();
							
							$sth = $db->prepare ($sql);
							
							$sth->execute ();
						}
						catch (PDOException $e)
						{
							toLog ('Lucene Exception: Impossível capturar tuplas de ['. $form->getTable () .'].');
							
							continue;
						}
					}
					
					$primary = $form->getPrimary ();
					
					while ($obj = $sth->fetch (PDO::FETCH_OBJ))
					{
						$itemId = $obj->$primary;
						
						$url = 'titan.php?target=body&toSection='. $section->getName () .'&toAction='. $indexTo .'&itemId='. $itemId;
						
						$doc = new Zend_Search_Lucene_Document ();
							
						$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
						
						$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::ITEM, 'iso-8859-1'));
						
						$doc->addField (Zend_Search_Lucene_Field::Text ('local', getBreadPath ($section, FALSE, FALSE) . $section->getAction ($indexTo)->getLabel (), 'iso-8859-1'));
						
						$doc->addField (Zend_Search_Lucene_Field::Text ('content', $form->getResume ($itemId, TRUE), 'iso-8859-1'));
						
						self::$index->addDocument ($doc);
						
						$form->setLoad (FALSE);
					}
				}
			}
			
			self::$index->commit ();
			
			self::$index->optimize ();
			
			$this->saveFile (array (), TRUE);
			
			restore_error_handler ();
			
			Log::singleton ()->add (__ ('Automatic Lucene Index creation. Added [1] documents.', self::$index->count ()));
			
			Message::singleton ()->addMessage (__ ('Automatic Lucene Index creation. Added [1] documents.', self::$index->count ()));
			
			Business::singleton ()->setCurrent ($aSection, $aAction);
		}
		catch (Exception $e)
		{
			$error = Instance::singleton ()->onDebugMode () ? $e->getMessage () : '';
			
			Message::singleton ()->addWarning (__ ('Error on automatic Lucene Index creation! Contact administrator. [1]', '['. $error .']'));
			
			toLog ($e->getMessage ());
			
			restore_error_handler ();
		}
		catch (PDOException $e)
		{
			$error = Instance::singleton ()->onDebugMode () ? $e->getMessage () : '';
			
			Message::singleton ()->addWarning (__ ('Error on automatic Lucene Index creation! Contact administrator. [1]', '['. $error .']'));
			
			toLog ($e->getMessage ());
			
			restore_error_handler ();
			
			return;
		}
		
		Message::singleton ()->save ();
	}
	
	static public function singleton ()
	{
		if (self::$lucene !== FALSE)
			return self::$lucene;
		
		$class = __CLASS__;
		
		self::$lucene = new $class ();
		
		return self::$lucene;
	}
	
	public function getPath ()
	{
		return $this->path;
	}
	
	public function getIndex ()
	{
		return self::$index;
	}
	
	public function isActive ()
	{
		return self::$index !== FALSE;
	}
	
	public function save ($url, $content, $indexTo = FALSE, $section = FALSE, $local = '')
	{
		if (!$this->isActive ())
			return FALSE;
		
		if (is_numeric ($url))
		{
			try
			{
				if ($section === FALSE)
					$oSection = Business::singleton ()->getSection (Section::TCURRENT);
				else
					$oSection = Business::singleton ()->getSection ($section);
				
				if ($indexTo === FALSE)
					$indexTo = Business::singleton ()->getAction (Action::TCURRENT)->getIndex ();
				
				if (trim ($indexTo) == '' || !$oSection->actionExists ($indexTo))
					return FALSE;
				
				$oAction = $oSection->getAction ($indexTo);
				
				$url = 'titan.php?target=body&toSection='. $oSection->getName () .'&toAction='. $oAction->getName () .'&itemId='. $url;
				
				if ($local == '')
					$local = getBreadPath ($oSection, FALSE, FALSE) . $oAction->getLabel ();
			}
			catch (Exception $e)
			{
				toLog ($e->getMessage ());
				
				return FALSE;
			}
		}
		
		try
		{
			set_time_limit (0);
			
			$index = $this->getIndex ();
			
			$term = new Zend_Search_Lucene_Index_Term ($url, 'url');
			
			$ids  = $index->termDocs ($term);
			
			foreach ($ids as $id)
				$index->delete ($id);
			
			$doc = new Zend_Search_Lucene_Document ();
		        
			$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
			
			$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::ITEM, 'iso-8859-1'));
			
			$doc->addField (Zend_Search_Lucene_Field::Text ('local', $local, 'iso-8859-1'));
			
			$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
			
			$index->addDocument ($doc);
			
			$index->commit ();
		}
		catch (Exception $e)
		{
			toLog (__ ('Impossible create index search for [[1]]: [2].', $url, $e->getMessage ()));
			
			return FALSE;
		}
		
		return TRUE;
	}
	
	public function delete ($url)
	{
		if (!$this->isActive ())
			return FALSE;
		
		if (is_numeric ($url))
		{
			try
			{
				$oSection = Business::singleton ()->getSection (Section::TCURRENT);
				
				$indexTo = Business::singleton ()->getAction (Action::TCURRENT)->getIndex ();
				
				if (trim ($indexTo) == '')
					return FALSE;
				
				$oAction = $oSection->getAction ($indexTo);
				
				$url = 'titan.php?target=body&toSection='. $oSection->getName () .'&toAction='. $oAction->getName () .'&itemId='. $url;
			}
			catch (Exception $e)
			{
				toLog ($e->getMessage ());
				
				return FALSE;
			}
		}
		
		try
		{
			$index = $this->getIndex ();
			
			$term = new Zend_Search_Lucene_Index_Term ($url, 'url');
				
			$ids  = $index->termDocs ($term);
			
			foreach ($ids as $id)
				$index->delete ($id);
			
			$index->commit ();
		}
		catch (Exception $e)
		{
			toLog (__ ('Impossible delete index search for [[1]]: [2].', $url, $e->getMessage ()));
			
			return FALSE;
		}
		catch (Zend_Search_Lucene_Search_QueryParserException $e)
		{
			toLog (__ ('Impossible delete index search for [[1]]: [2].', $url, $e->getMessage ()));
			
			return FALSE;
		}
		
		return TRUE;
	}
	
	public function saveFile ($ids, $indexAll = FALSE)
	{
		if (!$this->isActive ())
			return FALSE;
		
		if (!is_array ($ids))
			$ids = array ($ids);
		
		$sql = "SELECT _file.*, _user._name AS _user_name,
				to_char(_file._create_date, 'DD-MM-YYYY HH24:MI:SS') AS _date 
				FROM _file LEFT JOIN _user ON _user._id = _file._user";
		
		if ($indexAll !== TRUE)
			if (sizeof ($ids))
				$sql .= " WHERE _file._id IN ('". implode ("', '", $ids) ."')";
			else
				return TRUE;
		
		$db = Database::singleton ();
		
		$sth = $db->prepare ($sql);
		
		$sth->execute ();
		
		$flag = FALSE;
		
		while ($obj = $sth->fetch (PDO::FETCH_OBJ))
		{
			$doc = FALSE;
			
			try
			{
				switch (trim ($obj->_mimetype))
				{
					case 'application/pdf':
						$doc = self::pdfToIndex ($obj);
						break;
					
					case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
						$doc = self::docxToIndex ($obj);
						break;
					
					case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
						$doc = self::pptxToIndex ($obj);
						break;
					
					case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
						$doc = self::xlsxToIndex ($obj);
						break;
					
					case 'text/plain':
						$doc = self::txtToIndex ($obj);
						break;
					
					case 'application/msword':
						$doc = self::docToIndex ($obj);
						break;
					
					case 'text/html':
						$doc = self::htmlToIndex ($obj);
						break;
					
					default:
						continue;
				}
			}
			catch (Exception $e)
			{
				toLog ($e->getMessage ());
				
				continue;
			}
			
			if (!is_object ($doc))
				continue;
			
			self::$index->addDocument ($doc);
			
			$flag = TRUE;
		}
		
		if ($flag)
		{
			set_time_limit (0);
			
			self::$index->commit ();
			
			self::$index->optimize ();
		}
		
		return TRUE;
	}
	
	public function deleteFile ($fileIds)
	{
		if (!$this->isActive ())
			return FALSE;
		
		if (!is_array ($fileIds))
			$ids = array ($fileIds);
		
		try
		{
			$index = $this->getIndex ();
			
			foreach ($fileIds as $trash => $fileId)
			{
				$url = 'titan.php?target=openFile&fileId='. $fileId;
					
				$term = new Zend_Search_Lucene_Index_Term ($url, 'url');
					
				$ids  = $index->termDocs ($term);
				
				foreach ($ids as $id)
					$index->delete ($id);
			}
			
			$index->commit ();
			
			$index->optimize ();
		}
		catch (Exception $e)
		{
			toLog (__ ('Impossible delete index search for [[1]]: [2].', $url, $e->getMessage ()));
			
			return FALSE;
		}
		
		return TRUE;
	}
	
	static private function pdfToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$path = Instance::singleton ()->getCachePath () .'text/';
		
		if (!file_exists ($path) && !@mkdir ($path, 0777))
			throw new Exception (__ ('Impossible to create [[1]].', $path));
		
		if (!file_exists ($path . $file) || !(int) filesize ($path . $file))
			@system ('pdftotext -enc Latin1 -nopgbrk -q '. $original .' '. $path . $file .' > '. $path .'log', $trash);
		
		if (!file_exists ($path . $file) || !(int) filesize ($path . $file))
			throw new Exception  (__ ('Impossible to create [[1]].', $path . $file));
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". file_get_contents ($path . $file);
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		
		$doc = new Zend_Search_Lucene_Document ();
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
	
	static private function docxToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$doc = Zend_Search_Lucene_Document_Docx::loadDocxFile ($original, FALSE);
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". $doc->body;
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
	
	static private function pptxToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$doc = Zend_Search_Lucene_Document_Pptx::loadPptxFile ($original, FALSE);
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". $doc->body;
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
	
	static private function xlsxToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$doc = Zend_Search_Lucene_Document_Xlsx::loadXlsxFile ($original, FALSE);
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". $doc->body;
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
	
	static private function txtToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". file_get_contents ($original);
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		
		$doc = new Zend_Search_Lucene_Document ();
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
	
	static private function docToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$path = Instance::singleton ()->getCachePath () .'text/';
		
		if (!file_exists ($path) && !@mkdir ($path, 0777))
			throw new Exception (__ ('Impossible to create [[1]].', $path));
		
		if (!file_exists ($path . $file) || !(int) filesize ($path . $file))
			@system ('antiword '. $original .' 1> '. $path . $file .' 2> '. $path .'log', $trash);
		
		if (!file_exists ($path . $file) || !(int) filesize ($path . $file))
			throw new Exception  (__ ('Impossible to create [[1]].', $path . $file));
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". file_get_contents ($path . $file);
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		
		$doc = new Zend_Search_Lucene_Document ();
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
	
	static private function htmlToIndex ($obj)
	{
		$file = 'file_'. str_pad ($obj->_id, 7, '0', STR_PAD_LEFT);
		
		$original = File::getFilePath ($obj->_id);
		
		if (!file_exists ($original))
			$original = File::getLegacyFilePath ($obj->_id);
		
		if (!file_exists ($original))
			throw new Exception (__ ('File dont exists [[1]].', $original));
		
		$doc = Zend_Search_Lucene_Document_Html::loadHTMLFile ($original, FALSE);
		
		$content = $obj->_name ." \n\n". $obj->_date ." \n\n". $obj->_user_name ." \n\n". $doc->body;
		
		$url = 'titan.php?target=openFile&fileId='. $obj->_id;
		        
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('url', $url, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Keyword ('type', self::FILE, 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('local', __ ('File'), 'iso-8859-1'));
		
		$doc->addField (Zend_Search_Lucene_Field::Text ('content', $content, 'iso-8859-1'));
		
		return $doc;
	}
}
?>