Open Preprint Systems  3.3.0
ArticleSearch.inc.php
1 <?php
2 
18 import('lib.pkp.classes.search.SubmissionSearch');
19 
24  function getSparseArray($unorderedResults, $orderBy, $orderDir, $exclude) {
25  // Calculate a well-ordered (unique) score.
26  $resultCount = count($unorderedResults);
27  $i = 0;
28  foreach ($unorderedResults as $submissionId => &$data) {
29  // Reference is necessary to permit modification
30  $data['score'] = ($resultCount * $data['count']) + $i++;
31  }
32 
33  // If we got a primary sort order then apply it and use score as secondary
34  // order only.
35  // NB: We apply order after merging and before paging/formatting. Applying
36  // order before merging would require us to retrieve dependent objects for
37  // results being purged later. Doing everything in a closed SQL is not
38  // possible (e.g. for authors). Applying sort order after paging and
39  // formatting is not possible as we have to order the whole list before
40  // slicing it. So this seems to be the most appropriate place, although we
41  // may have to retrieve some objects again when formatting results.
42  $orderedResults = array();
43  $authorDao = DAORegistry::getDAO('AuthorDAO'); /* @var $authorDao AuthorDAO */
44  $submissionDao = DAORegistry::getDAO('SubmissionDAO'); /* @var $submissionDao SubmissionDAO */
45  $contextDao = Application::getContextDAO();
46  $contextTitles = array();
47  if ($orderBy == 'popularityAll' || $orderBy == 'popularityMonth') {
48  $application = Application::get();
49  $metricType = $application->getDefaultMetricType();
50  if (is_null($metricType)) {
51  // If no default metric has been found then sort by score...
52  $orderBy = 'score';
53  } else {
54  // Retrieve a metrics report for all submissions.
55  $column = STATISTICS_DIMENSION_SUBMISSION_ID;
56  $filter = array(
57  STATISTICS_DIMENSION_ASSOC_TYPE => array(ASSOC_TYPE_GALLEY, ASSOC_TYPE_SUBMISSION),
58  STATISTICS_DIMENSION_SUBMISSION_ID => array(array_keys($unorderedResults))
59  );
60  if ($orderBy == 'popularityMonth') {
61  $oneMonthAgo = date('Ymd', strtotime('-1 month'));
62  $today = date('Ymd');
63  $filter[STATISTICS_DIMENSION_DAY] = array('from' => $oneMonthAgo, 'to' => $today);
64  }
65  $rawReport = $application->getMetrics($metricType, $column, $filter);
66  foreach ($rawReport as $row) {
67  $unorderedResults[$row['submission_id']]['metric'] = (int)$row['metric'];
68  }
69  }
70  }
71 
72  $i=0; // Used to prevent ties from clobbering each other
73  foreach ($unorderedResults as $submissionId => $data) {
74  // Exclude unwanted IDs.
75  if (in_array($submissionId, $exclude)) continue;
76 
77  switch ($orderBy) {
78  case 'authors':
79  $submission = $submissionDao->getById($submissionId);
80  $orderKey = $submission->getAuthorString();
81  break;
82 
83  case 'title':
84  $submission = $submissionDao->getById($submissionId);
85  $orderKey = '';
86  if (!empty($submission->getCurrentPublication())) {
87  $orderKey = $submission->getCurrentPublication()->getLocalizedData('title');
88  }
89  break;
90 
91  case 'journalTitle':
92  if (!isset($contextTitles[$data['journal_id']])) {
93  $context = $contextDao->getById($data['journal_id']);
94  $contextTitles[$data['journal_id']] = $context->getLocalizedName();
95  }
96  $orderKey = $contextTitles[$data['journal_id']];
97  break;
98 
99  case 'publicationDate':
100  $orderKey = $data[$orderBy];
101  break;
102 
103  case 'popularityAll':
104  case 'popularityMonth':
105  $orderKey = (isset($data['metric']) ? $data['metric'] : 0);
106  break;
107 
108  default: // order by score.
109  $orderKey = $data['score'];
110  }
111  if (!isset($orderedResults[$orderKey])) {
112  $orderedResults[$orderKey] = array();
113  }
114  $orderedResults[$orderKey][$data['score'] + $i++] = $submissionId;
115  }
116 
117  // Order the results by primary order.
118  if (strtolower($orderDir) == 'asc') {
119  ksort($orderedResults);
120  } else {
121  krsort($orderedResults);
122  }
123 
124  // Order the result by secondary order and flatten it.
125  $finalOrder = array();
126  foreach($orderedResults as $orderKey => $submissionIds) {
127  if (count($submissionIds) == 1) {
128  $finalOrder[] = array_pop($submissionIds);
129  } else {
130  if (strtolower($orderDir) == 'asc') {
131  ksort($submissionIds);
132  } else {
133  krsort($submissionIds);
134  }
135  $finalOrder = array_merge($finalOrder, array_values($submissionIds));
136  }
137  }
138  return $finalOrder;
139  }
140 
146  function getSearchFilters($request) {
147  $searchFilters = array(
148  'query' => $request->getUserVar('query'),
149  'searchJournal' => $request->getUserVar('searchJournal'),
150  'abstract' => $request->getUserVar('abstract'),
151  'authors' => $request->getUserVar('authors'),
152  'title' => $request->getUserVar('title'),
153  'galleyFullText' => $request->getUserVar('galleyFullText'),
154  'discipline' => $request->getUserVar('discipline'),
155  'subject' => $request->getUserVar('subject'),
156  'type' => $request->getUserVar('type'),
157  'coverage' => $request->getUserVar('coverage'),
158  'indexTerms' => $request->getUserVar('indexTerms')
159  );
160 
161  // Is this a simplified query from the navigation
162  // block plugin?
163  $simpleQuery = $request->getUserVar('simpleQuery');
164  if (!empty($simpleQuery)) {
165  // In the case of a simplified query we get the
166  // filter type from a drop-down.
167  $searchType = $request->getUserVar('searchField');
168  if (array_key_exists($searchType, $searchFilters)) {
169  $searchFilters[$searchType] = $simpleQuery;
170  }
171  }
172 
173  // Publishing dates.
174  $fromDate = $request->getUserDateVar('dateFrom', 1, 1);
175  $searchFilters['fromDate'] = (is_null($fromDate) ? null : date('Y-m-d H:i:s', $fromDate));
176  $toDate = $request->getUserDateVar('dateTo', 32, 12, null, 23, 59, 59);
177  $searchFilters['toDate'] = (is_null($toDate) ? null : date('Y-m-d H:i:s', $toDate));
178 
179  // Instantiate the context.
180  $context = $request->getContext();
181  $siteSearch = !((boolean)$context);
182  if ($siteSearch) {
183  $contextDao = Application::getContextDAO();
184  if (!empty($searchFilters['searchJournal'])) {
185  $context = $contextDao->getById($searchFilters['searchJournal']);
186  } elseif (array_key_exists('journalTitle', $request->getUserVars())) {
187  $contexts = $contextDao->getAll(true);
188  while ($context = $contexts->next()) {
189  if (in_array(
190  $request->getUserVar('journalTitle'),
191  (array) $context->getTitle(null)
192  )) break;
193  }
194  }
195  }
196  $searchFilters['searchJournal'] = $context;
197  $searchFilters['siteSearch'] = $siteSearch;
198 
199  return $searchFilters;
200  }
201 
208  function getKeywordsFromSearchFilters($searchFilters) {
209  $indexFieldMap = $this->getIndexFieldMap();
210  $indexFieldMap[SUBMISSION_SEARCH_INDEX_TERMS] = 'indexTerms';
211  $keywords = array();
212  if (isset($searchFilters['query'])) {
213  $keywords[null] = $searchFilters['query'];
214  }
215  foreach($indexFieldMap as $bitmap => $searchField) {
216  if (isset($searchFilters[$searchField]) && !empty($searchFilters[$searchField])) {
217  $keywords[$bitmap] = $searchFilters[$searchField];
218  }
219  }
220  return $keywords;
221  }
222 
231  function formatResults($results, $user = null) {
232  $contextDao = Application::getContextDAO();
233  $sectionDao = DAORegistry::getDAO('SectionDAO'); /* @var $sectionDao SectionDAO */
234 
235  $publishedSubmissionCache = array();
236  $articleCache = array();
237  $contextCache = array();
238  $sectionCache = array();
239 
240  $returner = array();
241  foreach ($results as $articleId) {
242  // Get the article, storing in cache if necessary.
243  if (!isset($articleCache[$articleId])) {
244  $submission = Services::get('submission')->get($articleId);
245  $publishedSubmissionCache[$articleId] = $submission;
246  $articleCache[$articleId] = $submission;
247  }
248  $article = $articleCache[$articleId];
249  $publishedSubmission = $publishedSubmissionCache[$articleId];
250 
251  if ($publishedSubmission && $article) {
252  $sectionId = $article->getSectionId();
253  if (!isset($sectionCache[$sectionId])) {
254  $sectionCache[$sectionId] = $sectionDao->getById($sectionId);
255  }
256 
257  // Get the context, storing in cache if necessary.
258  $contextId = $article->getData('contextId');
259  if (!isset($contextCache[$contextId])) {
260  $contextCache[$contextId] = $contextDao->getById($contextId);
261  }
262 
263  // Store the retrieved objects in the result array.
264  $returner[] = array(
265  'article' => $article,
266  'publishedSubmission' => $publishedSubmissionCache[$articleId],
267  'journal' => $contextCache[$contextId],
268  'section' => $sectionCache[$sectionId]
269  );
270  }
271  }
272  return $returner;
273  }
274 
281  function getSimilarityTerms($submissionId) {
282  // Check whether a search plugin provides terms for a similarity search.
283  $searchTerms = array();
284  $result = HookRegistry::call('ArticleSearch::getSimilarityTerms', array($submissionId, &$searchTerms));
285 
286  // If no plugin implements the hook then use the subject keywords
287  // of the submission for a similarity search.
288  if ($result === false) {
289  // Retrieve the article.
290  $article = Services::get('submission')->get($submissionId);
291  if ($article->getData('status') === STATUS_PUBLISHED) {
292  // Retrieve keywords (if any).
293  $submissionSubjectDao = DAORegistry::getDAO('SubmissionKeywordDAO');
294  $allSearchTerms = array_filter($submissionSubjectDao->getKeywords($article->getId(), array(AppLocale::getLocale(), $article->getLocale(), AppLocale::getPrimaryLocale())));
295  foreach ($allSearchTerms as $locale => $localeSearchTerms) {
296  $searchTerms += $localeSearchTerms;
297  }
298  }
299  }
300 
301  return $searchTerms;
302  }
303 
304  function getIndexFieldMap() {
305  return array(
306  SUBMISSION_SEARCH_AUTHOR => 'authors',
307  SUBMISSION_SEARCH_TITLE => 'title',
308  SUBMISSION_SEARCH_ABSTRACT => 'abstract',
309  SUBMISSION_SEARCH_GALLEY_FILE => 'galleyFullText',
310  SUBMISSION_SEARCH_DISCIPLINE => 'discipline',
311  SUBMISSION_SEARCH_SUBJECT => 'subject',
312  SUBMISSION_SEARCH_TYPE => 'type',
313  SUBMISSION_SEARCH_COVERAGE => 'coverage'
314  );
315  }
316 
320  function getResultSetOrderingOptions($request) {
321  $resultSetOrderingOptions = array(
322  'score' => __('search.results.orderBy.relevance'),
323  'authors' => __('search.results.orderBy.author'),
324  'publicationDate' => __('search.results.orderBy.date'),
325  'title' => __('search.results.orderBy.article')
326  );
327 
328  // Only show the "popularity" options if we have a default metric.
329  $application = Application::get();
330  $metricType = $application->getDefaultMetricType();
331  if (!is_null($metricType)) {
332  $resultSetOrderingOptions['popularityAll'] = __('search.results.orderBy.popularityAll');
333  $resultSetOrderingOptions['popularityMonth'] = __('search.results.orderBy.popularityMonth');
334  }
335 
336  // Only show the "journal title" option if we have several journals.
337  $context = $request->getContext();
338  if (!$context) {
339  $resultSetOrderingOptions['journalTitle'] = __('search.results.orderBy.journal');
340  }
341 
342  // Let plugins mangle the search ordering options.
344  'SubmissionSearch::getResultSetOrderingOptions',
345  array($context, &$resultSetOrderingOptions)
346  );
347 
348  return $resultSetOrderingOptions;
349  }
350 
354  function getDefaultOrderDir($orderBy) {
355  $orderDir = 'asc';
356  if (in_array($orderBy, array('score', 'publicationDate', 'popularityAll', 'popularityMonth'))) {
357  $orderDir = 'desc';
358  }
359  return $orderDir;
360  }
361 
365  protected function getSearchDao() {
366  return DAORegistry::getDAO('ArticleSearchDAO');
367  }
368 }
369 
370 
ArticleSearch\formatResults
formatResults($results, $user=null)
Definition: ArticleSearch.inc.php:231
ArticleSearch\getKeywordsFromSearchFilters
getKeywordsFromSearchFilters($searchFilters)
Definition: ArticleSearch.inc.php:208
ArticleSearch\getDefaultOrderDir
getDefaultOrderDir($orderBy)
Definition: ArticleSearch.inc.php:354
Application\getContextDAO
static getContextDAO()
Definition: Application.inc.php:127
ArticleSearch\getSimilarityTerms
getSimilarityTerms($submissionId)
Definition: ArticleSearch.inc.php:281
SubmissionSearch
Class for retrieving search results.
Definition: SubmissionSearch.inc.php:35
DAORegistry\getDAO
static & getDAO($name, $dbconn=null)
Definition: DAORegistry.inc.php:57
AppLocale\getPrimaryLocale
static getPrimaryLocale()
Definition: env1/MockAppLocale.inc.php:95
ArticleSearch\getIndexFieldMap
getIndexFieldMap()
Definition: ArticleSearch.inc.php:304
ArticleSearch\getSearchDao
getSearchDao()
Definition: ArticleSearch.inc.php:365
ArticleSearch\getResultSetOrderingOptions
getResultSetOrderingOptions($request)
Definition: ArticleSearch.inc.php:320
ArticleSearch\getSearchFilters
getSearchFilters($request)
Definition: ArticleSearch.inc.php:146
ArticleSearch\getSparseArray
getSparseArray($unorderedResults, $orderBy, $orderDir, $exclude)
Definition: ArticleSearch.inc.php:24
PKPApplication\get
static get()
Definition: PKPApplication.inc.php:235
ArticleSearch
Class for retrieving article search results.
Definition: ArticleSearch.inc.php:20
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
AppLocale\getLocale
static getLocale()
Definition: env1/MockAppLocale.inc.php:40
PKPServices\get
static get($service)
Definition: PKPServices.inc.php:49