diff --git a/code/solr/Solr.php b/code/solr/Solr.php
index e48eebe..53f0530 100644
--- a/code/solr/Solr.php
+++ b/code/solr/Solr.php
@@ -96,6 +96,12 @@ class Solr {
/** @var [SolrService_Core] - The instances of SolrService_Core for each core */
static protected $service_core_singletons = array();
+ /**
+ * Get a SolrService
+ *
+ * @param string $core Optional core name
+ * @return SolrService_Core
+ */
static function service($core = null) {
$options = self::solr_options();
@@ -143,58 +149,82 @@ class Solr {
class Solr_Configure extends BuildTask {
public function run($request) {
- $service = Solr::service();
+ // Find the IndexStore handler, which will handle uploading config files to Solr
+ $store = $this->getSolrConfigStore();
$indexes = Solr::get_indexes();
- $options = Solr::solr_options();
+ foreach ($indexes as $instance) {
+ try {
+ $this->updateIndex($instance, $store);
+ } catch(Exception $e) {
+ // We got an exception. Warn, but continue to next index.
+ $this->log("Failure: " . $e->getMessage());
+ }
+ }
+ }
+
+ /**
+ * Update the index on the given store
+ *
+ * @param SolrIndex $instance Instance
+ * @param SolrConfigStore $store
+ */
+ protected function updateIndex($instance, $store) {
+ $index = $instance->getIndexName();
+ $this->log("Configuring $index.");
+ $this->log("Uploading configuration ... ");
+
+
+ // Upload the config files for this index
+ $instance->uploadConfig($store);
+
+ // Then tell Solr to use those config files
+ $service = Solr::service();
+ if ($service->coreIsActive($index)) {
+ $this->log("Reloading core ...");
+ $service->coreReload($index);
+ } else {
+ $this->log("Creating core ...");
+ $service->coreCreate($index, $store->instanceDir($index));
+ }
+
+ $this->log("Done");
+ }
+
+ /**
+ * Get config store
+ *
+ * @return SolrConfigStore
+ */
+ protected function getSolrConfigStore() {
+ $options = Solr::solr_options();
+
if (!isset($options['indexstore']) || !($indexstore = $options['indexstore'])) {
user_error('No index configuration for Solr provided', E_USER_ERROR);
}
-
+
// Find the IndexStore handler, which will handle uploading config files to Solr
$mode = $indexstore['mode'];
if ($mode == 'file') {
- $store = new SolrConfigStore_File($indexstore);
+ return new SolrConfigStore_File($indexstore);
} elseif ($mode == 'webdav') {
- $store = new SolrConfigStore_WebDAV($indexstore);
+ return new SolrConfigStore_WebDAV($indexstore);
} elseif (ClassInfo::exists($mode) && ClassInfo::classImplements($mode, 'SolrConfigStore')) {
- $store = new $mode($indexstore);
+ return new $mode($indexstore);
} else {
user_error('Unknown Solr index mode '.$indexstore['mode'], E_USER_ERROR);
}
-
- foreach ($indexes as $instance) {
- $index = $instance->getIndexName();
- echo "Configuring $index. \n"; flush();
-
- try {
- // Upload the config files for this index
- echo "Uploading configuration ... \n"; flush();
-
- $store->uploadString($index, 'schema.xml', (string)$instance->generateSchema());
-
- foreach (glob($instance->getExtrasPath().'/*') as $file) {
- if (is_file($file)) $store->uploadFile($index, $file);
- }
-
- // Then tell Solr to use those config files
- if ($service->coreIsActive($index)) {
- echo "Reloading core ... \n";
- $service->coreReload($index);
- } else {
- echo "Creating core ... \n";
- $service->coreCreate($index, $store->instanceDir($index));
- }
-
- // And done
- echo "Done\n";
-
- } catch(Exception $e) {
- // We got an exception. Warn, but continue to next index.
- echo "Failure: " . $e->getMessage() . "\n"; flush();
- }
+
+ }
+
+ protected function log($message) {
+ if(Director::is_cli()) {
+ echo $message . "\n";
+ } else {
+ echo Convert::raw2xml($message) . "
";
}
+ flush();
}
}
diff --git a/code/solr/SolrIndex.php b/code/solr/SolrIndex.php
index 172e630..bea3b1d 100644
--- a/code/solr/SolrIndex.php
+++ b/code/solr/SolrIndex.php
@@ -141,6 +141,26 @@ abstract class SolrIndex extends SearchIndex {
return implode("\n\t\t", $xml);
}
+
+ /**
+ * Extract first suggestion text from collated values
+ *
+ * @param mixed $collation
+ * @return string
+ */
+ protected function getCollatedSuggestion($collation = '') {
+ if(is_string($collation)) {
+ return $collation;
+ }
+ if(is_object($collation)) {
+ if(isset($collation->misspellingsAndCorrections)) {
+ foreach($collation->misspellingsAndCorrections as $key => $value) {
+ return $value;
+ }
+ }
+ }
+ return '';
+ }
/**
* Extract a human friendly spelling suggestion from a Solr spellcheck collation string.
@@ -472,14 +492,18 @@ abstract class SolrIndex extends SearchIndex {
* @param SearchQuery $query
* @param integer $offset
* @param integer $limit
- * @param Array $params Extra request parameters passed through to Solr
+ * @param array $params Extra request parameters passed through to Solr
* @return ArrayData Map with the following keys:
* - 'Matches': ArrayList of the matched object instances
*/
public function search(SearchQuery $query, $offset = -1, $limit = -1, $params = array()) {
$service = $this->getService();
-
- SearchVariant::with(count($query->classes) == 1 ? $query->classes[0]['class'] : null)->call('alterQuery', $query, $this);
+
+ $searchClass = count($query->classes) == 1
+ ? $query->classes[0]['class']
+ : null;
+ SearchVariant::with($searchClass)
+ ->call('alterQuery', $query, $this);
$q = array(); // Query
$fq = array(); // Filter query
@@ -665,15 +689,18 @@ abstract class SolrIndex extends SearchIndex {
// Suggestions. Requires spellcheck.collate=true in $params
if(isset($res->spellcheck->suggestions->collation)) {
+ // Extract string suggestion
+ $suggestion = $this->getCollatedSuggestion($res->spellcheck->suggestions->collation);
+
// The collation, including advanced query params (e.g. +), suitable for making another query programmatically.
- $ret['Suggestion'] = $res->spellcheck->suggestions->collation;
+ $ret['Suggestion'] = $suggestion;
// A human friendly version of the suggestion, suitable for 'Did you mean $SuggestionNice?' display.
- $ret['SuggestionNice'] = $this->getNiceSuggestion($res->spellcheck->suggestions->collation);
+ $ret['SuggestionNice'] = $this->getNiceSuggestion($suggestion);
// A string suitable for appending to an href as a query string.
// For example $SuggestionNice
- $ret['SuggestionQueryString'] = $this->getSuggestionQueryString($res->spellcheck->suggestions->collation);
+ $ret['SuggestionQueryString'] = $this->getSuggestionQueryString($suggestion);
}
}
@@ -694,4 +721,25 @@ abstract class SolrIndex extends SearchIndex {
$this->service = $service;
return $this;
}
+
+ /**
+ * Upload config for this index to the given store
+ *
+ * @param SolrConfigStore $store
+ */
+ public function uploadConfig($store) {
+ // Upload the config files for this index
+ $store->uploadString(
+ $this->getIndexName(),
+ 'schema.xml',
+ (string)$this->generateSchema()
+ );
+
+ // Upload additional files
+ foreach (glob($this->getExtrasPath().'/*') as $file) {
+ if (is_file($file)) {
+ $store->uploadFile($this->getIndexName(), $file);
+ }
+ }
+ }
}
diff --git a/conf/solr/4/extras/solrconfig.xml b/conf/solr/4/extras/solrconfig.xml
index 60ae117..8e19810 100644
--- a/conf/solr/4/extras/solrconfig.xml
+++ b/conf/solr/4/extras/solrconfig.xml
@@ -863,6 +863,10 @@
nameOfCustomComponent2
-->
+
+
+ spellcheck
+
@@ -1254,7 +1258,31 @@
default
- text
+ _text
+ solr.DirectSolrSpellChecker
+
+ internal
+
+ 0.5
+
+ 2
+
+ 1
+
+ 5
+
+ 4
+
+ 0.01
+
+
+
+
+
+ _spellcheck
+ _spellcheckText
solr.DirectSolrSpellChecker
internal
@@ -1279,7 +1307,7 @@
wordbreak
solr.WordBreakSolrSpellChecker
- name
+ _text
true
true
10