Exemple #1
0
 /**
  * Test sanitizeDate functionality.
  *
  * @return void
  */
 public function testSanitizeDate()
 {
     $tests = ['[2014]' => '2014-01-01', 'n.d.' => null, 'may 7, 1981' => '1981-05-07', 'July 1570' => '1570-07-01', 'incomprehensible garbage' => null, '1930/12/21' => '1930-12-21', '1964?' => '1964-01-01', '1947-3' => '1947-03-01', '1973-02-31' => '1973-02-01', '1973-31-31' => '1973-01-01', '1964-zz' => '1964-01-01', '1964-01-zz' => '1964-01-01', 'Winter 2012' => '2012-01-01', '05-1901' => '1901-05-01', '5-1901' => '1901-05-01', '05/1901' => '1901-05-01', '5/1901' => '1901-05-01', '2nd Quarter 2004' => '2004-01-01', 'Nov 2009 and Dec 2009' => '2009-01-01'];
     foreach ($tests as $in => $out) {
         $this->assertEquals($out === null ? null : $out . 'T00:00:00Z', Utils::sanitizeDate($in));
     }
 }
Exemple #2
0
 /**
  * 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);
     }
 }
 /**
  * Get new items facets (facet titles)
  *
  * @return array
  */
 public function getNewItemsFacets()
 {
     if (!isset($this->newItemsFacets)) {
         return [];
     }
     $filters = $this->results->getParams()->getFilters();
     $result = [];
     foreach ($this->newItemsFacets as $current) {
         $from = '';
         if (isset($filters[$current])) {
             foreach ($filters[$current] as $filter) {
                 if ($range = SolrUtils::parseRange($filter)) {
                     $from = $range['from'] == '*' ? '' : $range['from'];
                     break;
                 }
             }
         }
         $result[$current] = ['raw' => $from, 'date' => preg_match('/^\\d{4}-\\d{2}-\\d{2}/', $from) ? substr($from, 0, 10) : str_replace('/DAY', '', $from)];
     }
     return $result;
 }
 /**
  * Support function to get publication date range. Return string in the form
  * "YYYY-YYYY"
  *
  * @param string                     $field   Name of filter field to check for
  * date limits
  * @param \VuFind\Search\Params\Base $params  Search parameter object
  * @param \Zend\StdLib\Parameters    $request Parameter object representing user
  * request.
  *
  * @return string
  */
 protected function getPublishedDates($field, $params, $request)
 {
     // Try to extract range details from request parameters or SearchObject:
     $from = $request->get($field . 'from');
     $to = $request->get($field . 'to');
     if (!is_null($from) && !is_null($to)) {
         $range = ['from' => $from, 'to' => $to];
     } else {
         if (is_object($params)) {
             $currentFilters = $params->getFilters();
             if (isset($currentFilters[$field][0])) {
                 $range = SolrUtils::parseRange($currentFilters[$field][0]);
             }
         }
     }
     // Normalize range if we found one:
     if (isset($range)) {
         if (empty($range['from']) || $range['from'] == '*') {
             $range['from'] = 0;
         }
         if (empty($range['to']) || $range['to'] == '*') {
             $range['to'] = date('Y') + 1;
         }
         return $range['from'] . '-' . $range['to'];
     }
     // No range found?  Return empty string:
     return '';
 }
Exemple #5
0
 /**
  * Format a single filter for use in getFilterList().
  *
  * @param string $field     Field name
  * @param string $value     Field value
  * @param string $operator  Operator (AND/OR/NOT)
  * @param bool   $translate Should we translate the label?
  *
  * @return array
  */
 protected function formatFilterListEntry($field, $value, $operator, $translate)
 {
     if (!in_array($field, $this->newItemsFacets) || !($range = Utils::parseRange($value))) {
         $result = parent::formatFilterListEntry($field, $value, $operator, $translate);
         return $this->formatDateRangeFilterListEntry($result, $field, $value);
     }
     $domain = $this->getOptions()->getTextDomainForTranslatedFacet($field);
     list($from, $fromDate) = $this->formatNewItemsDateForDisplay($range['from'], $domain);
     list($to, $toDate) = $this->formatNewItemsDateForDisplay($range['to'], $domain);
     $ndash = html_entity_decode('–', ENT_NOQUOTES, 'UTF-8');
     if ($fromDate && $toDate) {
         $displayText = $from ? "{$from} {$ndash}" : $ndash;
         $displayText .= $to ? " {$to}" : '';
     } else {
         $displayText = $from;
         $displayText .= $to ? " {$ndash} {$to}" : '';
     }
     return compact('value', 'displayText', 'field', 'operator');
 }
Exemple #6
0
 /**
  * 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));
             }
         }
     }
 }
Exemple #7
0
 /**
  * Test parseRange functionality.
  *
  * @return void
  */
 public function testParseRange()
 {
     // basic range test:
     $result = Utils::parseRange("[1 TO 100]");
     $this->assertEquals('1', $result['from']);
     $this->assertEquals('100', $result['to']);
     // test whitespace handling:
     $result = Utils::parseRange("[1      TO     100]");
     $this->assertEquals('1', $result['from']);
     $this->assertEquals('100', $result['to']);
     // test invalid ranges:
     $this->assertFalse(Utils::parseRange('1 TO 100'));
     $this->assertFalse(Utils::parseRange('[not a range to me]'));
 }
Exemple #8
0
 /**
  * Return range facet information in a format processed for use in the view.
  *
  * @param string $property Name of property containing active range facets
  *
  * @return array Array of from/to value arrays keyed by field.
  */
 protected function getRangeFacets($property)
 {
     $filters = $this->results->getParams()->getFilters();
     $result = [];
     if (isset($this->{$property}) && is_array($this->{$property})) {
         foreach ($this->{$property} as $current) {
             $from = $to = '';
             if (isset($filters[$current])) {
                 foreach ($filters[$current] as $filter) {
                     if ($range = SolrUtils::parseRange($filter)) {
                         $from = $range['from'] == '*' ? '' : $range['from'];
                         $to = $range['to'] == '*' ? '' : $range['to'];
                         break;
                     }
                 }
             }
             $result[$current] = [$from, $to];
         }
     }
     return $result;
 }
Exemple #9
0
 /**
  * Process the publicationd date range limiter widget
  *
  * @param object $searchObject Saved search object (false if none)
  *
  * @return array               To and from dates
  */
 protected function processPublicationDateRange($searchObject = false)
 {
     $from = $to = '';
     if ($searchObject) {
         $filters = $searchObject->getParams()->getFilterList();
         foreach ($filters as $key => $value) {
             if ('PublicationDate' == $key) {
                 if ($range = SolrUtils::parseRange($value[0]['value'])) {
                     $from = $range['from'] == '*' ? '11' : $range['from'];
                     $to = $range['to'] == '*' ? '12' : $range['to'];
                 }
                 $searchObject->getParams()->removeFilter($key . ':' . $value[0]['value']);
                 break;
             }
         }
     }
     return [$from, $to];
 }
