<?php

/**
 * Rebuilds the search indexes for the documentation pages. 
 *
 * For the hourly cron rebuild use RebuildLuceneDocusIndex_Hourly 
 *
 * @package docsviewer
 * @subpackage tasks
 */

class RebuildLuceneDocsIndex extends BuildTask {
	
	protected $title = "Rebuild Documentation Search Indexes";
	
	protected $description = "
		Rebuilds the indexes used for the search engine in the docsviewer.";
	
	public function run($request) {
		$this->rebuildIndexes();
	}
	
	public function rebuildIndexes($quiet = false) {
		require_once 'Zend/Search/Lucene.php';

		ini_set("memory_limit", -1);
		ini_set('max_execution_time', 0);

		Filesystem::makeFolder(DocumentationSearch::get_index_location());
	
		// only rebuild the index if we have to. Check for either flush or the time write.lock.file
		// was last altered
		$lock = DocumentationSearch::get_index_location() .'/write.lock.file';
		$lockFileFresh = (file_exists($lock) && filemtime($lock) > (time() - (60 * 60 * 24)));

		echo "Building index in ". DocumentationSearch::get_index_location() . PHP_EOL;

		if($lockFileFresh && !isset($_REQUEST['flush'])) { 
			if(!$quiet) {
				echo "Index recently rebuilt. If you want to force reindex use ?flush=1";
			}
			
			return true;
		}

		try {
			$index = Zend_Search_Lucene::open(DocumentationSearch::get_index_location());
			$index->removeReference();
		}
		catch (Zend_Search_Lucene_Exception $e) {
			// user_error($e);
		}

		try {
			$index = Zend_Search_Lucene::create(DocumentationSearch::get_index_location());
		}
		catch(Zend_Search_Lucene_Exception $c) {
			user_error($c);
		}

		// includes registration
		$manifest = new DocumentationManifest(true);
		$pages = $manifest->getPages();
		
		if($pages) {
			$count = 0;
			
			// iconv complains about all the markdown formatting
			// turn off notices while we parse
			
			if(!Director::is_cli()) {
				echo "<ul>";
			}
			foreach($pages as $url => $record) {
				$count++;
				$page = $manifest->getPage($url);

				$doc = new Zend_Search_Lucene_Document();
				$error = error_reporting();
				error_reporting(E_ALL ^ E_NOTICE);
				$content = $page->getHTML();
				error_reporting($error);

				$doc->addField(Zend_Search_Lucene_Field::Text('content', $content));
				$doc->addField($titleField = Zend_Search_Lucene_Field::Text('Title', $page->getTitle()));
				$doc->addField($breadcrumbField = Zend_Search_Lucene_Field::Text('BreadcrumbTitle', $page->getBreadcrumbTitle()));

				$doc->addField(Zend_Search_Lucene_Field::Keyword(
					'Version', $page->getEntity()->getVersion()
				));

				$doc->addField(Zend_Search_Lucene_Field::Keyword(
					'Language', $page->getEntity()->getLanguage()
				));

				$doc->addField(Zend_Search_Lucene_Field::Keyword(
					'Entity', $page->getEntity()
				));

				$doc->addField(Zend_Search_Lucene_Field::Keyword(
					'Link', $page->Link()
				));
	
				// custom boosts
				$titleField->boost = 3;
				$breadcrumbField->boost = 1.5;

				$boost = Config::inst()->get('DocumentationSearch', 'boost_by_path');

				foreach($boost as $pathExpr => $boost) {
					if(preg_match($pathExpr, $page->getRelativePath())) {
						$doc->boost = $boost;
					}
				}
				$index->addDocument($doc);
				if(!$quiet) {
					if(Director::is_cli()) echo " * adding ". $page->getPath() ."\n";
					else echo "<li>adding ". $page->getPath() ."</li>\n";
				}
			}
		}

		$index->commit();
		
		if(!$quiet) {
			echo "complete.";
		}
	}
}