/** * Takes the search term and extracts a normal name from it * * @return string */ protected function getAuthor() { $search = $this->searchObject->getParams()->getSearchTerms(); if (isset($search[0]['lookfor'])) { $author = $search[0]['lookfor']; // remove quotes $author = str_replace('"', '', $author); // remove dates $author = preg_replace('/[0-9]+-[0-9]*/', '', $author); // if name is rearranged by commas $author = trim($author, ', .'); $nameParts = explode(', ', $author); $last = $nameParts[0]; // - move all names up an index, move last name to last // - Last, First M. -> First M. Last for ($i = 1; $i < count($nameParts); $i++) { $nameParts[$i - 1] = $nameParts[$i]; } $nameParts[count($nameParts) - 1] = $last; $author = implode($nameParts, ' '); // remove punctuation return $author; } return ''; }
/** * This method returns an array of strings matching the user's query for * display in the autocomplete box. * * @param string $query The user query * * @return array The suggestions for the provided query */ public function getSuggestions($query) { if (!is_object($this->searchObject)) { throw new \Exception('Please set configuration first.'); } try { $this->searchObject->getParams()->setBasicSearch($this->mungeQuery($query), $this->handler); $this->searchObject->getParams()->setSort($this->sortField); foreach ($this->filters as $current) { $this->searchObject->getParams()->addFilter($current); } // Perform the search: $searchResults = $this->searchObject->getResults(); // Build the recommendation list -- first we'll try with exact matches; // if we don't get anything at all, we'll try again with a less strict // set of rules. $results = $this->getSuggestionsFromSearch($searchResults, $query, true); if (empty($results)) { $results = $this->getSuggestionsFromSearch($searchResults, $query, false); } } catch (\Exception $e) { // Ignore errors -- just return empty results if we must. } return isset($results) ? array_unique($results) : []; }
/** * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { $this->results = $results; // We can't currently deal with advanced searches: if ($this->results->getParams()->getSearchType() == 'advanced') { return; } // Get the query to manipulate: $query = $this->results->getParams()->getDisplayQuery(); // If the query is of a type that should be skipped, go no further: if ($this->queryShouldBeSkipped($query)) { return; } // Perform all checks (based on naming convention): $methods = get_class_methods($this); foreach ($methods as $method) { if (substr($method, 0, 5) == 'check') { $currentCheck = strtolower(substr($method, 5)); if (!in_array($currentCheck, $this->skipChecks)) { if ($result = $this->{$method}($query)) { $this->suggestions['switchquery_' . $currentCheck] = $result; } } } } }
/** * Get identities related to the query. * * @return array */ public function getIdentities() { // Extract the first search term from the search object: $search = $this->searchObject->getParams()->getQuery(); $lookfor = $search instanceof Query ? $search->getString() : ''; // Get terminology information: return $this->worldCatUtils->getRelatedIdentities($lookfor); }
/** * Internal utility function for initializing * UrlQueryHelper for a Results-object with search ids for all tabs. * * @param ResultsManager $results Search results. * @param ServiceManager $sm Service manager. * * @return Results Search results with initialized UrlQueryHelper */ public static function initUrlQueryHelper(\VuFind\Search\Base\Results $results, $sm) { $helper = new UrlQueryHelper($results->getParams()); $savedSearches = $sm->getServiceLocator()->get('Request')->getQuery('search'); if ($savedSearches) { $helper->setDefaultParameter('search', $savedSearches); } $results->setHelper('urlQuery', $helper); return $results; }
/** * Initialize this result set scroller. This should only be called * prior to displaying the results of a new search. * * @param \VuFind\Search\Base\Results $searchObject The search object that was * used to execute the last search. * * @return bool */ public function init($searchObject) { // Do nothing if disabled: if (!$this->enabled) { return; } // Save the details of this search in the session $this->data->searchId = $searchObject->getSearchId(); $this->data->page = $searchObject->getParams()->getPage(); $this->data->limit = $searchObject->getParams()->getLimit(); $this->data->total = $searchObject->getResultTotal(); // save the IDs of records on the current page to the session // so we can "slide" from one record to the next/previous records // spanning 2 consecutive pages $this->data->currIds = $this->fetchPage($searchObject); // clear the previous/next page unset($this->data->prevIds); unset($this->data->nextIds); return true; }
/** * Takes the search term and extracts a normal name from it * * @return string */ protected function getAuthor() { $search = $this->searchObject->getParams()->getQuery(); if ($search instanceof Query) { $author = $search->getString(); // remove quotes $author = str_replace('"', '', $author); return $this->useViaf ? $this->normalizeNameWithViaf($author) : $this->normalizeName($author); } return ''; }
/** * Turns facet information into an alphabetical list. * * @param \VuFind\Search\Base\Results $results Search result object * @param string $field Facet field to sort * @param array $list Facet value list extract from * the search result object's getFacetList method * @param array $searchRoute Route to use to generate * search URLs for individual facet values * * @return array Associative URL => description array sorted by description */ public function __invoke($results, $field, $list, $searchRoute) { $facets = []; // avoid limit on URL $results->getParams()->setLimit($results->getOptions()->getDefaultLimit()); $urlHelper = $this->getView()->plugin('url'); foreach ($list as $value) { $url = $urlHelper($searchRoute) . $results->getUrlQuery()->addFacet($field, $value['value']); $facets[$url] = $value['displayText']; } natcasesort($facets); return $facets; }
/** * Return the count of records when checkbox filter is activated. * * @param array $checkboxFilter Checkbox filter * @param \VuFind\Search\Base\Results $results Search result set * * @return int Record count */ public function __invoke($checkboxFilter, $results) { $ret = 0; list($field, $value) = $results->getParams()->parseFilter($checkboxFilter['filter']); $facets = $results->getFacetList([$field => $value]); if (isset($facets[$field])) { foreach ($facets[$field]['list'] as $item) { if ($item['value'] == $value || substr($value, -1) == '*' && preg_match('/^' . $value . '/', $item['value']) || $item['value'] == 'true' && $value == '1' || $item['value'] == 'false' && $value == '0') { $ret += $item['count']; } } } return $ret; }
/** * Get input parameters for API call. * * @return array */ protected function getApiInput() { // Extract the first search term from the search object: $search = $this->searchObject->getParams()->getQuery(); $filters = $this->searchObject->getParams()->getFilters(); $lookfor = $search instanceof \VuFindSearch\Query\Query ? $search->getString() : ''; $params = ['q' => $lookfor, 'fields' => implode(',', $this->returnFields), 'api_key' => $this->apiKey]; foreach ($filters as $field => $filter) { if (isset($this->formatMap[$field])) { $params[$this->formatMap[$field]] = implode(',', $filter); } } return $params; }
/** * Represent the current search results as a feed. * * @param \VuFind\Search\Base\Results $results Search results to convert to * feed * @param string $currentPath Base path to display in feed * (leave null to load dynamically using currentpath view helper) * * @return Feed */ public function __invoke($results, $currentPath = null) { $this->registerExtension(); // Determine base URL if not already provided: if (is_null($currentPath)) { $currentPath = $this->getView()->plugin('currentpath')->__invoke(); } $serverUrl = $this->getView()->plugin('serverurl'); $baseUrl = $serverUrl($currentPath); // Create the parent feed $feed = new Feed(); $feed->setTitle($this->translate('Results for') . ' ' . $results->getParams()->getDisplayQuery()); $feed->setLink($baseUrl . $results->getUrlQuery()->setViewParam(null, false)); $feed->setFeedLink($baseUrl . $results->getUrlQuery()->getParams(false), $results->getParams()->getView()); $feed->setDescription($this->translate('Showing') . ' ' . $results->getStartRecord() . '-' . $results->getEndRecord() . ' ' . $this->translate('of') . ' ' . $results->getResultTotal()); $params = $results->getParams(); // add atom links for easier paging $feed->addOpensearchLink($baseUrl . $results->getUrlQuery()->setPage(1, false), 'first', $params->getView()); if ($params->getPage() > 1) { $feed->addOpensearchLink($baseUrl . $results->getUrlQuery()->setPage($params->getPage() - 1, false), 'previous', $params->getView()); } $lastPage = ceil($results->getResultTotal() / $params->getLimit()); if ($params->getPage() < $lastPage) { $feed->addOpensearchLink($baseUrl . $results->getUrlQuery()->setPage($params->getPage() + 1, false), 'next', $params->getView()); } $feed->addOpensearchLink($baseUrl . $results->getUrlQuery()->setPage($lastPage, false), 'last', $params->getView()); // add opensearch fields $feed->setOpensearchTotalResults($results->getResultTotal()); $feed->setOpensearchItemsPerPage($params->getLimit()); $feed->setOpensearchStartIndex($results->getStartRecord() - 1); $feed->setOpensearchSearchTerms($params->getQuery()->getString()); $records = $results->getResults(); foreach ($records as $current) { $this->addEntry($feed, $current); } return $feed; }
/** * Support method for getVisData() -- extract details from applied filters. * * @param array $filters Current filter list * * @return array */ protected function processDateFacets($filters) { $result = []; foreach ($this->dateFacets as $current) { $from = $to = ''; if (isset($filters[$current])) { foreach ($filters[$current] as $filter) { if (preg_match('/\\[\\d+ TO \\d+\\]/', $filter)) { $range = explode(' TO ', trim($filter, '[]')); $from = $range[0] == '*' ? '' : $range[0]; $to = $range[1] == '*' ? '' : $range[1]; break; } } } $result[$current] = [$from, $to]; $result[$current]['label'] = $this->searchObject->getParams()->getFacetLabel($current); } return $result; }
/** * Get terms related to the query. * * @return array */ public function getTerms() { // Extract the first search term from the search object: $search = $this->searchObject->getParams()->getQuery(); $lookfor = $search instanceof Query ? $search->getString() : ''; // Get terminology information: $terms = $this->worldCatUtils->getRelatedTerms($lookfor, $this->vocab); // Wipe out any empty or unexpected sections of the related terms array; // this will make it easier to only display content in the template if // we have something worth displaying. if (is_array($terms)) { $desiredKeys = ['exact', 'broader', 'narrower']; foreach ($terms as $key => $value) { if (empty($value) || !in_array($key, $desiredKeys)) { unset($terms[$key]); } } } return $terms; }
/** * Return the count of records when checkbox filter is activated. * * @param array $checkboxFilter Checkbox filter * @param \VuFind\Search\Base\Results $results Search result set * * @return int Record count */ public function __invoke($checkboxFilter, $results) { $ret = 0; list($field, $value) = $results->getParams()->parseFilter($checkboxFilter['filter']); $facets = $results->getFacetList([$field => $value]); if (isset($facets[$field])) { foreach ($facets[$field]['list'] as $item) { if ($item['value'] == $value || substr($value, -1) == '*' && preg_match('/^' . $value . '/', $item['value']) || $item['value'] == 'true' && $value == '1' || $item['value'] == 'false' && $value == '0') { $ret += $item['count']; } } } elseif ($field == 'online_boolean' && $value == '1') { // Special case for online_boolean, which is translated to online_str_mv // when deduplication is enabled. // If we don't have a facet value for online_boolean it means we need to // do an additional lookup for online_str_mv. $results = clone $results; $params = $results->getParams(); $options = $results->getOptions(); $searchConfig = $this->getView()->getHelperPluginManager()->getServiceLocator()->get('VuFind\\Config')->get($options->getSearchIni()); if (!empty($searchConfig->Records->sources)) { $sources = explode(',', $searchConfig->Records->sources); $sources = array_map(function ($s) { return "\"{$s}\""; }, $sources); $params->addFilter('(online_str_mv:' . implode(' OR online_str_mv:', $sources) . ')'); } else { $params->addFilter('online_str_mv:*'); } $params->setLimit(0); $params->resetFacetConfig(); $options->disableHighlighting(); $options->spellcheckEnabled(false); $results->performAndProcessSearch(); return $results->getResultTotal(); } return $ret; }
/** * Called at the end of the Search Params objects' initFromRequest() method. * This method is responsible for setting search parameters needed by the * recommendation module and for reading any existing search parameters that may * be needed. * * @param \VuFind\Search\Base\Params $params Search parameter object * @param \Zend\StdLib\Parameters $request Parameter object representing user * request. * * @return void */ public function init($params, $request) { // See if we can determine the label for the current search type; first // check for an override in the GET parameters, then look at the incoming // params object.... $typeLabel = $request->get('typeLabel'); $type = $request->get('type'); if (empty($typeLabel) && !empty($type)) { $typeLabel = $params->getOptions()->getLabelForBasicHandler($type); } // Extract a search query: $lookfor = $request->get($this->requestParam); if (empty($lookfor) && is_object($params)) { $lookfor = $params->getQuery()->getAllTerms(); } // Set up the parameters: $this->results = $this->resultsManager->get($this->getSearchClassId()); $params = $this->results->getParams(); $params->setLimit($this->limit); $params->setBasicSearch($lookfor, $params->getOptions()->getHandlerForLabel($typeLabel)); // Perform the search: $this->results->performAndProcessSearch(); }
/** * process * * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { // If we received a Summon search object, we'll use that. If not, we need // to create a new Summon search object using the specified request // parameter for search terms. if ($results->getParams()->getSearchClassId() != 'Summon') { $sm = $this->getSearchManager(); $params = $sm->setSearchClassId('Summon')->getParams(); $params->setBasicSearch($this->lookfor); $results = $sm->setSearchClassId('Summon')->getResults($params); $results->performAndProcessSearch(); } $this->databases = $results->getDatabaseRecommendations(); }
/** * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { $handler = $results->getParams()->getSearchHandler(); $this->results = $results; // If the handler is null, we can't figure out a single handler, so this // is probably an advanced search. In that case, we shouldn't try to change // anything! We should only show recommendations if we know what handler is // being used and can determine that it is not the same as the new handler // that we want to recommend. $this->active = !is_null($handler) && $handler != $this->newHandler; }
/** * process * * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { $filters = $results->getParams()->getFilters(); foreach ($filters as $key => $value) { if ($key == $this->geoField) { $match = array(); if (preg_match('/Intersects\\(([0-9 \\-\\.]+)\\)/', $value[0], $match)) { $this->selectedCoordinates = explode(' ', $match[1]); } else { if (preg_match($this->polygonMatch, $value[0], $match)) { $this->selectedCoordinates = [$match[1], $match[2], $match[3], $match[4]]; } } $this->searchParams = $results->getUrlQuery()->removeFacet($this->geoField, $value[0], false); } } if ($this->searchParams == null) { $this->searchParams = $results->getUrlQuery()->getParams(false); } }
/** * Return a modified results array for the case where we need to retrieve data * from the next page of results * * @param array $retVal Return values (in progress) * @param \VuFind\Search\Base\Results $lastSearch Representation of last search * @param int $pos Current position within next * page * * @return array */ protected function scrollToNextPage($retVal, $lastSearch, $pos) { // increase the page in the session because // we're now sliding into the next page // (++ doesn't work on ArrayObjects) $this->data->page = $this->data->page + 1; // shift pages to the left $tmp = $this->data->currIds; $this->data->currIds = $this->data->nextIds; $this->data->prevIds = $tmp; $this->data->nextIds = null; // now we can set the previous/next record $retVal['previousRecord'] = $this->data->prevIds[count($this->data->prevIds) - 1]; if ($pos < count($this->data->currIds) - 1) { $retVal['nextRecord'] = $this->data->currIds[$pos + 1]; } // recalculate the current position $retVal['currentPosition'] = ($this->data->page - 1) * $this->data->limit + $pos + 1; // update the search URL in the session $lastSearch->getParams()->setPage($this->data->page); $this->rememberSearch($lastSearch); // and we're done return $retVal; }
/** * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { $this->results = $results; // function will return blank on Advanced Search if ($results->getParams()->getSearchType() == 'advanced') { return; } // check result limit before proceeding... if ($this->resultLimit > 0 && $this->resultLimit < $results->getResultTotal()) { return; } // Build an advanced search request that prevents Solr from retrieving // records that would already have been retrieved by a search of the biblio // core, i.e. it only returns results where $lookfor IS found in in the // "Heading" search and IS NOT found in the "MainHeading" search defined // in authsearchspecs.yaml. $request = new Parameters(['join' => 'AND', 'bool0' => ['AND'], 'lookfor0' => [$this->lookfor], 'type0' => ['Heading'], 'bool1' => ['NOT'], 'lookfor1' => [$this->lookfor], 'type1' => ['MainHeading']]); // Initialise and process search (ignore Solr errors -- no reason to fail // just because search syntax is not compatible with Authority core): try { $authResults = $this->resultsManager->get('SolrAuth'); $authParams = $authResults->getParams(); $authParams->initFromRequest($request); foreach ($this->filters as $filter) { $authParams->addHiddenFilter($filter); } $results = $authResults->getResults(); } catch (RequestErrorException $e) { return; } // loop through records and assign id and headings to separate arrays defined // above foreach ($results as $result) { // Extract relevant details: $recordArray = ['id' => $result->getUniqueID(), 'heading' => $result->getBreadcrumb()]; // check for duplicates before adding record to recordSet if (!$this->inArrayR($recordArray['heading'], $this->recommendations)) { array_push($this->recommendations, $recordArray); } else { continue; } } }
/** * Saves the search to wherever the config [Statistics] says so * * @param \VuFind\Search\Base\Results $data Results from Search controller * @param Zend_Controller_Request_Http $request Request data from the controller * * @return void */ public function log($data, $request) { $stat = ['phrase' => $data->getParams()->getDisplayQuery(), 'searchSource' => $data->getParams()->getSearchClassId(), 'type' => $data->getParams()->getSearchHandler(), 'resultCount' => $data->getResultTotal(), 'noresults' => $data->getResultTotal() == 0]; $this->save($stat, $request); }
/** * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { // If we received a Summon search object, we'll use that. If not, we need // to create a new Summon search object using the specified request // parameter for search terms. if ($results->getParams()->getSearchClassId() != 'Summon') { $results = $this->resultsManager->get('Summon'); $this->configureSummonResults($results); $results->performAndProcessSearch(); } $this->results = $results; }
/** * Returns search term. * * @return string */ public function getSearchTerm() { $search = $this->results->getParams()->getQuery(); return $search instanceof Query ? $search->getString() : ''; }
/** * Build a hidden filter query fragment from the given filters * * @param Results $results Search results * @param array $filters Filters * * @return string Query parameters */ protected function buildUrlHiddenFilters(Results $results, $filters) { // Set up results object for URL building: $params = $results->getParams(); foreach ($filters as $filter) { $params->addHiddenFilter($filter); } $urlParams = $results->getUrlQuery()->getParams(false); return $urlParams !== '?' ? $urlParams : ''; }
/** * Return a modified results array for the case where we need to retrieve data * from the the last page of results * * @param array $retVal Return values (in progress) * @param \VuFind\Search\Base\Results $lastSearch Representation of last search * * @return array */ protected function scrollToLastRecord($retVal, $lastSearch) { // Set page in session to Last Page $this->data->page = $this->getLastPageNumber(); // update the search URL in the session $lastSearch->getParams()->setPage($this->data->page); $this->rememberSearch($lastSearch); // update current, next and prev Ids $this->data->currIds = $this->fetchPage($lastSearch, $this->data->page); $this->data->prevIds = $this->fetchPage($lastSearch, $this->data->page - 1); $this->data->nextIds = null; // recalculate the current position $retVal['currentPosition'] = $this->data->total; // now we can set the previous/next record $retVal['nextRecord'] = null; if (count($this->data->currIds) > 1) { $pos = count($this->data->currIds) - 2; $retVal['previousRecord'] = $this->data->currIds[$pos]; } else { if (count($this->data->prevIds) > 0) { $prevPos = count($this->data->prevIds) - 1; $retVal['previousRecord'] = $this->data->prevIds[$prevPos]; } } // and we're done return $retVal; }
/** * Internal utility function for initializing * UrlQueryHelper for a Results-object with search ids for all tabs. * * @param ResultsManager $results Search results. * @param ServiceManager $locator Service locator. * * @return Results Search results with initialized UrlQueryHelper */ public static function initUrlQueryHelper(\VuFind\Search\Base\Results $results, $locator) { if (Console::isConsole()) { return $results; } $helper = new UrlQueryHelper($results->getParams()); $savedSearches = $locator->get('Request')->getQuery('search'); if ($savedSearches) { $helper->setDefaultParameter('search', $savedSearches); } $results->setHelper('urlQuery', $helper); return $results; }
/** * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { $filters = $results->getParams()->getFilterList(false); if (count($filters) > 0) { foreach ($filters as $filter) { foreach ($filter as $f) { $this->activeFacetsCount++; } } } $this->results = $results; }
/** * Called after the Search Results object has performed its main search. This * may be used to extract necessary information from the Search Results object * or to perform completely unrelated processing. * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ public function process($results) { $this->query = $results->getParams()->getDisplayQuery(); }
/** * Store the URL of the provided search (if appropriate). * * @param \VuFind\Search\Base\Results $results Search results object * * @return void */ protected function rememberSearch($results) { // Only save search URL if the property tells us to... if ($this->rememberSearch) { $searchUrl = $this->url()->fromRoute($results->getOptions()->getSearchAction()) . $results->getUrlQuery()->getParams(false); $this->getSearchMemory()->rememberSearch($searchUrl); } // Always save search parameters, since these are namespaced by search // class ID. $this->getSearchMemory()->rememberParams($results->getParams()); }
/** * Represent the current search results as a feed. * * @param \VuFind\Search\Base\Results $results Search results to convert to * feed * @param string $currentPath Base path to display in feed * (leave null to load dynamically using currentpath view helper) * * @return Feed */ public function __invoke($results, $currentPath = null) { $this->registerExtension(); // Determine base URL if not already provided: if (is_null($currentPath)) { $currentPath = $this->getView()->plugin('currentpath')->__invoke(); } $serverUrl = $this->getView()->plugin('serverurl'); $baseUrl = $serverUrl($currentPath); // Create the parent feed $feed = new Feed(); $translator = $this->getTranslator(); $feed->setTitle($translator('Results for') . ' ' . $results->getParams()->getDisplayQuery()); $feed->setLink($baseUrl . $results->getUrlQuery()->setViewParam(null, false)); $feed->setFeedLink($baseUrl . $results->getUrlQuery()->getParams(false), $results->getParams()->getView()); $records = $results->getResults(); $feed->setDescription($translator('Displaying the top') . ' ' . count($records) . ' ' . $translator('search results of') . ' ' . $results->getResultTotal() . ' ' . $translator('found')); foreach ($records as $current) { $this->addEntry($feed, $current); } return $feed; }