Exemple #10
0
 /**
  * Support method for initSearchParams() -- set up query, handler and filters.
  *
  * @return void
  */
 protected function initSearchQuery()
 {
     // Grab relevant user parameters:
     $query = $this->userSearchParams['query'];
     $filter = $this->userSearchParams['filter'];
     $handler = $this->userSearchParams['handler'];
     // Determine which handler to use
     if (!$this->isAdvanced($query)) {
         $ss = is_null($handler) ? null : $this->getSearchSpecs($handler);
         // Is this a Dismax search?
         if (isset($ss['DismaxFields'])) {
             // Specify the fields to do a Dismax search on and use the default
             // Dismax search handler so we can use appropriate user-specified
             // solrconfig.xml settings:
             $this->solrSearchParams['qf'] = implode(' ', $ss['DismaxFields']);
             $this->solrSearchParams['qt'] = 'dismax';
             // Load any custom Dismax parameters from the YAML search spec file:
             if (isset($ss['DismaxParams']) && is_array($ss['DismaxParams'])) {
                 foreach ($ss['DismaxParams'] as $current) {
                     $this->addSolrSearchParam($current[0], $current[1]);
                 }
             }
             // Apply search-specific filters if necessary:
             if (isset($ss['FilterQuery'])) {
                 if (is_array($filter)) {
                     $filter[] = $ss['FilterQuery'];
                 } else {
                     $filter = array($ss['FilterQuery']);
                 }
             }
         } else {
             // Not DisMax... but if we have a handler set, we may still need
             // to build a query using a setting in the YAML search specs or a
             // simple field name:
             if (!empty($handler)) {
                 $query = $this->buildQueryComponent($handler, $query);
             }
         }
     } else {
         // Force boolean operators and ranges to uppercase if we are in a
         // case-insensitive mode:
         if (!$this->caseSensitiveBooleans) {
             $query = SolrUtils::capitalizeBooleans($query);
         }
         if (!$this->caseSensitiveRanges) {
             $query = SolrUtils::capitalizeRanges($query);
         }
         // Process advanced search -- if a handler was specified, let's see
         // if we can adapt the search to work with the appropriate fields.
         if (!empty($handler)) {
             // If highlighting is enabled, we only want to use the inner query
             // for highlighting; anything added outside of this is a boost and
             // should be ignored for highlighting purposes!
             if ($this->userSearchParams['highlight']) {
                 $this->solrSearchParams['hl.q'] = $this->buildAdvancedInnerQuery($handler, $query);
             }
             $query = $this->buildAdvancedQuery($handler, $query);
         }
     }
     // Now that query and filters are fully processed, add them to the params:
     $this->solrSearchParams['q'] = $query;
     if (is_array($filter) && count($filter)) {
         $this->solrSearchParams['fq'] = $filter;
     }
 }
Exemple #11
0
 /**
  * Build basic Query string from search parameters (support method for
  * buildQuery)
  *
  * @param array $params An array of search parameters
  *
  * @return string
  */
 protected function buildBasicQuery($params)
 {
     // Clean and validate input -- note that index may be in a
     // different field depending on whether this is a basic or
     // advanced search.
     $lookfor = $params['lookfor'];
     if (isset($params['field'])) {
         $index = $params['field'];
     } else {
         if (isset($params['index'])) {
             $index = $params['index'];
         } else {
             $index = 'AllFields';
         }
     }
     // Force boolean operators to uppercase if we are in a
     // case-insensitive mode:
     if (!$this->caseSensitiveBooleans) {
         $lookfor = SolrUtils::capitalizeBooleans($lookfor);
     }
     // Prepend the index name, unless it's the special "AllFields"
     // index:
     return $index != 'AllFields' ? "{$index}:({$lookfor})" : $lookfor;
 }
 /**
  * Get the current settings for the date range facet, if it is set:
  *
  * @param object $savedSearch Saved search object (false if none)
  *
  * @return array              Date range: Key 0 = from, Key 1 = to.
  */
 protected function getDateRangeSettings($savedSearch = false)
 {
     // Default to blank strings:
     $from = $to = '';
     // Check to see if there is an existing range in the search object:
     if ($savedSearch) {
         $filters = $savedSearch->getParams()->getFilters();
         if (isset($filters['publishDate'])) {
             foreach ($filters['publishDate'] as $current) {
                 if ($range = SolrUtils::parseRange($current)) {
                     $from = $range['from'] == '*' ? '' : $range['from'];
                     $to = $range['to'] == '*' ? '' : $range['to'];
                     $savedSearch->getParams()->removeFilter('publishDate:' . $current);
                     break;
                 }
             }
         }
     }
     // Send back the settings:
     return array($from, $to);
 }
