/** * Set up filters based on VuFind settings. * * @param ParamBag $params Parameter collection to update * * @return void */ public function createBackendFilterParameters(ParamBag $params) { // flag our non-Standard checkbox filters: $foundIncludeNewspapers = false; # includeNewspapers $foundIncludeWithoutFulltext = false; # includeWithoutFulltext $filterList = $this->getFilterList(); // Which filters should be applied to our query? if (!empty($filterList)) { // Loop through all filters and add appropriate values to request: foreach ($filterList as $filterArray) { foreach ($filterArray as $filt) { $safeValue = SummonQuery::escapeParam($filt['value']); if ($filt['field'] == 'holdingsOnly') { // Special case -- "holdings only" is a separate parameter from // other facets. $params->set('holdings', strtolower(trim($safeValue)) == 'true'); } else { if ($filt['field'] == 'excludeNewspapers') { // support a checkbox for excluding newspapers: // this is now the default behaviour. } else { if ($filt['field'] == 'includeNewspapers') { // explicitly include newspaper articles $foundIncludeNewspapers = true; } else { if ($range = SolrUtils::parseRange($filt['value'])) { // Special case -- range query (translate [x TO y] syntax): $from = SummonQuery::escapeParam($range['from']); $to = SummonQuery::escapeParam($range['to']); $params->add('rangeFilters', "PublicationDate,{$from}:{$to}"); } else { if ($filt['field'] == 'includeWithoutFulltext') { $foundIncludeWithoutFulltext = true; } else { // Standard case: $params->add('filters', "{$filt['field']},{$safeValue}"); } } } } } } } } // special cases (apply also when filter list is empty) // newspaper articles if (!$foundIncludeNewspapers) { // this actually means: do *not* show newspaper articles $params->add('filters', "ContentType,Newspaper Article,true"); } // combined facet "with holdings/with fulltext" if (!$foundIncludeWithoutFulltext) { $params->set('holdings', true); $params->add('filters', 'IsFullText,true'); } else { $params->set('holdings', false); } }
/** * Test "remove" * * @return void */ public function testRemove() { $bag = new ParamBag(); $bag->set('foo', 'bar'); $bag->set('bar', 'baz'); $bag->remove('foo'); $this->assertEquals(['bar' => ['baz']], $bag->getArrayCopy()); }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); // The "relevance" sort option is a VuFind reserved word; we need to make // this null in order to achieve the desired effect with Primo: $sort = $this->getSort(); $finalSort = $sort == 'relevance' ? null : $sort; $backendParams->set('sort', $finalSort); $backendParams->set('filterList', $this->filterList); return $backendParams; }
/** * Return Primo search parameters based on a user query and params. * * @param AbstractQuery $query User query * * @return ParamBag */ public function build(AbstractQuery $query) { // Send back results $params = new ParamBag(); $params->set('query', $this->abstractQueryToArray($query)); return $params; }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); // Sort $sort = $this->getSort(); $backendParams->set('sortKeys', empty($sort) ? 'relevance' : $sort); return $backendParams; }
/** * Return Summon search parameters based on a user query and params. * * @param AbstractQuery $query User query * * @return ParamBag */ public function build(AbstractQuery $query) { // Build base query $queryStr = $this->abstractQueryToString($query); // Send back results $params = new ParamBag(); $params->set('query', $queryStr); return $params; }
/** * Return LibGuides search parameters based on a user query and params. * * @param AbstractQuery $query User query * * @return ParamBag */ public function build(AbstractQuery $query) { // Send back results $params = new ParamBag(); // Convert the query to an array, then flatten that to a string // (right now, we're ignoring a lot of data -- we may want to // revisit this and see if more detail can be utilized). $array = $this->abstractQueryToArray($query); if (isset($array[0]['lookfor'])) { $params->set('search', $array[0]['lookfor']); } return $params; }
/** * Return WorldCat search parameters based on a user query and params. * * @param AbstractQuery $query User query * * @return ParamBag */ public function build(AbstractQuery $query) { // Build base query $queryStr = $this->abstractQueryToString($query); // Exclude current library from results (if applicable) if (null !== $this->oclcCodeToExclude) { $queryStr .= ' not srw.li all "' . $this->oclcCodeToExclude . '"'; } // Send back results $params = new ParamBag(); $params->set('query', $queryStr); return $params; }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); // Sources $sources = $this->getSelectedShards(); if (!empty($sources)) { $allShards = $this->getOptions()->getShards(); foreach ($sources as $i => $current) { $sources[$i] = $allShards[$current]; } $backendParams->set('filter', 'pz:id=' . implode('|', $sources)); } return $backendParams; }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); $options = $this->getOptions(); // The "relevance" sort option is a VuFind reserved word; we need to make // this null in order to achieve the desired effect with Summon: $sort = $this->getSort(); $finalSort = $sort == 'relevance' ? null : $sort; $backendParams->set('sort', $finalSort); if ($options->highlightEnabled()) { $backendParams->set('highlight', true); } $view = $this->getEdsView(); if (isset($view)) { $backendParams->set('view', $view); } $mode = $options->getSearchMode(); if (isset($mode)) { $backendParams->set('searchMode', $mode); } //process the setup only parameter if (true == $this->isSetupOnly) { $backendParams->set('setuponly', $this->isSetupOnly); } $this->createBackendFilterParameters($backendParams, $options); return $backendParams; }
/** * Execute a search. * * @param ParamBag $params Parameters * @param integer $offset Search offset * @param integer $limit Search limit * * @return string */ public function search(ParamBag $params, $offset, $limit) { $params->set('startRecord', $offset); $params->set('maximumRecords', $limit); $params->set('servicelevel', 'full'); $params->set('wskey', $this->wskey); $response = $this->call('POST', $params->getArrayCopy(), false); $xml = simplexml_load_string($response); $docs = isset($xml->records->record) ? $xml->records->record : []; $finalDocs = []; foreach ($docs as $doc) { $finalDocs[] = $doc->recordData->asXML(); } return ['docs' => $finalDocs, 'offset' => $offset, 'total' => isset($xml->numberOfRecords) ? (int) $xml->numberOfRecords : 0]; }
/** * Add user institutions as facet queries to backend params * * @param ParamBag $backendParams * * @return ParamBag */ protected function addUserInstitutions(ParamBag $backendParams) { /** @var Manager $favoritesManger */ $favoritesManger = $this->getServiceLocator()->get('Swissbib\\FavoriteInstitutions\\Manager'); /** @var String[] $favoriteInstitutions */ $favoriteInstitutions = $favoritesManger->getUserInstitutions(); if (sizeof($favoriteInstitutions) > 0) { //facet parameter has to be true in case it's false $backendParams->set("facet", "true"); foreach ($favoriteInstitutions as $institutionCode) { //GH 19.12.2014: use configuration for index name //more investigation for a better solution necessary $backendParams->add("facet.query", "mylibrary:" . $institutionCode); //$backendParams->add("bq", "institution:" . $institutionCode . "^5000"); } } return $backendParams; }
/** * Set up filters based on VuFind settings. * * @param ParamBag $params Parameter collection to update * * @return void */ public function createBackendFilterParameters(ParamBag $params) { // Which filters should be applied to our query? $filterList = $this->getFilterList(); if (!empty($filterList)) { $orFacets = []; // Loop through all filters and add appropriate values to request: foreach ($filterList as $filterArray) { foreach ($filterArray as $filt) { $safeValue = SummonQuery::escapeParam($filt['value']); // Special case -- "holdings only" is a separate parameter from // other facets. if ($filt['field'] == 'holdingsOnly') { $params->set('holdings', strtolower(trim($safeValue)) == 'true'); } else { if ($filt['field'] == 'queryExpansion') { // Special case -- "query expansion" is a separate parameter // from other facets. $params->set('expand', strtolower(trim($safeValue)) == 'true'); } else { if ($filt['field'] == 'excludeNewspapers') { // Special case -- support a checkbox for excluding // newspapers: $params->add('filters', "ContentType,Newspaper Article,true"); } else { if ($range = SolrUtils::parseRange($filt['value'])) { // Special case -- range query (translate [x TO y] syntax): $from = SummonQuery::escapeParam($range['from']); $to = SummonQuery::escapeParam($range['to']); $params->add('rangeFilters', "{$filt['field']},{$from}:{$to}"); } else { if ($filt['operator'] == 'OR') { // Special case -- OR facets: $orFacets[$filt['field']] = isset($orFacets[$filt['field']]) ? $orFacets[$filt['field']] : []; $orFacets[$filt['field']][] = $safeValue; } else { // Standard case: $fq = "{$filt['field']},{$safeValue}"; if ($filt['operator'] == 'NOT') { $fq .= ',true'; } $params->add('filters', $fq); } } } } } } // Deal with OR facets: foreach ($orFacets as $field => $values) { $params->add('groupFilters', $field . ',or,' . implode(',', $values)); } } } }
/** * Inject response writer and named list implementation into parameters. * * @param ParamBag $params Parameters * * @return void * * @throws InvalidArgumentException Response writer and named list * implementation already set to an incompatible type. */ protected function injectResponseWriter(ParamBag $params) { if (array_diff($params->get('wt') ?: [], ['json'])) { throw new InvalidArgumentException(sprintf('Invalid response writer type: %s', implode(', ', $params->get('wt')))); } if (array_diff($params->get('json.nl') ?: [], ['arrarr'])) { throw new InvalidArgumentException(sprintf('Invalid named list implementation type: %s', implode(', ', $params->get('json.nl')))); } $params->set('wt', ['json']); $params->set('json.nl', ['arrarr']); }
/** * Return SOLR search parameters based on a user query and params. * * @param AbstractQuery $query User query * * @return ParamBag */ public function build(AbstractQuery $query) { $params = new ParamBag(); // Add spelling query if applicable -- note that we mus set this up before // we process the main query in order to avoid unwanted extra syntax: if ($this->createSpellingQuery) { $params->set('spellcheck.q', $query->getAllTerms()); } if ($query instanceof QueryGroup) { $query = $this->reduceQueryGroup($query); } else { $query->setString($this->getLuceneHelper()->normalizeSearchString($query->getString())); } $string = $query->getString() ?: '*:*'; if ($handler = $this->getSearchHandler($query->getHandler(), $string)) { if (!$handler->hasExtendedDismax() && $this->getLuceneHelper()->containsAdvancedLuceneSyntax($string)) { $newString = $this->createAdvancedInnerSearchString($string, $handler); if ($handler->hasDismax()) { $oldString = $newString; $newString = $handler->createBoostQueryString($newString); // If a boost was added, we don't want to highlight based on // the boost query, so we should use the non-boosted version: if ($this->createHighlightingQuery && $oldString != $string) { $params->set('hl.q', $oldString); } if ($string == '*:*') { $params->set('hl.q', '*:*'); } } $string = $newString; } else { if ($handler->hasDismax()) { $params->set('qf', implode(' ', $handler->getDismaxFields())); $params->set('qt', $handler->getDismaxHandler()); foreach ($handler->getDismaxParams() as $param) { $params->add(reset($param), next($param)); } if ($handler->hasFilterQuery()) { $params->add('fq', $handler->getFilterQuery()); } } else { $string = $handler->createSimpleQueryString($string); } } } $params->set('q', $string); return $params; }
/** * @return ParamBag */ protected function getParamBag() { $paramBag = new ParamBag(); $paramBag->set('q', array('a')); $paramBag->set('qf', array('title_short title_sub author series journals topic fulltext')); $paramBag->set('qt', array('edismax')); return $paramBag; }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); // Spellcheck $backendParams->set('spellcheck', $this->getOptions()->spellcheckEnabled() ? 'true' : 'false'); // Facets $facets = $this->getFacetSettings(); if (!empty($facets)) { $backendParams->add('facet', 'true'); if (isset($facets['indexSortedFacets'])) { foreach ($facets['indexSortedFacets'] as $field) { $backendParams->add("f.{$field}.facet.sort", 'index'); } unset($facets['indexSortedFacets']); } foreach ($facets as $key => $value) { if (substr($key, 0, strlen(self::PER_FIELD_PARAM)) === self::PER_FIELD_PARAM) { $backendParams->add($key, $value); } else { $backendParams->add("facet.{$key}", $value); } } $backendParams->add('facet.mincount', 1); } // Filters $filters = $this->getFilterSettings(); foreach ($filters as $filter) { $backendParams->add('fq', $filter); } // Shards $allShards = $this->getOptions()->getShards(); $shards = $this->getSelectedShards(); if (empty($shards)) { $shards = array_keys($allShards); } // If we have selected shards, we need to format them: if (!empty($shards)) { $selectedShards = []; foreach ($shards as $current) { $selectedShards[$current] = $allShards[$current]; } $shards = $selectedShards; $backendParams->add('shards', implode(',', $selectedShards)); } // Sort $sort = $this->getSort(); if ($sort) { // If we have an empty search with relevance sort, see if there is // an override configured: if ($sort == 'relevance' && $this->getQuery()->getAllTerms() == '' && ($relOv = $this->getOptions()->getEmptySearchRelevanceOverride())) { $sort = $relOv; } $backendParams->add('sort', $this->normalizeSort($sort)); } // Highlighting -- on by default, but we should disable if necessary: if (!$this->getOptions()->highlightEnabled()) { $backendParams->add('hl', 'false'); } // Pivot facets for visual results if ($pf = $this->getPivotFacets()) { $backendParams->add('facet.pivot', $pf); } if (!empty($this->boostFunctions)) { foreach ($this->boostFunctions as $func) { $backendParams->add('boost', $func); } } return $backendParams; }
/** * Submit requests for more spelling suggestions. * * @param Spellcheck $spellcheck Aggregating spellcheck object * @param string $query Spellcheck query * * @return void */ protected function aggregateSpellcheck(Spellcheck $spellcheck, $query) { while (next($this->dictionaries) !== false) { $params = new ParamBag(); $params->set('spellcheck', 'true'); $params->set('spellcheck.dictionary', current($this->dictionaries)); $queryObj = new Query($query, 'AllFields'); try { $collection = $this->backend->search($queryObj, 0, 0, $params); $spellcheck->mergeWith($collection->getSpellcheck()); } catch (\Exception $ex) { if ($this->logger) { $this->logger->err("Exception thrown when aggregating spellcheck, ignoring.", array('exception' => $ex)); } } } }
/** * Return SOLR search parameters based on a record Id and params. * * @param string $id Record Id * * @return ParamBag */ public function build($id) { $params = new ParamBag(); if ($this->useHandler) { $mltParams = $this->handlerParams ? $this->handlerParams : 'qf=title,title_short,callnumber-label,topic,language,author,' . 'publishDate mintf=1 mindf=1'; $params->set('q', sprintf('{!mlt %s}%s', $mltParams, $id)); } else { $params->set('q', sprintf('%s:"%s"', $this->uniqueKey, addcslashes($id, '"'))); $params->set('qt', 'morelikethis'); } if (null === $params->get('rows')) { $params->set('rows', $this->count); } return $params; }
/** * Perform a search with clean params * * @param ParamBag $paramBag The params you'd normally send to solr * * @return json */ protected function search($paramBag) { // Remove global filters from the Solr connector $map = $this->solr->getMap(); $params = $map->getParameters('select', 'appends'); $map->setParameters('select', 'appends', []); // Turn off grouping $paramBag->set('group', 'false'); $paramBag->add('wt', 'json'); // Search $response = $this->solr->search($paramBag); // Reapply the global filters $map->setParameters('select', 'appends', $params->getArrayCopy()); return $response; }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); // Spellcheck $backendParams->set('spellcheck', $this->getOptions()->spellcheckEnabled() ? 'true' : 'false'); // Facets $facets = $this->getFacetSettings(); if (!empty($facets)) { $backendParams->add('facet', 'true'); foreach ($facets as $key => $value) { // prefix keys with "facet" unless they already have a "f." prefix: $fullKey = substr($key, 0, 2) == 'f.' ? $key : "facet.{$key}"; $backendParams->add($fullKey, $value); } $backendParams->add('facet.mincount', 1); } // Filters $filters = $this->getFilterSettings(); foreach ($filters as $filter) { $backendParams->add('fq', $filter); } // Shards $allShards = $this->getOptions()->getShards(); $shards = $this->getSelectedShards(); if (empty($shards)) { $shards = array_keys($allShards); } // If we have selected shards, we need to format them: if (!empty($shards)) { $selectedShards = []; foreach ($shards as $current) { $selectedShards[$current] = $allShards[$current]; } $shards = $selectedShards; $backendParams->add('shards', implode(',', $selectedShards)); } // Sort $sort = $this->getSort(); if ($sort) { // If we have an empty search with relevance sort, see if there is // an override configured: if ($sort == 'relevance' && $this->getQuery()->getAllTerms() == '' && ($relOv = $this->getOptions()->getEmptySearchRelevanceOverride())) { $sort = $relOv; } $backendParams->add('sort', $this->normalizeSort($sort)); } // Highlighting -- on by default, but we should disable if necessary: if (!$this->getOptions()->highlightEnabled()) { $backendParams->add('hl', 'false'); } // Pivot facets for visual results if ($pf = $this->getPivotFacets()) { $backendParams->add('facet.pivot', $pf); } return $backendParams; }
/** * AggregateSpellcheck * * @param Spellcheck $spellcheck Spellcheck * @param string $query Query * * @return void */ protected function aggregateSpellcheck(Spellcheck $spellcheck, $query) { foreach ($this->dictionaries as $dictionary) { $params = new ParamBag(); $params->set('spellcheck', 'true'); $params->set('spellcheck.dictionary', $dictionary); $queryObj = new Query($query, 'AllFields'); $collection = $this->backend->search($queryObj, 0, 0, $params); $spellcheck->mergeWith($collection->getSpellcheck()); } }
/** * Return SOLR search parameters based on a user query and params. * * @param AbstractQuery $query User query * * @return ParamBag */ public function build(AbstractQuery $query) { $params = new ParamBag(); // Add spelling query if applicable -- note that we must set this up before // we process the main query in order to avoid unwanted extra syntax: if ($this->createSpellingQuery) { $params->set('spellcheck.q', $this->getLuceneHelper()->extractSearchTerms($query->getAllTerms())); } if ($query instanceof QueryGroup) { $query = $this->reduceQueryGroup($query); } else { $query->setString($this->getLuceneHelper()->normalizeSearchString($query->getString())); } $string = $query->getString() ?: '*:*'; if ($handler = $this->getSearchHandler($query->getHandler(), $string)) { if (!$handler->hasExtendedDismax() && $this->getLuceneHelper()->containsAdvancedLuceneSyntax($string)) { $string = $this->createAdvancedInnerSearchString($string, $handler); if ($handler->hasDismax()) { $oldString = $string; $string = $handler->createBoostQueryString($string); // If a boost was added, we don't want to highlight based on // the boost query, so we should use the non-boosted version: if ($this->createHighlightingQuery && $oldString != $string) { $params->set('hl.q', $oldString); } } } else { if ($handler->hasDismax()) { // If we're using extended dismax, we'll miss out on the question // mark fix in createAdvancedInnerSearchString(), so we should // apply it here. If other query munges arise that are valuable // to both dismax and edismax, we should add a wrapper function // around them and call it from here instead of this one very // specific check. $string = $this->fixTrailingQuestionMarks($string); $params->set('qf', implode(' ', $handler->getDismaxFields())); $params->set('qt', $handler->getDismaxHandler()); foreach ($handler->getDismaxParams() as $param) { $params->add(reset($param), next($param)); } if ($handler->hasFilterQuery()) { $params->add('fq', $handler->getFilterQuery()); } } else { $string = $handler->createSimpleQueryString($string); } } } $params->set('q', $string); return $params; }
/** * Create search backend parameters for advanced features. * * @return ParamBag */ public function getBackendParameters() { $backendParams = new ParamBag(); // Spellcheck $backendParams->set('spellcheck', $this->getOptions()->spellcheckEnabled() ? 'true' : 'false'); // Facets $facets = $this->getFacetSettings(); if (!empty($facets)) { $backendParams->add('facet', 'true'); foreach ($facets as $key => $value) { $backendParams->add("facet.{$key}", $value); } $backendParams->add('facet.mincount', 1); } // Filters $filters = $this->getFilterSettings(); foreach ($filters as $filter) { $backendParams->add('fq', $filter); } // Shards $allShards = $this->getOptions()->getShards(); $shards = $this->getSelectedShards(); if (empty($shards)) { $shards = array_keys($allShards); } // If we have selected shards, we need to format them: if (!empty($shards)) { $selectedShards = []; foreach ($shards as $current) { $selectedShards[$current] = $allShards[$current]; } $shards = $selectedShards; $backendParams->add('shards', implode(',', $selectedShards)); } // Sort $sort = $this->getSort(); if ($sort) { $backendParams->add('sort', $this->normalizeSort($sort)); } // Highlighting -- on by default, but we should disable if necessary: if (!$this->getOptions()->highlightEnabled()) { $backendParams->add('hl', 'false'); } // Pivot facets for visual results if ($pf = $this->getPivotFacets()) { $backendParams->add('facet.pivot', $pf); } return $backendParams; }
/** * Execute a search. * * @param ParamBag $params Parameters * @param int $offset Search offset * @param int $limit Search limit * * @return array */ public function search(ParamBag $params, $offset, $limit) { $startrec = $offset + 1; $params->set('startrec', $startrec); $params->set('numrec', $limit); $params->set('prof', $this->prof); $params->set('pwd', $this->pwd); $response = $this->call('GET', $params->getArrayCopy(), false); $xml = simplexml_load_string($response); $finalDocs = []; foreach ($xml->SearchResults->records->rec as $doc) { $finalDocs[] = simplexml_load_string($doc->asXML()); } return ['docs' => $finalDocs, 'offset' => $offset, 'total' => (int) $xml->Hits]; }