/** * @covers LucenePlugin * @covers SolrSearchRequest */ public function testCallbackRetrieveResults() { // Test data. $testCases = array(array(null => 'test AND query'), array(SUBMISSION_SEARCH_AUTHOR => 'author'), array(SUBMISSION_SEARCH_TITLE => 'title'), array(SUBMISSION_SEARCH_ABSTRACT => 'abstract'), array(SUBMISSION_SEARCH_INDEX_TERMS => 'Nicht index terms'), array(SUBMISSION_SEARCH_GALLEY_FILE => 'full OR text'), array(null => 'test query', SUBMISSION_SEARCH_AUTHOR => 'author', SUBMISSION_SEARCH_TITLE => 'title', SUBMISSION_SEARCH_DISCIPLINE => 'discipline', SUBMISSION_SEARCH_SUBJECT => 'subject', SUBMISSION_SEARCH_TYPE => 'type', SUBMISSION_SEARCH_COVERAGE => 'coverage', SUBMISSION_SEARCH_GALLEY_FILE => 'full text')); $expectedResults = array(array('authors|title|abstract|galleyFullText|discipline|subject|type|coverage' => 'test AND query'), array('authors' => 'author'), array('title' => 'title'), array('abstract' => 'abstract'), array('discipline|subject|type|coverage' => 'Nicht index terms'), array('galleyFullText' => 'full OR text'), array('authors|title|abstract|galleyFullText|discipline|subject|type|coverage' => 'test query', 'authors' => 'author', 'title' => 'title', 'discipline' => 'discipline', 'subject' => 'subject', 'type' => 'type', 'coverage' => 'coverage', 'galleyFullText' => 'full text')); $journal = new Journal(); $fromDate = '2000-01-01 00:00:00'; $hook = 'SubmissionSearch::retrieveResults'; $totalResults = null; $error = null; $facetCategories = array('discipline', 'subject', 'type', 'coverage', 'authors'); foreach ($testCases as $testNum => $testCase) { // Build the expected search request. $searchRequest = new SolrSearchRequest(); $searchRequest->setJournal($journal); $searchRequest->setFromDate($fromDate); $searchRequest->setQuery($expectedResults[$testNum]); $searchRequest->setSpellcheck(true); $searchRequest->setHighlighting(true); // Facets should only be requested for categories that have no // active filter. $expectedFacetCategories = array_values(array_diff($facetCategories, array_keys($expectedResults[$testNum]))); $searchRequest->setFacetCategories($expectedFacetCategories); // Mock a SolrWebService. $webService = $this->getMock('SolrWebService', array('retrieveResults'), array(), '', false); // Check whether the Lucene plug-in calls the web service // with the right parameters. $webService->expects($this->once())->method('retrieveResults')->with($this->equalTo($searchRequest), $this->equalTo($totalResults)); $this->lucenePlugin->_solrWebService = $webService; unset($webService, $searchRequest); // Execute the test. $params = array($journal, $testCase, $fromDate, null, 1, 25, &$totalResults, &$error); $this->lucenePlugin->callbackRetrieveResults($hook, $params); } // Test an error condition. $webService = $this->getMock('SolrWebService', array('retrieveResults', 'getServiceMessage'), array(), '', false); $webService->expects($this->once())->method('retrieveResults')->will($this->returnValue(null)); $webService->expects($this->any())->method('getServiceMessage')->will($this->returnValue('some error message')); $originalWebService = $this->lucenePlugin->_solrWebService; $this->lucenePlugin->_solrWebService = $webService; $params = array($journal, array(null => 'test'), null, null, 1, 25, &$totalResults, &$error); $this->assertEquals(array(), $this->lucenePlugin->callbackRetrieveResults($hook, $params)); $this->assertEquals('some error message ##plugins.generic.lucene.message.techAdminInformed##', $error); $this->lucenePlugin->_solrWebService = $originalWebService; }
/** * AJAX request for search query auto-completion. * @param $args array * @param $request Request * @return JSON string */ function queryAutocomplete($args, $request) { $this->validate(null, $request); // Check whether auto-suggest is enabled. $suggestionList = array(); $lucenePlugin = $this->_getLucenePlugin(); $enabled = (bool) $lucenePlugin->getSetting(0, 'autosuggest'); if ($enabled) { // Retrieve search criteria from the user input. $articleSearch = new ArticleSearch(); $searchFilters = $articleSearch->getSearchFilters($request); // Get the autosuggest input and remove it from // the filter array. $autosuggestField = $request->getUserVar('searchField'); $userInput = $searchFilters[$autosuggestField]; if (isset($searchFilters[$autosuggestField])) { unset($searchFilters[$autosuggestField]); } // Instantiate a search request. $searchRequest = new SolrSearchRequest(); $searchRequest->setJournal($searchFilters['searchJournal']); $searchRequest->setFromDate($searchFilters['fromDate']); $searchRequest->setToDate($searchFilters['toDate']); $keywords = $articleSearch->getKeywordsFromSearchFilters($searchFilters); $searchRequest->addQueryFromKeywords($keywords); // Get the web service. $solrWebService = $lucenePlugin->getSolrWebService(); /* @var $solrWebService SolrWebService */ $suggestions = $solrWebService->getAutosuggestions($searchRequest, $autosuggestField, $userInput, (int) $lucenePlugin->getSetting(0, 'autosuggestType')); // Prepare a suggestion list as understood by the // autocomplete JS handler. foreach ($suggestions as $suggestion) { $suggestionList[] = array('label' => $suggestion, 'value' => $suggestion); } } // Return the suggestions as JSON message. $json = new JSONMessage(true, $suggestionList); return $json->getString(); }
/** * @see ArticleSearch::retrieveResults() */ function callbackRetrieveResults($hookName, $params) { assert($hookName == 'ArticleSearch::retrieveResults'); // Unpack the parameters. list($journal, $keywords, $fromDate, $toDate, $page, $itemsPerPage, $dummy) = $params; $totalResults =& $params[6]; // need to use reference $error =& $params[7]; // need to use reference // Instantiate a search request. $searchRequest = new SolrSearchRequest(); $searchRequest->setJournal($journal); $searchRequest->setFromDate($fromDate); $searchRequest->setToDate($toDate); $searchRequest->setPage($page); $searchRequest->setItemsPerPage($itemsPerPage); $searchRequest->addQueryFromKeywords($keywords); // Get the ordering criteria. list($orderBy, $orderDir) = $this->_getResultSetOrdering($journal); $searchRequest->setOrderBy($orderBy); $searchRequest->setOrderDir($orderDir == 'asc' ? true : false); // Configure alternative spelling suggestions. $spellcheck = (bool) $this->getSetting(0, 'spellcheck'); $searchRequest->setSpellcheck($spellcheck); // Configure highlighting. $highlighting = (bool) $this->getSetting(0, 'highlighting'); $searchRequest->setHighlighting($highlighting); // Configure faceting. // 1) Faceting will be disabled for filtered search categories. $activeFilters = array_keys($searchRequest->getQuery()); if (is_a($journal, 'Journal')) { $activeFilters[] = 'journalTitle'; } if (!empty($fromDate) || !empty($toDate)) { $activeFilters[] = 'publicationDate'; } // 2) Switch faceting on for enabled categories that have no // active filters. $facetCategories = array_values(array_diff($this->_getEnabledFacetCategories(), $activeFilters)); $searchRequest->setFacetCategories($facetCategories); // Configure custom ranking. $customRanking = (bool) $this->getSetting(0, 'customRanking'); if ($customRanking) { $sectionDao =& DAORegistry::getDAO('SectionDAO'); /* @var $sectionDao SectionDAO */ if (is_a($journal, 'Journal')) { $sections = $sectionDao->getJournalSections($journal->getId()); } else { $sections = $sectionDao->getSections(); } while (!$sections->eof()) { /* @var $sections DAOResultFactory */ $section =& $sections->next(); $rankingBoost = $section->getData('rankingBoost'); if (isset($rankingBoost)) { $sectionBoost = (double) $rankingBoost; } else { $sectionBoost = LUCENE_PLUGIN_DEFAULT_RANKING_BOOST; } if ($sectionBoost != LUCENE_PLUGIN_DEFAULT_RANKING_BOOST) { $searchRequest->addBoostFactor('section_id', $section->getId(), $sectionBoost); } unset($section); } unset($sections); } // Call the solr web service. $solrWebService =& $this->getSolrWebService(); $result =& $solrWebService->retrieveResults($searchRequest, $totalResults); if (is_null($result)) { $error = $solrWebService->getServiceMessage(); $this->_informTechAdmin($error, $journal, true); $error .= ' ' . __('plugins.generic.lucene.message.techAdminInformed'); return array(); } else { // Store spelling suggestion, highlighting and faceting info // internally. We cannot route these back through the request // as the default search implementation does not support // these features. if ($spellcheck && isset($result['spellingSuggestion'])) { $this->_spellingSuggestion = $result['spellingSuggestion']; // Identify the field for which we got the suggestion. foreach ($keywords as $bitmap => $searchPhrase) { if (!empty($searchPhrase)) { switch ($bitmap) { case null: $queryField = 'query'; break; case ARTICLE_SEARCH_INDEX_TERMS: $queryField = 'indexTerms'; break; default: $indexFieldMap = ArticleSearch::getIndexFieldMap(); assert(isset($indexFieldMap[$bitmap])); $queryField = $indexFieldMap[$bitmap]; } } } $this->_spellingSuggestionField = $queryField; } if ($highlighting && isset($result['highlightedArticles'])) { $this->_highlightedArticles = $result['highlightedArticles']; } if (!empty($facetCategories) && isset($result['facets'])) { $this->_facets = $result['facets']; } // Return the scored results. if (isset($result['scoredResults']) && !empty($result['scoredResults'])) { return $result['scoredResults']; } else { return array(); } } }
/** * @covers SolrWebService::retrieveResults() * * NB: Depends on correct journal indexing * and must therefore be run after testIndexJournal(). * We run journal indexing as the last test and * this test as the first test as journal indexing * is asynchronous. This means that a prior test * run must be successful for this test to pass. */ public function testRetrieveResults() { $embeddedServer = new EmbeddedServer(); $this->_startServer($embeddedServer); // Make sure that the journal is properly indexed. $this->_indexTestJournals(); // Make a search on specific fields. $searchRequest = new SolrSearchRequest(); $journal = new Journal(); $journal->setId(2); $searchRequest->setJournal($journal); $searchRequest->setQuery(array('suppFiles' => 'pizza', 'authors' => 'Author', 'galleyFullText' => 'Nutella', 'title' => 'Article')); $searchRequest->setFromDate(date('Y-m-d\\TH:i:s\\Z', strtotime('2000-01-01'))); $searchRequest->setHighlighting(true); $totalResults = null; $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); // Check search results. self::assertTrue(is_int($totalResults), $totalResults > 0); self::assertTrue(isset($results['scoredResults'])); $scoredResults = $results['scoredResults']; self::assertTrue(is_array($scoredResults)); self::assertTrue(!empty($scoredResults)); self::assertTrue(in_array('3', $scoredResults)); // Check highlighting results. self::assertTrue(isset($results['highlightedArticles'])); $highlightedArticles = $results['highlightedArticles']; self::assertTrue(is_array($highlightedArticles)); self::assertTrue(!empty($highlightedArticles)); self::assertTrue(isset($highlightedArticles['3'])); self::assertContains('Lucene Test <em>Article</em> 1 Abstract', $highlightedArticles['3']); $searchRequest->setHighlighting(false); // Test result set ordering via simple (default field) search. $searchRequest->setQuery(array('title' => 'lucene')); $searchRequest->setOrderBy('authors'); $searchRequest->setOrderDir('asc'); $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); $scoredResults = isset($results['scoredResults']) ? $results['scoredResults'] : null; self::assertEquals(array(4, 3), array_values($scoredResults)); $searchRequest->setOrderBy('title'); $searchRequest->setOrderDir('desc'); $searchRequest->setFacetCategories(array('discipline', 'subject', 'coverage', 'journalTitle', 'authors', 'publicationDate')); $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); $scoredResults = isset($results['scoredResults']) ? $results['scoredResults'] : null; self::assertEquals(array(3, 4), array_values($scoredResults)); // Check faceting results. self::assertTrue(isset($results['facets'])); $facets = $results['facets']; self::assertTrue(is_array($facets)); $expectedFacets = array('discipline' => array('exotic food' => 1, 'dietary research' => 1), 'subject' => array('lunchtime no lunch' => 1), 'coverage' => array('daily probes' => 1, 'the 21st century' => 1, 'world wide' => 1), 'journalTitle' => array(), 'authors' => array('author, some' => 1, 'authorname, second a' => 1, 'author, another' => 1), 'publicationDate' => array('2011' => 1, '2012' => 1)); self::assertEquals($expectedFacets, $facets); $searchRequest->setFacetCategories(array()); // Test translation of search terms. // If the word "und" is not correctly translated to "AND" then // the search should return results due to our "implicit OR" strategy. // We confirm that by confirming that the two words without the keyword // will return something. $searchRequest->setQuery(array('galleyFullText' => 'nutella und quatsch')); $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); self::assertTrue(empty($results['scoredResults'])); $searchRequest->setQuery(array('galleyFullText' => 'nutella quatsch')); $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); self::assertFalse(empty($results['scoredResults'])); // Test spelling suggestions. $searchRequest->setQuery(array('galleyFullText' => 'Nutela')); $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); self::assertTrue(empty($results['spellingSuggestion'])); $searchRequest->setSpellcheck(true); $results = $this->solrWebService->retrieveResults($searchRequest, $totalResults); self::assertFalse(empty($results['spellingSuggestion'])); self::assertEquals('nutella', $results['spellingSuggestion']); }