function &getSparseArray(&$unorderedResults, $orderBy, $orderDir, $exclude)
{
// Calculate a well-ordered (unique) score.
$resultCount = count($unorderedResults);
$i = 0;
foreach ($unorderedResults as $submissionId => &$data) {
$data['score'] = $resultCount * $data['count'] + $i++;
unset($data);
}
// If we got a primary sort order then apply it and use score as secondary
// order only.
// NB: We apply order after merging and before paging/formatting. Applying
// order before merging (i.e. in ArticleSearchDAO) would require us to
// retrieve dependent objects for results being purged later. Doing
// everything in a closed SQL is not possible (e.g. for authors). Applying
// sort order after paging and formatting is not possible as we have to
// order the whole list before slicing it. So this seems to be the most
// appropriate place, although we may have to retrieve some objects again
// when formatting results.
$orderedResults = array();
$authorDao = DAORegistry::getDAO('AuthorDAO');
/* @var $authorDao AuthorDAO */
$articleDao = DAORegistry::getDAO('ArticleDAO');
/* @var $articleDao ArticleDAO */
$journalDao = DAORegistry::getDAO('JournalDAO');
/* @var $journalDao JournalDAO */
$journalTitles = array();
if ($orderBy == 'popularityAll' || $orderBy == 'popularityMonth') {
$application = PKPApplication::getApplication();
$metricType = $application->getDefaultMetricType();
if (is_null($metricType)) {
// If no default metric has been found then sort by score...
$orderBy = 'score';
} else {
// Retrieve a metrics report for all articles.
$column = STATISTICS_DIMENSION_ARTICLE_ID;
$filter = array(STATISTICS_DIMENSION_ASSOC_TYPE => array(ASSOC_TYPE_GALLEY, ASSOC_TYPE_ARTICLE), STATISTICS_DIMENSION_ARTICLE_ID => array(array_keys($unorderedResults)));
if ($orderBy == 'popularityMonth') {
$oneMonthAgo = date('Ymd', strtotime('-1 month'));
$today = date('Ymd');
$filter[STATISTICS_DIMENSION_DAY] = array('from' => $oneMonthAgo, 'to' => $today);
}
$rawReport = $application->getMetrics($metricType, $column, $filter);
foreach ($rawReport as $row) {
$unorderedResults[$row['submission_id']]['metric'] = (int) $row['metric'];
}
}
}
$i = 0;
// Used to prevent ties from clobbering each other
foreach ($unorderedResults as $submissionId => $data) {
// Exclude unwanted IDs.
if (in_array($submissionId, $exclude)) {
continue;
}
switch ($orderBy) {
case 'authors':
$authors = $authorDao->getBySubmissionId($submissionId);
$authorNames = array();
foreach ($authors as $author) {
/* @var $author Author */
$authorNames[] = $author->getFullName(true);
}
$orderKey = implode('; ', $authorNames);
unset($authors, $authorNames);
break;
case 'title':
$submission = $articleDao->getById($submissionId);
$orderKey = $submission->getLocalizedTitle(null, false);
break;
case 'journalTitle':
if (!isset($journalTitles[$data['journal_id']])) {
$journal = $journalDao->getById($data['journal_id']);
$journalTitles[$data['journal_id']] = $journal->getLocalizedName();
}
$orderKey = $journalTitles[$data['journal_id']];
break;
case 'issuePublicationDate':
case 'publicationDate':
$orderKey = $data[$orderBy];
break;
case 'popularityAll':
case 'popularityMonth':
$orderKey = isset($data['metric']) ? $data['metric'] : 0;
break;
default:
// order by score.
$orderKey = $data['score'];
}
if (!isset($orderedResults[$orderKey])) {
$orderedResults[$orderKey] = array();
}
$orderedResults[$orderKey][$data['score'] + $i++] = $submissionId;
}
// Order the results by primary order.
if (strtolower($orderDir) == 'asc') {
ksort($orderedResults);
} else {
krsort($orderedResults);
}
// Order the result by secondary order and flatten it.
$finalOrder = array();
foreach ($orderedResults as $orderKey => $submissionIds) {
if (count($submissionIds) == 1) {
$finalOrder[] = array_pop($submissionIds);
} else {
if (strtolower($orderDir) == 'asc') {
ksort($submissionIds);
} else {
krsort($submissionIds);
}
$finalOrder = array_merge($finalOrder, array_values($submissionIds));
}
}
return $finalOrder;
}