Exemple #13
0
 /**
  * Get new items facets (facet titles)
  *
  * @return array
  */
 public function getNewItemsFacets()
 {
     $filters = $this->results->getParams()->getFilters();
     $result = [];
     foreach ($this->newItemsFacets as $current) {
         $from = '';
         if (isset($filters[$current])) {
             foreach ($filters[$current] as $filter) {
                 if ($range = SolrUtils::parseRange($filter)) {
                     $from = $range['from'] == '*' ? '' : $range['from'];
                     break;
                 }
             }
         }
         $translatable = '';
         if (preg_match('/^NOW-(\\w+)/', $from, $matches)) {
             $translatable = 'new_items_' . strtolower($matches[1]);
         }
         $result[$current] = ['raw' => $from, 'translatable' => $translatable];
     }
     return $result;
 }
Exemple #14
0
 /**
  * Support method for initFullDateFilters() -- normalize a date for use in a
  * year/month/day date range.
  *
  * @param string $date Value to check for valid date.
  *
  * @return string      Formatted date.
  */
 protected function formatDateForFullDateRange($date)
 {
     // Make sure date is valid; default to wildcard otherwise:
     $date = SolrUtils::sanitizeDate($date);
     return $date === null ? '*' : $date;
 }
Exemple #15
0
 /**
  * Set up filters based on VuFind settings.
  *
  * @param array $filterList Filter settings
  *
  * @return void
  */
 public function initFilters($filterList)
 {
     // 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 = self::escapeParam($filt['value']);
                 // Special case -- "holdings only" is a separate parameter from
                 // other facets.
                 if ($filt['field'] == 'holdingsOnly') {
                     $this->setHoldings(strtolower(trim($safeValue)) == 'true');
                 } else {
                     if ($filt['field'] == 'excludeNewspapers') {
                         // Special case -- support a checkbox for excluding
                         // newspapers:
                         $this->addFilter("ContentType,Newspaper Article,true");
                     } else {
                         if ($range = SolrUtils::parseRange($filt['value'])) {
                             // Special case -- range query (translate [x TO y] syntax):
                             $from = self::escapeParam($range['from']);
                             $to = self::escapeParam($range['to']);
                             $this->addRangeFilter("{$filt['field']},{$from}:{$to}");
                         } else {
                             // Standard case:
                             $this->addFilter("{$filt['field']},{$safeValue}");
                         }
                     }
                 }
             }
         }
     }
 }
Exemple #16
0
 /**
  * Get the current settings for the specified range facet, if it is set:
  *
  * @param array  $fields      Fields to check
  * @param string $type        Type of range to include in return value
  * @param object $savedSearch Saved search object (false if none)
  *
  * @return array
  */
 protected function getRangeSettings($fields, $type, $savedSearch = false)
 {
     $parts = [];
     foreach ($fields as $field) {
         // Default to blank strings:
         $from = $to = '';
         // Check to see if there is an existing range in the search object:
         if ($savedSearch) {
             $filters = $savedSearch->getParams()->getFilters();
             if (isset($filters[$field])) {
                 foreach ($filters[$field] as $current) {
                     if ($range = SolrUtils::parseRange($current)) {
                         $from = $range['from'] == '*' ? '' : $range['from'];
                         $to = $range['to'] == '*' ? '' : $range['to'];
                         $savedSearch->getParams()->removeFilter($field . ':' . $current);
                         break;
                     }
                 }
             }
         }
         // Send back the settings:
         $parts[] = ['field' => $field, 'type' => $type, 'values' => [$from, $to]];
     }
     return $parts;
 }
Exemple #17
0
 /**
  * getDateFacets
  *
  * Return date facet information in a format processed for use in the view.
  *
  * @return array Array of from/to value arrays keyed by field.
  */
 public function getDateFacets()
 {
     $filters = $this->results->getParams()->getFilters();
     $result = array();
     foreach ($this->dateFacets as $current) {
         $from = $to = '';
         if (isset($filters[$current])) {
             foreach ($filters[$current] as $filter) {
                 if ($range = SolrUtils::parseRange($filter)) {
                     $from = $range['from'] == '*' ? '' : $range['from'];
                     $to = $range['to'] == '*' ? '' : $range['to'];
                     break;
                 }
             }
         }
         $result[$current] = array($from, $to);
     }
     return $result;
 }