/** * @see templates/article/footer.tpl */ function callbackTemplateArticlePageFooter($hookName, $params) { $smarty =& $params[1]; $output =& $params[2]; // Identify similarity terms for the given article. $displayedArticle = $smarty->get_template_vars('article'); $articleId = $displayedArticle->getId(); import('classes.search.ArticleSearch'); $articleSearch = new ArticleSearch(); $searchTerms = $articleSearch->getSimilarityTerms($articleId); if (empty($searchTerms)) { return false; } // If we got similarity terms then execute a search with... // ... request, journal and error messages, ... $request = PKPApplication::getRequest(); $router = $request->getRouter(); $journal = $router->getContext($request); $error = null; // ... search keywords ... $query = implode(' ', $searchTerms); $keywords = array(null => $query); // ... and pagination. $rangeInfo = Handler::getRangeInfo($request, 'articlesBySimilarity'); $rangeInfo->setCount(RECOMMEND_BY_SIMILARITY_PLUGIN_COUNT); $results = $articleSearch->retrieveResults($request, $journal, $keywords, $error, null, null, $rangeInfo, array($articleId)); $smarty->assign('articlesBySimilarity', $results); $smarty->assign('articlesBySimilarityQuery', $query); $output .= $smarty->fetch($this->getTemplatePath() . 'articleFooter.tpl'); return false; }
function display(&$args, $request) { $templateMgr = TemplateManager::getManager($request); parent::display($args, $request); $issueDao = DAORegistry::getDAO('IssueDAO'); $publishedArticleDao = DAORegistry::getDAO('PublishedArticleDAO'); $articleGalleyDao = DAORegistry::getDAO('ArticleGalleyDAO'); $journal = $request->getJournal(); switch (array_shift($args)) { case 'exportGalley': $articleId = array_shift($args); $galleyId = array_shift($args); $article = $publishedArticleDao->getPublishedArticleByArticleId($articleId); $galley = $articleGalleyDao->getById($galleyId, $articleId); if ($article && $galley && ($issue = $issueDao->getById($article->getIssueId(), $journal->getId()))) { $this->exportArticle($journal, $issue, $article, $galley); break; } default: // Display a list of articles for export AppLocale::requireComponents(LOCALE_COMPONENT_PKP_SUBMISSION); $publishedArticleDao = DAORegistry::getDAO('PublishedArticleDAO'); $rangeInfo = Handler::getRangeInfo($this->getRequest(), $this->getRequest(), $this->getRequest(), $this->getRequest(), 'articles'); $articleIds = $publishedArticleDao->getPublishedArticleIdsAlphabetizedByJournal($journal->getId(), false); $totalArticles = count($articleIds); $articleIds = array_slice($articleIds, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); import('lib.pkp.classes.core.VirtualArrayIterator'); $articleSearch = new ArticleSearch(); $iterator = new VirtualArrayIterator($articleSearch->formatResults($articleIds), $totalArticles, $rangeInfo->getPage(), $rangeInfo->getCount()); $templateMgr->assign('articles', $iterator); $templateMgr->display($this->getTemplatePath() . 'index.tpl'); break; } }
function display(&$args) { $templateMgr =& TemplateManager::getManager(); parent::display($args); $issueDao =& DAORegistry::getDAO('IssueDAO'); $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); $articleGalleyDao =& DAORegistry::getDAO('ArticleGalleyDAO'); $journal =& Request::getJournal(); switch (array_shift($args)) { case 'exportGalley': $articleId = array_shift($args); $galleyId = array_shift($args); $article =& $publishedArticleDao->getPublishedArticleByArticleId($articleId); $galley =& $articleGalleyDao->getGalley($galleyId, $articleId); if ($article && $galley && ($issue =& $issueDao->getIssueById($article->getIssueId(), $journal->getJournalId()))) { $this->exportArticle($journal, $issue, $article, $galley); break; } default: // Display a list of articles for export $this->setBreadcrumbs(); $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); $rangeInfo = Handler::getRangeInfo('articles'); $articleIds = $publishedArticleDao->getPublishedArticleIdsAlphabetizedByJournal($journal->getJournalId(), false); $totalArticles = count($articleIds); $articleIds = array_slice($articleIds, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); import('core.VirtualArrayIterator'); $iterator =& new VirtualArrayIterator(ArticleSearch::formatResults($articleIds), $totalArticles, $rangeInfo->getPage(), $rangeInfo->getCount()); $templateMgr->assign_by_ref('articles', $iterator); $templateMgr->display($this->getTemplatePath() . 'index.tpl'); break; } }
function view() { // parse the search params $kind = get_http_var('type', ""); $q = get_http_var('q'); if (!$kind) { $j = get_http_var('j', ""); $a = get_http_var('a', ""); if ($j) { $q = $j; $kind = 'journo'; } if ($a) { $q = $a; $kind = 'article'; } } $art_page = get_http_var('p', 0); $journo_page = get_http_var('jp', 0); // special 'by' param for article searches $by = get_http_var('by', ""); if ($by && $kind != 'journo') { $q .= " author:" . $by; } $sort_order = get_http_var('o'); $article_results = null; if ($q != "" && $kind != 'journo') { $as = new ArticleSearch($q, $sort_order, $art_page, 'p'); $article_results = $as->perform(); } $journo_results = null; if ($q != "" && $kind != 'article') { $js = new JournoSearch($q, $journo_page, 'jp'); $journo_results = $js->perform(); } // hackhackhack /* if( $s['fmt'] == 'csv' ) { search_articles_output_csv($article_results->data); return; } */ tmpl($q, $kind, $sort_order, $journo_results, $article_results); }
/** * 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(); }
/** * Show advanced search results. * @param $args array * @param $request PKPRequest */ function advancedResults($args, &$request) { $this->validate(); $this->setupTemplate($request, true); $rangeInfo = $this->getRangeInfo('search'); $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); $searchJournalId = $request->getUserVar('searchJournal'); if (!empty($searchJournalId)) { $journalDao =& DAORegistry::getDAO('JournalDAO'); $journal =& $journalDao->getById($searchJournalId); $yearRange = $publishedArticleDao->getArticleYearRange($journal->getId()); } else { $journal =& $request->getJournal(); $yearRange = $publishedArticleDao->getArticleYearRange(null); } // Load the keywords array with submitted values $keywords = array(null => ArticleSearch::parseQuery($request->getUserVar('query'))); $keywords[ARTICLE_SEARCH_AUTHOR] = ArticleSearch::parseQuery($request->getUserVar('author')); $keywords[ARTICLE_SEARCH_TITLE] = ArticleSearch::parseQuery($request->getUserVar('title')); $keywords[ARTICLE_SEARCH_DISCIPLINE] = ArticleSearch::parseQuery($request->getUserVar('discipline')); $keywords[ARTICLE_SEARCH_SUBJECT] = ArticleSearch::parseQuery($request->getUserVar('subject')); $keywords[ARTICLE_SEARCH_TYPE] = ArticleSearch::parseQuery($request->getUserVar('type')); $keywords[ARTICLE_SEARCH_COVERAGE] = ArticleSearch::parseQuery($request->getUserVar('coverage')); $keywords[ARTICLE_SEARCH_GALLEY_FILE] = ArticleSearch::parseQuery($request->getUserVar('fullText')); $keywords[ARTICLE_SEARCH_SUPPLEMENTARY_FILE] = ArticleSearch::parseQuery($request->getUserVar('supplementaryFiles')); $fromDate = $request->getUserDateVar('dateFrom', 1, 1); if ($fromDate !== null) { $fromDate = date('Y-m-d H:i:s', $fromDate); } $toDate = $request->getUserDateVar('dateTo', 32, 12, null, 23, 59, 59); if ($toDate !== null) { $toDate = date('Y-m-d H:i:s', $toDate); } $results =& ArticleSearch::retrieveResults($journal, $keywords, $fromDate, $toDate, $rangeInfo); $templateMgr =& TemplateManager::getManager(); $templateMgr->assign_by_ref('results', $results); $this->_assignAdvancedSearchParameters($request, $templateMgr, $yearRange); $templateMgr->display('search/searchResults.tpl'); }
/** * Execute import/export tasks using the command-line interface. * @param $args Parameters to the plugin */ function executeCLI($scriptName, &$args) { // $command = array_shift($args); $xmlFile = array_shift($args); $journalPath = array_shift($args); $journalDao = DAORegistry::getDAO('JournalDAO'); $issueDao = DAORegistry::getDAO('IssueDAO'); $sectionDao = DAORegistry::getDAO('SectionDAO'); $userDao = DAORegistry::getDAO('UserDAO'); $publishedArticleDao = DAORegistry::getDAO('PublishedArticleDAO'); $journal = $journalDao->getByPath($journalPath); if (!$journal) { if ($journalPath != '') { echo __('plugins.importexport.pubmed.cliError') . "\n"; echo __('plugins.importexport.pubmed.error.unknownJournal', array('journalPath' => $journalPath)) . "\n\n"; } $this->usage($scriptName); return; } if ($xmlFile != '') { switch (array_shift($args)) { case 'articles': $articleSearch = new ArticleSearch(); $results = $articleSearch->formatResults($args); if (!$this->exportArticles($results, $xmlFile)) { echo __('plugins.importexport.pubmed.cliError') . "\n"; echo __('plugins.importexport.pubmed.export.error.couldNotWrite', array('fileName' => $xmlFile)) . "\n\n"; } return; case 'issue': $issueId = array_shift($args); $issue = $issueDao->getByBestId($issueId, $journal->getId()); if ($issue == null) { echo __('plugins.importexport.pubmed.cliError') . "\n"; echo __('plugins.importexport.pubmed.export.error.issueNotFound', array('issueId' => $issueId)) . "\n\n"; return; } $issues = array($issue); if (!$this->exportIssues($journal, $issues, $xmlFile)) { echo __('plugins.importexport.pubmed.cliError') . "\n"; echo __('plugins.importexport.pubmed.export.error.couldNotWrite', array('fileName' => $xmlFile)) . "\n\n"; } return; } } $this->usage($scriptName); }
/** * @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(); } } }
/** * Redirect to a search query that shows documents * similar to the one identified by an article id in the * request. * @param $args array * @param $request Request */ function similarDocuments($args, &$request) { $this->validate(null, $request); // Retrieve the (mandatory) ID of the article that // we want similar documents for. $articleId = $request->getUserVar('articleId'); if (!is_numeric($articleId)) { $request->redirect(null, 'search'); } // Check whether a search plugin provides terms for a similarity search. $articleSearch = new ArticleSearch(); $searchTerms = $articleSearch->getSimilarityTerms($articleId); // Redirect to a search query with the identified search terms (if any). if (empty($searchTerms)) { $searchParams = null; } else { $searchParams = array('query' => implode(' ', $searchTerms)); } $request->redirect(null, 'search', 'search', null, $searchParams); }
/** * Show index of published articles by title. * @param $args array * @param $request PKPRequest */ function titles($args, &$request) { $this->validate(); $this->setupTemplate($request, true); $journal =& $request->getJournal(); $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); $rangeInfo = $this->getRangeInfo('search'); $articleIds =& $publishedArticleDao->getPublishedArticleIdsAlphabetizedByJournal(isset($journal) ? $journal->getId() : null); $totalResults = count($articleIds); $articleIds = array_slice($articleIds, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); import('lib.pkp.classes.core.VirtualArrayIterator'); $results = new VirtualArrayIterator(ArticleSearch::formatResults($articleIds), $totalResults, $rangeInfo->getPage(), $rangeInfo->getCount()); $templateMgr =& TemplateManager::getManager(); $templateMgr->assign_by_ref('results', $results); $templateMgr->display('search/titleIndex.tpl'); }
/** * Show list of journal sections identify types. */ function identifyTypes($args = array(), $request) { $this->setupTemplate($request); $router = $request->getRouter(); $journal = $router->getContext($request); $browsePlugin =& PluginRegistry::getPlugin('generic', BROWSE_PLUGIN_NAME); $enableBrowseByIdentifyTypes = $browsePlugin->getSetting($journal->getId(), 'enableBrowseByIdentifyTypes'); if ($enableBrowseByIdentifyTypes) { if (isset($args[0]) && $args[0] == 'view') { $identifyType = $request->getUserVar('identifyType'); $sectionDao = DAORegistry::getDAO('SectionDAO'); $sectionsIterator = $sectionDao->getByJournalId($journal->getId()); $sections = array(); while ($section = $sectionsIterator->next()) { if ($section->getLocalizedIdentifyType() == $identifyType) { $sections[] = $section; } } $publishedArticleDao = DAORegistry::getDAO('PublishedArticleDAO'); $publishedArticleIds = array(); foreach ($sections as $section) { $publishedArticleIdsBySection = $publishedArticleDao->getPublishedArticleIdsBySection($section->getId()); $publishedArticleIds = array_merge($publishedArticleIds, $publishedArticleIdsBySection); } $rangeInfo = $this->getRangeInfo($request, 'search'); $totalResults = count($publishedArticleIds); $publishedArticleIds = array_slice($publishedArticleIds, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); $articleSearch = new ArticleSearch(); $results = new VirtualArrayIterator($articleSearch->formatResults($publishedArticleIds), $totalResults, $rangeInfo->getPage(), $rangeInfo->getCount()); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign('results', $results); $templateMgr->assign('title', $identifyType); $templateMgr->assign('enableBrowseByIdentifyTypes', $enableBrowseByIdentifyTypes); $templateMgr->display($browsePlugin->getTemplatePath() . 'searchDetails.tpl'); } else { $excludedIdentifyTypes = $browsePlugin->getSetting($journal->getId(), 'excludedIdentifyTypes'); $sectionDao = DAORegistry::getDAO('SectionDAO'); $sectionsIterator = $sectionDao->getByJournalId($journal->getId()); $sectionidentifyTypes = array(); while ($section = $sectionsIterator->next()) { if ($section->getLocalizedIdentifyType() && !in_array($section->getId(), $excludedIdentifyTypes) && !in_array($section->getLocalizedIdentifyType(), $sectionidentifyTypes)) { $sectionidentifyTypes[] = $section->getLocalizedIdentifyType(); } } sort($sectionidentifyTypes); $rangeInfo = $this->getRangeInfo($request, 'search'); $totalResults = count($sectionidentifyTypes); $sectionidentifyTypes = array_slice($sectionidentifyTypes, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); $results = new VirtualArrayIterator($sectionidentifyTypes, $totalResults, $rangeInfo->getPage(), $rangeInfo->getCount()); $templateMgr = TemplateManager::getManager($request); $templateMgr->assign('results', $results); $templateMgr->assign('enableBrowseByIdentifyTypes', $enableBrowseByIdentifyTypes); $templateMgr->display($browsePlugin->getTemplatePath() . 'searchIndex.tpl'); } } else { $request->redirect(null, 'index'); } }
/** * @covers ArticleSearch */ public function testRetrieveResultsViaPluginHook() { // Diverting a search to the search plugin hook. HookRegistry::register('SubmissionSearch::retrieveResults', array($this, 'callbackRetrieveResults')); $testCases = array(array(null => 'query'), array('1' => 'author'), array('2' => 'title'), array(null => 'query', 1 => 'author', 2 => 'title')); $testFromDate = date('Y-m-d H:i:s', strtotime('2011-03-15 00:00:00')); $testToDate = date('Y-m-d H:i:s', strtotime('2012-03-15 18:30:00')); $error = ''; foreach ($testCases as $testCase) { // Test a simple search with the simulated callback. $journal = new Journal(); $keywords = $testCase; $articleSearch = new ArticleSearch(); $searchResult = $articleSearch->retrieveResults($journal, $keywords, $error, $testFromDate, $testToDate); // Check the parameters passed into the callback. $expectedPage = 1; $expectedItemsPerPage = 20; $expectedTotalResults = 3; $expectedError = ''; $expectedParams = array($journal, $testCase, $testFromDate, $testToDate, $expectedPage, $expectedItemsPerPage, $expectedTotalResults, $expectedError); self::assertEquals($expectedParams, $this->_retrieveResultsParams); // Test and clear the call history of the hook registry. $calledHooks = HookRegistry::getCalledHooks(); self::assertEquals('SubmissionSearch::retrieveResults', $calledHooks[0][0]); HookRegistry::resetCalledHooks(true); // Test whether the result from the hook is being returned. self::assertInstanceOf('VirtualArrayIterator', $searchResult); // Test the total count. self::assertEquals(3, $searchResult->getCount()); // Test the search result. $firstResult = $searchResult->next(); self::assertArrayHasKey('article', $firstResult); self::assertEquals(SUBMISSION_SEARCH_TEST_ARTICLE_FROM_PLUGIN, $firstResult['article']->getId()); self::assertEquals('', $error); } // Remove the test hook. HookRegistry::clear('SubmissionSearch::retrieveResults'); }
/** * @see templates/article/footer.tpl */ function callbackTemplateArticlePageFooter($hookName, $params) { $smarty =& $params[1]; $output =& $params[2]; // Find articles of the same author(s). $displayedArticle = $smarty->get_template_vars('article'); $authors = $displayedArticle->getAuthors(); $authorDao = DAORegistry::getDAO('AuthorDAO'); /* @var $authorDao AuthorDAO */ $foundArticles = array(); foreach ($authors as $author) { /* @var $author Author */ // The following article search is by name only as authors are // not normalized in OJS. This is rather crude and may produce // false positives or miss some entries. But there's no other way // until OJS allows users to consistently normalize authors (via name, // email, ORCID, whatever). $articles = $authorDao->getPublishedArticlesForAuthor(null, $author->getFirstName(), $author->getMiddleName(), $author->getLastName(), $author->getLocalizedAffiliation(), $author->getCountry()); foreach ($articles as $article) { /* @var $article PublishedArticle */ if ($displayedArticle->getId() == $article->getId()) { continue; } $foundArticles[] = $article->getId(); } } $results = array_unique($foundArticles); // Order results by metric. $application = PKPApplication::getApplication(); $metricType = $application->getDefaultMetricType(); if (empty($metricType)) { $smarty->assign('noMetricSelected', true); } $column = STATISTICS_DIMENSION_ARTICLE_ID; $filter = array(STATISTICS_DIMENSION_ASSOC_TYPE => array(ASSOC_TYPE_GALLEY, ASSOC_TYPE_ARTICLE), STATISTICS_DIMENSION_ARTICLE_ID => array($results)); $orderBy = array(STATISTICS_METRIC => STATISTICS_ORDER_DESC); $statsReport = $application->getMetrics($metricType, $column, $filter, $orderBy); $orderedResults = array(); foreach ($statsReport as $reportRow) { $orderedResults[] = $reportRow['submission_id']; } // Make sure we even get results that have no statistics (yet) and that // we get them in some consistent order for paging. $remainingResults = array_diff($results, $orderedResults); sort($remainingResults); $orderedResults = array_merge($orderedResults, $remainingResults); // Pagination. $request = PKPApplication::getRequest(); $rangeInfo = Handler::getRangeInfo($request, 'articlesBySameAuthor'); if ($rangeInfo && $rangeInfo->isValid()) { $page = $rangeInfo->getPage(); } else { $page = 1; } $totalResults = count($orderedResults); $itemsPerPage = RECOMMEND_BY_AUTHOR_PLUGIN_COUNT; $offset = $itemsPerPage * ($page - 1); $length = max($totalResults - $offset, 0); $length = min($itemsPerPage, $length); if ($length == 0) { $pagedResults = array(); } else { $pagedResults = array_slice($orderedResults, $offset, $length); } // Visualization. import('classes.search.ArticleSearch'); $articleSearch = new ArticleSearch(); $pagedResults = $articleSearch->formatResults($pagedResults); import('lib.pkp.classes.core.VirtualArrayIterator'); $returner = new VirtualArrayIterator($pagedResults, $totalResults, $page, $itemsPerPage); $smarty->assign('articlesBySameAuthor', $returner); $output .= $smarty->fetch($this->getTemplatePath() . 'articleFooter.tpl'); return false; }
function display(&$args, $request) { $templateMgr =& TemplateManager::getManager(); parent::display($args, $request); $this->setBreadcrumbs(); $journal =& Request::getJournal(); $plugin =& $this->getSwordPlugin(); $swordUrl = Request::getUserVar('swordUrl'); $depositPointKey = Request::getUserVar('depositPoint'); $depositPoints = $plugin->getSetting($journal->getId(), 'depositPoints'); $username = Request::getUserVar('swordUsername'); $password = Request::getUserVar('swordPassword'); if (isset($depositPoints[$depositPointKey])) { $selectedDepositPoint = $depositPoints[$depositPointKey]; if ($selectedDepositPoint['username'] != '') { $username = $selectedDepositPoint['username']; } if ($selectedDepositPoint['password'] != '') { $password = $selectedDepositPoint['password']; } } $swordDepositPoint = Request::getUserVar('swordDepositPoint'); $depositEditorial = Request::getUserVar('depositEditorial'); $depositGalleys = Request::getUserVar('depositGalleys'); switch (array_shift($args)) { case 'deposit': $depositIds = array(); try { foreach (Request::getUserVar('articleId') as $articleId) { $depositIds[] = $this->deposit($swordDepositPoint, $username, $password, $articleId, $depositEditorial, $depositGalleys); } } catch (Exception $e) { // Deposit failed $templateMgr->assign(array('pageTitle' => 'plugins.importexport.sword.depositFailed', 'messageTranslated' => $e->getMessage(), 'backLink' => Request::url(null, null, null, array('plugin', $this->getName()), array('swordUrl' => $swordUrl, 'swordUsername' => $username, 'swordDepositPoint' => $swordDepositPoint, 'depositEditorial' => $depositEditorial, 'depositGalleys' => $depositGalleys)), 'backLinkLabel' => 'common.back')); return $templateMgr->display('common/message.tpl'); } // Deposit was successful $templateMgr->assign(array('pageTitle' => 'plugins.importexport.sword.depositSuccessful', 'message' => 'plugins.importexport.sword.depositSuccessfulDescription', 'backLink' => Request::url(null, null, null, array('plugin', $this->getName()), array('swordUrl' => $swordUrl, 'swordUsername' => $username, 'swordDepositPoint' => $swordDepositPoint, 'depositEditorial' => $depositEditorial, 'depositGalleys' => $depositGalleys)), 'backLinkLabel' => 'common.continue')); return $templateMgr->display('common/message.tpl'); break; default: $journal =& Request::getJournal(); $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); $rangeInfo = Handler::getRangeInfo('articles'); $articleIds = $publishedArticleDao->getPublishedArticleIdsAlphabetizedByJournal($journal->getId(), false); $totalArticles = count($articleIds); if ($rangeInfo->isValid()) { $articleIds = array_slice($articleIds, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); } import('lib.pkp.classes.core.VirtualArrayIterator'); $iterator = new VirtualArrayIterator(ArticleSearch::formatResults($articleIds), $totalArticles, $rangeInfo->getPage(), $rangeInfo->getCount()); foreach (array('swordUrl', 'swordUsername', 'swordPassword', 'depositEditorial', 'depositGalleys', 'swordDepositPoint') as $var) { $templateMgr->assign($var, Request::getUserVar($var)); } $templateMgr->assign('depositPoints', $depositPoints); if (!empty($swordUrl)) { $client = new SWORDAPPClient(); $doc = $client->servicedocument($swordUrl, $username, $password, ''); $depositPoints = array(); if (is_array($doc->sac_workspaces)) { foreach ($doc->sac_workspaces as $workspace) { if (is_array($workspace->sac_collections)) { foreach ($workspace->sac_collections as $collection) { $depositPoints["{$collection->sac_href}"] = "{$collection->sac_colltitle}"; } } } } $templateMgr->assign_by_ref('swordDepositPoints', $depositPoints); } $templateMgr->assign_by_ref('articles', $iterator); $templateMgr->display($this->getTemplatePath() . 'articles.tpl'); break; } }
/** * Return an array of search results matching the supplied * keyword IDs in decreasing order of match quality. * Keywords are supplied in an array of the following format: * $keywords[ARTICLE_SEARCH_AUTHOR] = array('John', 'Doe'); * $keywords[ARTICLE_SEARCH_...] = array(...); * $keywords[null] = array('Matches', 'All', 'Fields'); * @param $journal object The journal to search * @param $keywords array List of keywords * @param $error string a reference to a variable that will * contain an error message if the search service produces * an error. * @param $publishedFrom object Search-from date * @param $publishedTo object Search-to date * @param $rangeInfo Information on the range of results to return * @return VirtualArrayIterator An iterator with one entry per retrieved * article containing the article, published article, issue, journal, etc. */ function &retrieveResults(&$journal, &$keywords, &$error, $publishedFrom = null, $publishedTo = null, $rangeInfo = null) { // Pagination if ($rangeInfo && $rangeInfo->isValid()) { $page = $rangeInfo->getPage(); $itemsPerPage = $rangeInfo->getCount(); } else { $page = 1; $itemsPerPage = ARTICLE_SEARCH_DEFAULT_RESULT_LIMIT; } // Check whether a search plug-in jumps in to provide ranked search results. $totalResults = null; $results =& HookRegistry::call('ArticleSearch::retrieveResults', array(&$journal, &$keywords, $publishedFrom, $publishedTo, $page, $itemsPerPage, &$totalResults, &$error)); // If no search plug-in is activated then fall back to the // default database search implementation. if ($results === false) { // Parse the query. foreach ($keywords as $searchType => $query) { $keywords[$searchType] = ArticleSearch::_parseQuery($query); } // Fetch all the results from all the keywords into one array // (mergedResults), where mergedResults[article_id] // = sum of all the occurences for all keywords associated with // that article ID. $mergedResults =& ArticleSearch::_getMergedArray($journal, $keywords, $publishedFrom, $publishedTo); // Convert mergedResults into an array (frequencyIndicator => // $articleId). // The frequencyIndicator is a synthetically-generated number, // where higher is better, indicating the quality of the match. // It is generated here in such a manner that matches with // identical frequency do not collide. $results =& ArticleSearch::_getSparseArray($mergedResults); $totalResults = count($results); // Use only the results for the specified page. $offset = $itemsPerPage * ($page - 1); $length = max($totalResults - $offset, 0); $length = min($itemsPerPage, $length); if ($length == 0) { $results = array(); } else { $results = array_slice($results, $offset, $length); } } // Take the range of results and retrieve the Article, Journal, // and associated objects. $results =& ArticleSearch::formatResults($results); // Return the appropriate iterator. import('lib.pkp.classes.core.VirtualArrayIterator'); $returner = new VirtualArrayIterator($results, $totalResults, $page, $itemsPerPage); return $returner; }
/** * Execute import/export tasks using the command-line interface. * @param $args Parameters to the plugin */ function executeCLI($scriptName, &$args) { $command = array_shift($args); $xmlFile = array_shift($args); $journalPath = array_shift($args); AppLocale::requireComponents(LOCALE_COMPONENT_APPLICATION_COMMON); $journalDao =& DAORegistry::getDAO('JournalDAO'); $issueDao =& DAORegistry::getDAO('IssueDAO'); $sectionDao =& DAORegistry::getDAO('SectionDAO'); $userDao =& DAORegistry::getDAO('UserDAO'); $publishedArticleDao =& DAORegistry::getDAO('PublishedArticleDAO'); $journal =& $journalDao->getJournalByPath($journalPath); if (!$journal) { if ($journalPath != '') { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.error.unknownJournal', array('journalPath' => $journalPath)) . "\n\n"; } $this->usage($scriptName); return; } $this->import('NativeImportDom'); if ($xmlFile && NativeImportDom::isRelativePath($xmlFile)) { $xmlFile = PWD . '/' . $xmlFile; } switch ($command) { case 'import': $userName = array_shift($args); $user =& $userDao->getByUsername($userName); if (!$user) { if ($userName != '') { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.error.unknownUser', array('userName' => $userName)) . "\n\n"; } $this->usage($scriptName); return; } $doc =& $this->getDocument($xmlFile); $context = array('user' => $user, 'journal' => $journal); switch ($this->getRootNodeName($doc)) { case 'article': case 'articles': // Determine the extra context information required // for importing articles. if (array_shift($args) !== 'issue_id') { return $this->usage($scriptName); } $issue =& $issueDao->getIssueByBestIssueId($issueId = array_shift($args), $journal->getId()); if (!$issue) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.issueNotFound', array('issueId' => $issueId)) . "\n\n"; return; } $context['issue'] =& $issue; switch (array_shift($args)) { case 'section_id': $section =& $sectionDao->getSection($sectionIdentifier = array_shift($args)); break; case 'section_name': $section =& $sectionDao->getSectionByTitle($sectionIdentifier = array_shift($args), $journal->getId()); break; case 'section_abbrev': $section =& $sectionDao->getSectionByAbbrev($sectionIdentifier = array_shift($args), $journal->getId()); break; default: return $this->usage($scriptName); } if (!$section) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.sectionNotFound', array('sectionIdentifier' => $sectionIdentifier)) . "\n\n"; return; } $context['section'] =& $section; } $result = $this->handleImport($context, $doc, $errors, $issues, $articles, true); if ($result) { echo __('plugins.importexport.native.import.success.description') . "\n\n"; if (!empty($issues)) { echo __('issue.issues') . ":\n"; } foreach ($issues as $issue) { echo "\t" . $issue->getIssueIdentification() . "\n"; } if (!empty($articles)) { echo __('article.articles') . ":\n"; } foreach ($articles as $article) { echo "\t" . $article->getLocalizedTitle() . "\n"; } } else { $errorsTranslated = array(); foreach ($errors as $error) { $errorsTranslated[] = __($error[0], $error[1]); } echo __('plugins.importexport.native.cliError') . "\n"; foreach ($errorsTranslated as $errorTranslated) { echo "\t" . $errorTranslated . "\n"; } } return; break; case 'export': if ($xmlFile != '') { switch (array_shift($args)) { case 'article': $articleId = array_shift($args); $publishedArticle =& $publishedArticleDao->getPublishedArticleByBestArticleId($journal->getId(), $articleId); if ($publishedArticle == null) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.articleNotFound', array('articleId' => $articleId)) . "\n\n"; return; } $issue =& $issueDao->getIssueById($publishedArticle->getIssueId(), $journal->getId()); $sectionDao =& DAORegistry::getDAO('SectionDAO'); $section =& $sectionDao->getSection($publishedArticle->getSectionId()); if (!$this->exportArticle($journal, $issue, $section, $publishedArticle, $xmlFile)) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.couldNotWrite', array('fileName' => $xmlFile)) . "\n\n"; } return; case 'articles': $results =& ArticleSearch::formatResults($args); if (!$this->exportArticles($results, $xmlFile)) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.couldNotWrite', array('fileName' => $xmlFile)) . "\n\n"; } return; case 'issue': $issueId = array_shift($args); $issue =& $issueDao->getIssueByBestIssueId($issueId, $journal->getId()); if ($issue == null) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.issueNotFound', array('issueId' => $issueId)) . "\n\n"; return; } if (!$this->exportIssue($journal, $issue, $xmlFile)) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.couldNotWrite', array('fileName' => $xmlFile)) . "\n\n"; } return; case 'issues': $issues = array(); while (($issueId = array_shift($args)) !== null) { $issue =& $issueDao->getIssueByBestIssueId($issueId, $journal->getId()); if ($issue == null) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.issueNotFound', array('issueId' => $issueId)) . "\n\n"; return; } $issues[] =& $issue; } if (!$this->exportIssues($journal, $issues, $xmlFile)) { echo __('plugins.importexport.native.cliError') . "\n"; echo __('plugins.importexport.native.export.error.couldNotWrite', array('fileName' => $xmlFile)) . "\n\n"; } return; } } break; } $this->usage($scriptName); }
/** * Configure the search request from a keywords * array as required by ArticleSearch::retrieveResults() * * @param $keywords array See ArticleSearch::retrieveResults() */ function addQueryFromKeywords($keywords) { // Get a mapping of OJS search fields bitmaps to index fields. $indexFieldMap = ArticleSearch::getIndexFieldMap(); // The keywords list is indexed with a search field bitmap. foreach ($keywords as $searchFieldBitmap => $searchPhrase) { // Translate the search field from OJS to solr nomenclature. if (empty($searchFieldBitmap)) { // An empty search field means "all fields". $solrFields = array_values($indexFieldMap); } else { $solrFields = array(); foreach ($indexFieldMap as $ojsField => $solrField) { // The search field bitmap may stand for // several actual index fields (e.g. the index terms // field). if ($searchFieldBitmap & $ojsField) { $solrFields[] = $solrField; } } } $solrFieldString = implode('|', $solrFields); $this->addQueryFieldPhrase($solrFieldString, $searchPhrase); } }
/** * Return an array of search results matching the supplied * keyword IDs in decreasing order of match quality. * Keywords are supplied in an array of the following format: * $keywords[ARTICLE_SEARCH_AUTHOR] = array('John', 'Doe'); * $keywords[ARTICLE_SEARCH_...] = array(...); * $keywords[null] = array('Matches', 'All', 'Fields'); * @param $journal object The journal to search * @param $keywords array List of keywords * @param $publishedFrom object Search-from date * @param $publishedTo object Search-to date * @param $rangeInfo Information on the range of results to return */ function &retrieveResults(&$journal, &$keywords, $publishedFrom = null, $publishedTo = null, $rangeInfo = null) { // Fetch all the results from all the keywords into one array // (mergedResults), where mergedResults[article_id] // = sum of all the occurences for all keywords associated with // that article ID. // resultCount contains the sum of result counts for all keywords. $mergedResults =& ArticleSearch::_getMergedArray($journal, $keywords, $publishedFrom, $publishedTo, $resultCount); // Convert mergedResults into an array (frequencyIndicator => // $articleId). // The frequencyIndicator is a synthetically-generated number, // where higher is better, indicating the quality of the match. // It is generated here in such a manner that matches with // identical frequency do not collide. $results =& ArticleSearch::_getSparseArray($mergedResults, $resultCount); $totalResults = count($results); // Use only the results for the specified page, if specified. if ($rangeInfo && $rangeInfo->isValid()) { $results = array_slice($results, $rangeInfo->getCount() * ($rangeInfo->getPage() - 1), $rangeInfo->getCount()); $page = $rangeInfo->getPage(); $itemsPerPage = $rangeInfo->getCount(); } else { $page = 1; $itemsPerPage = max($totalResults, 1); } // Take the range of results and retrieve the Article, Journal, // and associated objects. $results =& ArticleSearch::formatResults($results); // Return the appropriate iterator. $returner =& new VirtualArrayIterator($results, $totalResults, $page, $itemsPerPage); return $returner; }
/** * Retrieve auto-suggestions from the faceting service. * @param $url string * @param $searchRequest SolrSearchRequest * @param $userInput string * @param $fieldName string * @return array The generated suggestions. */ function _getFacetingAutosuggestions($url, $searchRequest, $userInput, $fieldName) { // Remove special characters from the user input. $searchTerms = strtr($userInput, '"()+-|&!', ' '); // Cut off the last search term. $searchTerms = explode(' ', $searchTerms); $facetPrefix = array_pop($searchTerms); if (empty($facetPrefix)) { return array(); } // Use the remaining search query to pre-filter // facet results. This may be an invalid query // but edismax will deal gracefully with syntax // errors. $userInput = String::substr($userInput, 0, -String::strlen($facetPrefix)); switch ($fieldName) { case 'query': // The 'query' filter goes agains all fields. $articleSearch = new ArticleSearch(); $solrFields = array_values($articleSearch->getIndexFieldMap()); break; case 'indexTerms': // The 'index terms' filter goes against keyword index fields. $solrFields = array('discipline', 'subject', 'type', 'coverage'); break; default: // All other filters can be used directly. $solrFields = array($fieldName); } $solrFieldString = implode('|', $solrFields); $searchRequest->addQueryFieldPhrase($solrFieldString, $userInput); // Construct the main query. $params = $this->_getSearchQueryParameters($searchRequest); if (!isset($params['q'])) { // Use a catch-all query in case we have no limiting // search. $params['q'] = '*:*'; } if ($fieldName == 'query') { $params['facet.field'] = 'default_spell'; } else { $params['facet.field'] = $fieldName . '_spell'; } $facetPrefixLc = String::strtolower($facetPrefix); $params['facet.prefix'] = $facetPrefixLc; // Make the request. $response = $this->_makeRequest($url, $params); if (!is_a($response, 'DOMXPath')) { return array(); } // Extract term suggestions. $nodeList = $response->query('//lst[@name="facet_fields"]/lst/int/@name'); if ($nodeList->length == 0) { return array(); } $termSuggestions = array(); foreach ($nodeList as $childNode) { $termSuggestions[] = $childNode->value; } // Add the term suggestion to the remaining user input. $suggestions = array(); foreach ($termSuggestions as $termSuggestion) { // Restore case if possible. if (strpos($termSuggestion, $facetPrefixLc) === 0) { $termSuggestion = $facetPrefix . String::substr($termSuggestion, String::strlen($facetPrefix)); } $suggestions[] = $userInput . $termSuggestion; } return $suggestions; }