### Eclipse Workspace Patch 1.0
#P vufind
Index: web/sys/Solr.php
===================================================================
--- web/sys/Solr.php	(revision 3015)
+++ web/sys/Solr.php	(working copy)
@@ -83,7 +83,9 @@
      * case-insensitive (false), or must they be ALL UPPERCASE (true)?
      */
     private $caseSensitiveBooleans = true;
-    
+
+    private $solrShards = array();
+
     /**
      * Constructor
      *
@@ -101,7 +103,7 @@
             $index = isset($configArray['Index']['default_core']) ? 
                 $configArray['Index']['default_core'] : "biblio";
         }
-     
+
         $this->host = $host . '/' . $index;
 
         // Test to see solr is online
@@ -128,6 +130,17 @@
             $this->caseSensitiveBooleans = 
                 $searchSettings['General']['case_sensitive_bools'];
         }
+
+        // Deal with session-based shard settings:
+        if (isset($_SESSION['shards'])) {
+            $shards = array();
+            foreach($_SESSION['shards'] as $current) {
+                if (isset($configArray['IndexShards'][$current])) {
+                    $shards[$current] = $configArray['IndexShards'][$current];
+                }
+            }
+            $this->setShards($shards);
+        }
     }
 
     /**
@@ -915,6 +928,59 @@
     }
 
     /**
+     * Set the shards for distributed search
+     * 
+     * @param   array       $shards             Name => URL array of shards
+     */
+    public function setShards($shards) {
+        $this->solrShards = $shards;
+    }
+
+    /**
+     * Strip facet settings that are illegal due to shard settings.
+     *
+     * @param   array       $value              Current facet.field setting
+     * @return  array                           Filtered facet.field setting
+     */
+    private function stripUnwantedFacets($value)
+    {
+        // Load the configuration of facets to strip and build a list of the ones
+        // that currently apply:
+        $facetConfig = getExtraConfigArray('facets');
+        $badFacets = array();
+        if (!empty($this->solrShards) && is_array($this->solrShards) && 
+            isset($facetConfig['StripFacets']) &&
+            is_array($facetConfig['StripFacets'])) {
+            $shardNames = array_keys($this->solrShards);
+            foreach ($facetConfig['StripFacets'] as $indexName => $facets) {
+                if (in_array($indexName, $shardNames) === true) {
+                    $badFacets = array_merge($badFacets, explode(",", $facets));
+                }
+            }
+        }
+
+        // No bad facets means no filtering necessary:
+        if (empty($badFacets)) {
+            return $value;
+        }
+
+        // Ensure that $value is an array:
+        if (!is_array($value)) {
+            $value = array($value);
+        }
+
+        // Rebuild the $value array, excluding all unwanted facets:
+        $newValue = array();
+        foreach($value as $current) {
+            if (!in_array($current, $badFacets)) {
+                $newValue[] = $current;
+            }
+        }
+
+        return $newValue;
+    }
+
+    /**
      * Submit REST Request to read data
      *
      * @param   string      $method             HTTP Method to use: GET, POST, 
@@ -939,6 +1005,15 @@
         if ($params) {
             foreach ($params as $function => $value) {
                 if ($function != '') {
+                    // Strip custom FacetFields when sharding makes it necessary:
+                    if ($function === 'facet.field') {
+                        $value = $this->stripUnwantedFacets($value);
+
+                        // If we stripped all values, skip the parameter:
+                        if (empty($value)) {
+                            continue;
+                        }
+                    }
                     if(is_array($value)) {
                         foreach ($value as $additional) {
                             $additional = urlencode($additional);
@@ -951,6 +1026,10 @@
                 }
             }
         }
+        if (!empty($this->solrShards) && is_array($this->solrShards)) {
+            // strip custom FacetField since its not in other indices
+            $query[] = 'shards=' . urlencode(implode(',', $this->solrShards));
+        }
         $queryString = implode('&', $query);
 
         if ($this->debug) {
Index: web/index.php
===================================================================
--- web/index.php	(revision 3036)
+++ web/index.php	(working copy)
@@ -159,6 +159,9 @@
     processFollowup();
 }
 
+// Process Solr shard settings
+processShards();
+
 // Call Action
 if (is_readable("services/$module/$action.php")) {
     require_once "services/$module/$action.php";
@@ -198,6 +201,42 @@
     }
 }
 
+function processShards()
+{
+    global $configArray;
+    global $interface;
+
+    // If shards are not configured, give up now:
+    if (!isset($configArray['IndexShards']) || empty($configArray['IndexShards'])) {
+        return;
+    }
+
+    // If a shard selection list is found as an incoming parameter, we should save
+    // it in the session for future reference:
+    if (array_key_exists('shard', $_REQUEST)) {
+        $_SESSION['shards'] = $_REQUEST['shard'];
+    // If no selection list was passed in, select the shards configured in ShardPreferences by default:
+    } else if (!array_key_exists('shards', $_SESSION)) {
+    	if (isset($configArray['ShardPreferences']['defaultChecked']) && !empty($configArray['ShardPreferences']['defaultChecked'])) {
+    		$checkedShards = explode(',', $configArray['ShardPreferences']['defaultChecked']);
+    		$_SESSION['shards'] = $checkedShards;
+    	}
+        else {
+            $_SESSION['shards'] = array_keys($configArray['IndexShards']);
+        }
+    }
+
+    // If we are configured to use shards, send a list of shards to the interface,
+    // with keys being shard names and values being a boolean value indicating
+    // whether or not the shard is currently selected.
+    $shards = array();
+    foreach ($configArray['IndexShards'] as $shardName => $shardAddress) {
+        $shards[$shardName] = in_array($shardName, $_SESSION['shards']);
+    }
+
+    $interface->assign('shards', $shards);
+}
+
 // Process any errors that are thrown
 function handlePEARError($error, $method = null)
 {
Index: web/interface/themes/default/Search/searchbox.tpl
===================================================================
--- web/interface/themes/default/Search/searchbox.tpl	(revision 3036)
+++ web/interface/themes/default/Search/searchbox.tpl	(working copy)
@@ -24,6 +24,11 @@
           {/if}
         {/foreach}
       {/if}
+      {if $shards}
+        {foreach from=$shards key=shard item=isSelected}
+          <input type="checkbox" {if $isSelected}checked="checked" {/if}name="shard[]" value='{$shard|escape}' /> {$shard|escape}
+        {/foreach}
+      {/if}
       {if $filterList || $hasCheckboxFilters}
         <div class="keepFilters">
           <input type="checkbox" checked="checked" onclick="filterAll(this);" /> {translate text="basic_search_keep_filters"}
Index: web/conf/facets.ini
===================================================================
--- web/conf/facets.ini	(revision 3036)
+++ web/conf/facets.ini	(working copy)
@@ -22,6 +22,14 @@
 [ResultsTop]
 topic_facet        = "Suggested Topics"
 
+; Facets must be stripped if you have a facet in your main index which is missing
+; from any index includable by shards.  This section can be ignored if you are
+; not using sharding or if all of your shards have identical schemas.
+;
+; Put in the facets to strip here in the following format:
+; shard name = fieldname,another fieldname,...
+[StripFacets]
+
 ; This section is reserved for special boolean facets.  These are displayed
 ; as checkboxes.  If the box is checked, the filter on the left side of the
 ; equal sign is applied.  If the box is not checked, the filter is not applied.
Index: web/sys/SearchObject/Solr.php
===================================================================
--- web/sys/SearchObject/Solr.php	(revision 3036)
+++ web/sys/SearchObject/Solr.php	(working copy)
@@ -909,6 +909,11 @@
         // this null in order to achieve the desired effect with Solr:
         $finalSort = ($this->sort == 'relevance') ? null : $this->sort;
 
+        // Load additional indices for distributed search
+        if (isset($_SESSION['shards'])) {
+            $this->fields = '*,score';
+        }
+
         // The first record to retrieve:
         //  (page - 1) * limit = start
         $recordStart = ($this->page - 1) * $this->limit;
Index: web/conf/config.ini
===================================================================
--- web/conf/config.ini	(revision 3036)
+++ web/conf/config.ini	(working copy)
@@ -87,6 +87,23 @@
 local           = /usr/local/vufind/solr
 default_core    = biblio
 
+; This section allows sharding to be used to pull in content from additional Solr
+; servers.  All servers used in sharding must contain the same index fields needed
+; to satisfy queries sent to them!  Leave this commented out to disable sharding.
+; To use sharding, simply fill in lines using the format:
+; [display name of shard] = [URL of shard (without http://)]
+;[IndexShards]
+;Library Catalog = localhost:8080/solr/biblio
+;Weblog = localhost:8080/solr/weblog
+;Website = localhost:8080/solr/website
+
+; This section allows to set preferences for shards display
+; You only need to set these if you want to use shards
+; You can choose which shards should be checked by default on start page in a comma seperated list
+;[ShardPreferences]
+;defaultChecked = Library Catalog,Weblog,Website
+
+
 ; This section requires no changes for most installations; if your SMTP server
 ; requires authentication, you can fill in a username and password below.
 [Mail]

