From 2f6097898a5c057d11be9b6d55d67af535cf1539 Mon Sep 17 00:00:00 2001
From: Oliver Goldschmidt <o.goldschmidt@tuhh.de>
Date: Tue, 21 Apr 2015 09:32:59 -0400
Subject: [PATCH] prepares default filters to work with complex expressions -
 currently only works for Solr; Summon implementation probably possible with
 some variation.

---
 config/vufind/searches.ini                    |  4 +++
 .../VuFind/src/VuFind/Search/Base/Params.php  | 26 +++++++++++++++++++
 .../VuFind/src/VuFind/Search/Solr/Params.php  |  7 +++--
 3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/config/vufind/searches.ini b/config/vufind/searches.ini
index 9c0922189e3..3b99fce01db 100644
--- a/config/vufind/searches.ini
+++ b/config/vufind/searches.ini
@@ -77,11 +77,15 @@ retain_filters_by_default = true
 ; this setting to have no default filters applied. These differ from hidden
 ; filters because they are visible in the UI and may be removed by the user.
 ;
+; You can use complex filters (for example with boolean operators inside).
+; In order to do that, just set the filter into parentheses (as in the third sample line).
+;
 ; NOTE: If you are setting a default filter on a field that is used for OR
 ; facets (see the orFacets setting in facets.ini), be sure to prefix the field
 ; name with a tilde (~)... e.g. "~format:Book"
 ;default_filters[] = "format:Book"
 ;default_filters[] = "institution:MyInstitution"
+;default_filters[] = "(format:Book AND institution:MyInstitution)"
 
 [Cache]
 ; This controls whether the parsed searchspecs.yaml file will be stored to
diff --git a/module/VuFind/src/VuFind/Search/Base/Params.php b/module/VuFind/src/VuFind/Search/Base/Params.php
index eec7e04b08c..97b7c72cb97 100644
--- a/module/VuFind/src/VuFind/Search/Base/Params.php
+++ b/module/VuFind/src/VuFind/Search/Base/Params.php
@@ -844,6 +844,13 @@ class Params implements ServiceLocatorAwareInterface
      */
     public function parseFilter($filter)
     {
+        // Special case: complex filters cannot be split into field/value
+        // since they have multiple parts (e.g. field1:a OR field2:b). Use
+        // a fake "#" field to collect these types of filters.
+        if ($this->isAdvancedFilter($filter) == true) {
+            return ['#', $filter];
+        }
+
         // Split the string and assign the parts to $field and $value
         $temp = explode(':', $filter, 2);
         $field = array_shift($temp);
@@ -901,6 +908,25 @@ class Params implements ServiceLocatorAwareInterface
         }
     }
 
+    /**
+     * Detects if a filter is advanced (true) or simple (false). An advanced
+     * filter is currently defined as one surrounded by parentheses, while a
+     * simple filter is of the form field:value. Advanced filters are used to
+     * express more complex queries, such as combining multiple values from
+     * multiple fields using boolean operators.
+     *
+     * @param string $filter A filter string
+     *
+     * @return bool
+     */
+    public function isAdvancedFilter($filter)
+    {
+        if (substr($filter, 0, 1) == '(') {
+            return true;
+        }
+        return false;
+    }
+
     /**
      * Remove a filter from the list.
      *
diff --git a/module/VuFind/src/VuFind/Search/Solr/Params.php b/module/VuFind/src/VuFind/Search/Solr/Params.php
index 4d586f2ab2e..b85c7950a25 100644
--- a/module/VuFind/src/VuFind/Search/Solr/Params.php
+++ b/module/VuFind/src/VuFind/Search/Solr/Params.php
@@ -108,10 +108,13 @@ class Params extends \VuFind\Search\Base\Params
                 $field = substr($field, 1);
             }
             foreach ($filter as $value) {
-                // Special case -- allow trailing wildcards and ranges:
-                if (substr($value, -1) == '*'
+                // Special case -- complex filter, that should be taken as-is:
+                if ($field == '#') {
+                    $q = $value;
+                } else if (substr($value, -1) == '*'
                     || preg_match('/\[[^\]]+\s+TO\s+[^\]]+\]/', $value)
                 ) {
+                    // Special case -- allow trailing wildcards and ranges
                     $q = $field . ':' . $value;
                 } else {
                     $q = $field . ':"' . addcslashes($value, '"\\') . '"';
-- 
GitLab