diff --git a/_config.php b/_config.php index 5f69c51..5703ac6 100755 --- a/_config.php +++ b/_config.php @@ -7,7 +7,17 @@ * For more information and documentation see sapphiredocs/docs/en */ -// default location for documentation +// default location for documentation. If you want this under a custom url +// define your own rule in your mysite/_config.php Director::addRules(100, array( 'dev/docs' => 'DocumentationViewer' -)); \ No newline at end of file +)); + +// the default meta data for the OpenSearch library. More descriptive values +// can be set in your mysite file +DocumentationSearch::set_meta_data(array( + 'ShortName' => _t('DocumentationViewer.OPENSEARCHNAME', 'Documentation Search'), + 'Description' => _t('DocumentationViewer.OPENSEARCHDESC', 'Search the documentation'), + 'Contact' => Email::getAdminEmail(), + 'Tags' => _t('DocumentationViewer.OPENSEARCHTAGS', 'Documentation') +)); diff --git a/code/DocumentationSearch.php b/code/DocumentationSearch.php index e626d4e..8cd20ca 100644 --- a/code/DocumentationSearch.php +++ b/code/DocumentationSearch.php @@ -3,19 +3,82 @@ /** * Documentation Search powered by Lucene. You will need Zend_Lucene installed on your path * to rebuild the indexes run the {@link RebuildLuceneDocsIndex} task. You may wish to setup - * a cron job to remake the indexes on a regular basis + * a cron job to remake the indexes on a regular basis. + * + * It has the ability to generate an OpenSearch RSS formatted feeds simply by using the URL + * + * + * yoursite.com/search/?q=Foo&format=rss. // Format can either be specified as rss or left off. + * + * + * To get a specific amount of results you can also use the modifiers start and limit + * + * + * yoursite.com/search/?q=Foo&start=10&limit=10 + * * * @package sapphiredocs */ -class DocumentationSearch { - +class DocumentationSearch extends Controller { + + /** + * @var bool - Is search enabled + */ private static $enabled = false; + /** + * @var string - OpenSearch metadata. Please use {@link DocumentationSearch::set_meta_data()} + */ + private static $meta_data; + + /** + * @var DataObjectSet - Results + */ private $results; + /** + * @var int + */ private $totalResults; + /** + * @var string + */ + private $query; + + /** + * @var Controller + */ + private $outputController; + + /** + * Set the current search query + * + * @param string + */ + public function setQuery($query) { + $this->query = $query; + } + + /** + * Returns the current search query + * + * @return string + */ + public function getQuery() { + return $this->query; + } + + /** + * Sets the {@link DocumentationViewer} or {@link DocumentationSearch} instance which this search is rendering + * on based on whether it is the results display or RSS feed + * + * @param Controller + */ + public function setOutputController($controller) { + $this->outputController = $controller; + } /** * Folder name for indexes (in the temp folder). You can override it using @@ -26,7 +89,8 @@ class DocumentationSearch { private static $index_location = 'sapphiredocs'; static $allowed_actions = array( - 'buildindex' + 'buildindex', + 'opensearch' ); /** @@ -96,29 +160,28 @@ class DocumentationSearch { /** * Perform a search query on the index - * - * Rebuilds the index if it out of date */ - public function performSearch($query) { + public function performSearch() { try { $index = Zend_Search_Lucene::open(self::get_index_location()); Zend_Search_Lucene::setResultSetLimit(200); - $this->results = $index->find($query); + $this->results = $index->find($this->getQuery()); $this->totalResults = $index->numDocs(); } catch(Zend_Search_Lucene_Exception $e) { - // the reindexing task has not been run user_error('DocumentationSearch::performSearch() could not perform search as index does not exist. Please run /dev/tasks/RebuildLuceneDocsIndex', E_USER_ERROR); } } /** - * @return DataObjectSet + * @return ArrayData */ - public function getDataArrayFromHits($request) { + public function getSearchResults($request) { + $pageLength = (isset($_GET['length'])) ? (int) $_GET['length'] : 10; + $data = array( 'Results' => null, 'Query' => null, @@ -127,6 +190,7 @@ class DocumentationSearch { 'TotalPages' => null, 'ThisPage' => null, 'StartResult' => null, + 'PageLength' => $pageLength, 'EndResult' => null, 'PrevUrl' => DBField::create('Text', 'false'), 'NextUrl' => DBField::create('Text', 'false'), @@ -136,7 +200,7 @@ class DocumentationSearch { $start = ($request->requestVar('start')) ? (int)$request->requestVar('start') : 0; $query = ($request->requestVar('Search')) ? $request->requestVar('Search') : ''; - $pageLength = 10; + $currentPage = floor( $start / $pageLength ) + 1; $totalPages = ceil(count($this->results) / $pageLength ); @@ -204,10 +268,12 @@ class DocumentationSearch { } } - return $data; + return new ArrayData($data); } /** + * Build a nice query string for the results + * * @return string */ private function buildQueryUrl($params) { @@ -232,9 +298,79 @@ class DocumentationSearch { return (int) $this->totalResults; } + /** + * Optimizes the search indexes on the File System + * + * @return void + */ public function optimizeIndex() { $index = Zend_Search_Lucene::open(self::get_index_location()); if($index) $index->optimize(); } + + public function getTitle() { + return ($this->outputController) ? $this->outputController->Title : ""; + } + + /** + * OpenSearch MetaData. Includes 'description', 'tags', 'contact' + * + * @param array + */ + public static function set_meta_data($data) { + if(is_array($data)) { + foreach($data as $key => $value) { + self::$meta_data[strtolower($key)] = $value; + } + } + } + + /** + * Returns the meta data needed by opensearch. + * + * @return array + */ + public static function get_meta_data() { + $data = self::$meta_data; + + return array( + 'Description' => (isset($data['description'])) ? $data['description'] : "", + 'Tags' => (isset($data['tags'])) ? $data['tags'] : "", + 'Contact' => (isset($data['contact'])) ? $data['contact'] : "", + 'ShortName' => (isset($data['shortname'])) ? $data['shortname'] : "" + ); + } + + public function renderResults() { + if(!$this->results) $this->performSearch(); + if(!$this->outputController) $this->outputController = $this; + + $request = $this->outputController->getRequest(); + + $data = $this->getSearchResults($request); + $templates = array('DocumentationViewer_results', 'DocumentationViewer'); + + if($request->requestVar('format') && $request->requestVar('format') == "rss") { + // alter the fields for the opensearch xml. + $title = ($title = $this->getTitle()) ? ' | '. $title : ""; + + $data->setField('Title', $data->Title . $title); + + $data->setField('DescriptionURL', 'DocumentationSearch/opensearch/'); + + array_unshift($templates, 'OpenSearchResults'); + } + + return $this->outputController->customise($data)->renderWith($templates); + } + + /** + * Returns the opensearch description of the search results + */ + public function opensearch() { + $data = self::get_meta_data(); + + return $this->customise(new ArrayData($data))->renderWith(array('OpenSearchDescription')); + } } \ No newline at end of file diff --git a/code/DocumentationViewer.php b/code/DocumentationViewer.php index 3440018..3c0a6d3 100755 --- a/code/DocumentationViewer.php +++ b/code/DocumentationViewer.php @@ -709,12 +709,11 @@ class DocumentationViewer extends Controller { /** * Past straight to results, display and encode the query */ - function results($data, $form, $request) { + function results($data, $form, $request) { $search = new DocumentationSearch(); - $search->performSearch($form->dataFieldByName('Search')->dataValue()); + $search->setQuery($form->dataFieldByName('Search')->dataValue()); + $search->setOutputController($this); - $data = $search->getDataArrayFromHits($request); - - return $this->customise($data)->renderWith(array('DocumentationViewer_results', 'DocumentationViewer')); + return $search->renderResults(); } } \ No newline at end of file diff --git a/lang/_manifest_exclude b/lang/_manifest_exclude new file mode 100755 index 0000000..e69de29 diff --git a/lang/en_US.php b/lang/en_US.php new file mode 100755 index 0000000..78bd287 --- /dev/null +++ b/lang/en_US.php @@ -0,0 +1,10 @@ + \ No newline at end of file diff --git a/templates/OpenSearchDescription.ss b/templates/OpenSearchDescription.ss new file mode 100644 index 0000000..de8a8b4 --- /dev/null +++ b/templates/OpenSearchDescription.ss @@ -0,0 +1,10 @@ + + + + $ShortName + $Description + $Tags + $Content + + + \ No newline at end of file diff --git a/templates/OpenSearchResults.ss b/templates/OpenSearchResults.ss new file mode 100644 index 0000000..507f8ce --- /dev/null +++ b/templates/OpenSearchResults.ss @@ -0,0 +1,23 @@ + + + + $Title + $Link + + $TotalResults + $StartResult + $PageLength + + + \ No newline at end of file