my changes
This commit is contained in:
parent
28301e4312
commit
8dc1f1b048
263 changed files with 36882 additions and 4453 deletions
313
app/Library/Search/SearchResult.php
Normal file
313
app/Library/Search/SearchResult.php
Normal file
|
@ -0,0 +1,313 @@
|
|||
<?php
|
||||
namespace App\Library\Search;
|
||||
|
||||
/**
|
||||
* Implements API for describing successful response to search query.
|
||||
*/
|
||||
|
||||
use App\Library\Util\SearchResultMatch;
|
||||
|
||||
class SearchResult
|
||||
{
|
||||
protected $data = array(
|
||||
'matches' => null,
|
||||
'count' => null,
|
||||
'querytime' => null,
|
||||
'facets' => null,
|
||||
);
|
||||
protected $validated = false;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SearchResult
|
||||
*/
|
||||
public static function create()
|
||||
{
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns matches returned in response to search query.
|
||||
*
|
||||
* @param mixed $documentId ID of document considered match of related search query
|
||||
* @return SearchResultMatch
|
||||
*/
|
||||
public function addMatch($documentId)
|
||||
{
|
||||
if (!is_array($this->data['matches'])) {
|
||||
$this->data['matches'] = array();
|
||||
}
|
||||
$match = SearchResultMatch::create($documentId);
|
||||
$this->data['matches'][] = $match;
|
||||
|
||||
return $match;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets number of all matching documents.
|
||||
*
|
||||
* @note This may include documents not listed as matches here due to using
|
||||
* paging parameters on query.
|
||||
*
|
||||
* @param int $allMatchesCount number of all matching documents
|
||||
* @return $this fluent interface
|
||||
*/
|
||||
public function setAllMatchesCount($allMatchesCount)
|
||||
{
|
||||
if (!is_null($this->data['count'])) {
|
||||
throw new RuntimeException('must not set count of all matches multiple times');
|
||||
}
|
||||
|
||||
if (!ctype_digit(trim($allMatchesCount))) {
|
||||
throw new InvalidArgumentException('invalid number of overall matches');
|
||||
}
|
||||
$this->data['count'] = intval($allMatchesCount);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets information on time taken for querying search engine.
|
||||
*
|
||||
* @param string $time
|
||||
* @return $this fluent interface
|
||||
*/
|
||||
public function setQueryTime($time)
|
||||
{
|
||||
if (!is_null($this->data['querytime'])) {
|
||||
throw new RuntimeException('must not set query time multiple times');
|
||||
}
|
||||
if (!is_null($time)) {
|
||||
$this->data['querytime'] = trim($time);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds another result of faceted search to current result set.
|
||||
*
|
||||
* @param string $facetField name of field result of faceted search is related to
|
||||
* @param string $text description on particular faceted result on field (e.g. single value in field)
|
||||
* @param int $count number of occurrences of facet on field in all matches
|
||||
* @return $this fluent interface
|
||||
*
|
||||
* TODO special year_inverted facet handling should be moved to separate class
|
||||
*/
|
||||
public function addFacet($facetField, $text, $count)
|
||||
{
|
||||
$facetField = strval($facetField);
|
||||
|
||||
// remove inverted sorting prefix from year values
|
||||
if ($facetField === 'year_inverted') {
|
||||
$text = explode(':', $text, 2)[1];
|
||||
|
||||
// treat 'year_inverted' as if it was 'year'
|
||||
$facetField = 'year';
|
||||
}
|
||||
|
||||
// treat 'year_inverted' as if it was 'year'
|
||||
if ($facetField === 'year_inverted') {
|
||||
$facetField = 'year';
|
||||
}
|
||||
|
||||
if (!is_array($this->data['facets'])) {
|
||||
$this->data['facets'] = array();
|
||||
}
|
||||
|
||||
if (!array_key_exists($facetField, $this->data['facets'])) {
|
||||
$this->data['facets'][$facetField] = array();
|
||||
}
|
||||
|
||||
$this->data['facets'][$facetField][] = new Opus_Search_Result_Facet($text, $count);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves results of faceted search.
|
||||
*
|
||||
* @return Opus_Search_Result_Facet[][] map of fields' names into sets of facet result per field
|
||||
*/
|
||||
public function getFacets()
|
||||
{
|
||||
return is_null($this->data['facets']) ? array() : $this->data['facets'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves set of facet results on single field selected by name.
|
||||
*
|
||||
* @param string $fieldName name of field returned facet result is related to
|
||||
* @return Opus_Search_Result_Facet[] set of facet results on selected field
|
||||
*/
|
||||
public function getFacet($fieldName)
|
||||
{
|
||||
if ($this->data['facets'] && array_key_exists($fieldName, $this->data['facets'])) {
|
||||
return $this->data['facets'][$fieldName];
|
||||
}
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves set of matching and locally existing documents returned in
|
||||
* response to some search query.
|
||||
*
|
||||
* @return Opus_Search_Result_Match[]
|
||||
*/
|
||||
public function getReturnedMatches()
|
||||
{
|
||||
if (is_null($this->data['matches'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// map AND FILTER set of returned matches ensuring to list related
|
||||
// documents existing locally, only
|
||||
$matches = array();
|
||||
|
||||
foreach ($this->data['matches'] as $match) {
|
||||
try {
|
||||
/** @var SearchResultMatch $match */
|
||||
// $match->getDocument();
|
||||
$matches[] = $match;
|
||||
} catch (Opus_Document_Exception $e) {
|
||||
Opus_Log::get()->warn('skipping matching but locally missing document #' . $match->getId());
|
||||
}
|
||||
}
|
||||
return $matches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves set of matching documents' IDs returned in response to some
|
||||
* search query.
|
||||
*
|
||||
* @note If query was requesting to retrieve non-qualified matches this set
|
||||
* might include IDs of documents that doesn't exist locally anymore.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function getReturnedMatchingIds()
|
||||
{
|
||||
if (is_null($this->data['matches'])) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return array_map(function ($match) {
|
||||
/** @var SearchResultMatch $match */
|
||||
return $match->getId();
|
||||
}, $this->data['matches']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves set of matching documents.
|
||||
*
|
||||
* @note This is provided for downward compatibility, though it's signature
|
||||
* has changed in that it's returning set of Opus_Document instances
|
||||
* rather than set of Opus_SolrSearch_Result instances.
|
||||
*
|
||||
* @note The wording is less specific in that all information in response to
|
||||
* search query may considered results of search. Thus this new API
|
||||
* prefers "matches" over "results".
|
||||
*
|
||||
* @deprecated
|
||||
* @return Opus_Document[]
|
||||
*/
|
||||
public function getResults()
|
||||
{
|
||||
return $this->getReturnedMatches();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all returned matches referring to Opus documents missing in local
|
||||
* database.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function dropLocallyMissingMatches()
|
||||
{
|
||||
if (!$this->validated) {
|
||||
$finder = new Opus_DocumentFinder();
|
||||
|
||||
$returnedIds = $this->getReturnedMatchingIds();
|
||||
$existingIds = $finder
|
||||
->setServerState('published')
|
||||
->setIdSubset($returnedIds)
|
||||
->ids();
|
||||
|
||||
if (count($returnedIds) !== count($existingIds)) {
|
||||
Opus_Log::get()->err(sprintf(
|
||||
"inconsistency between db and search index: index returns %d documents, but only %d found in db",
|
||||
count($returnedIds),
|
||||
count($existingIds)
|
||||
));
|
||||
|
||||
// update set of returned matches internally
|
||||
$this->data['matches'] = array();
|
||||
foreach ($existingIds as $id) {
|
||||
$this->addMatch($id);
|
||||
}
|
||||
// set mark to prevent validating matches again
|
||||
$this->validated = true;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves overall number of matches.
|
||||
*
|
||||
* @note This number includes matches not included in fetched subset of
|
||||
* matches.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getAllMatchesCount()
|
||||
{
|
||||
if (is_null($this->data['count'])) {
|
||||
throw new RuntimeException('count of matches have not been provided yet');
|
||||
}
|
||||
return $this->data['count'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves overall number of matches.
|
||||
*
|
||||
* @note This is provided for downward compatibility.
|
||||
*
|
||||
* @deprecated
|
||||
* @return int
|
||||
*/
|
||||
public function getNumberOfHits()
|
||||
{
|
||||
return $this->getAllMatchesCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves information on search query's processing time.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getQueryTime()
|
||||
{
|
||||
return $this->data['querytime'];
|
||||
}
|
||||
|
||||
public function __get($name)
|
||||
{
|
||||
switch (strtolower(trim($name))) {
|
||||
case 'matches':
|
||||
return $this->getReturnedMatches();
|
||||
|
||||
case 'allmatchescount':
|
||||
return $this->getAllMatchesCount();
|
||||
|
||||
case 'querytime':
|
||||
return $this->getQueryTime();
|
||||
default:
|
||||
throw new RuntimeException('invalid request for property ' . $name);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue