NEW SearchIndex->excludeVariantState()

This commit is contained in:
Ingo Schommer 2012-08-28 23:21:51 +02:00
parent 2a3e882d70
commit 50304e4b0c
5 changed files with 81 additions and 2 deletions

View File

@ -169,6 +169,8 @@ abstract class SearchIndex extends ViewableData {
protected $sortFields = array();
protected $excludedVariantStates = array();
/**
* Add a DataObject subclass whose instances should be included in this index
*
@ -258,6 +260,23 @@ abstract class SearchIndex extends ViewableData {
return new MultipleArrayIterator($this->fulltextFields, $this->filterFields, $this->sortFields);
}
public function excludeVariantState($state) {
$this->excludedVariantStates[] = $state;
}
/** Returns true if some variant state should be ignored */
public function variantStateExcluded($state) {
foreach ($this->excludedVariantStates as $excludedstate) {
$matches = true;
foreach ($excludedstate as $variant => $variantstate) {
if (!isset($state[$variant]) || $state[$variant] != $variantstate) { $matches = false; break; }
}
if ($matches) return true;
}
}
public $dependancyList = array();
function buildDependancyList() {

View File

@ -250,12 +250,22 @@ class SearchUpdater extends Object {
$objs = DataObject::get($base, '"'.$base.'"."ID" IN ('.implode(',', array_keys($ids)).')');
if ($objs) foreach ($objs as $obj) {
foreach ($ids[$obj->ID] as $index) { $indexes[$index]->add($obj); $dirtyindexes[$index] = $index; }
foreach ($ids[$obj->ID] as $index) {
if (!$indexes[$index]->variantStateExcluded($state)) {
$indexes[$index]->add($obj);
$dirtyindexes[$index] = $index;
}
}
unset($ids[$obj->ID]);
}
foreach ($ids as $id => $fromindexes) {
foreach ($fromindexes as $index) { $indexes[$index]->delete($base, $id, $state); $dirtyindexes[$index] = $index; }
foreach ($fromindexes as $index) {
if (!$indexes[$index]->variantStateExcluded($state)) {
$indexes[$index]->delete($base, $id, $state);
$dirtyindexes[$index] = $index;
}
}
}
}
}

View File

@ -183,6 +183,8 @@ class Solr_Reindex extends BuildTask {
$includeSubclasses = $options['include_children'];
foreach (SearchVariant::reindex_states($class, $includeSubclasses) as $state) {
if ($instance->variantStateExcluded($state)) continue;
SearchVariant::activate_state($state);
$filter = $includeSubclasses ? "" : '"ClassName" = \''.$class."'";

View File

@ -88,3 +88,24 @@ See Solr.md
### Sphinx
Not written yet
## FAQ
### How do I exclude draft pages from the index?
By default, the `SearchUpdater` class indexes all available "variant states",
so in the case of the `Versioned` extension, both "draft" and "live".
For most cases, you'll want to exclude draft content from your search results.
You can either prevent the draft content from being indexed in the first place,
by adding the following to your `SearchIndex->init()` method:
$this->excludeVariantState(array('SearchVariantVersioned' => 'Stage'));
Alternatively, you can index draft content, but simply exclude it from searches.
This can be handy to preview search results on unpublished content, in case a CMS author is logged in.
Before constructing your `SearchQuery`, conditionally switch to the "live" stage:
if(!Permission::check('CMS_ACCESS_CMSMain')) Versioned::reading_stage('Live');
$query = new SearchQuery();
// ...

View File

@ -14,6 +14,14 @@ class SearchVariantVersionedTest_Index extends SearchIndex_Recording {
}
}
class SearchVariantVersionedTest_IndexNoStage extends SearchIndex_Recording {
function init() {
$this->addClass('SearchVariantVersionedTest_Item');
$this->addFilterField('TestText');
$this->excludeVariantState(array('SearchVariantVersioned' => 'Stage'));
}
}
class SearchVariantVersionedTest extends SapphireTest {
private static $index = null;
@ -68,4 +76,23 @@ class SearchVariantVersionedTest extends SapphireTest {
array('ID' => $item->ID, '_versionedstage' => 'Stage')
));
}
function testExcludeVariantState() {
$index = singleton('SearchVariantVersionedTest_IndexNoStage');
FullTextSearch::force_index_list($index);
// Check that write doesn't update stage
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Foo'));
$item->write();
SearchUpdater::flush_dirty_indexes();
$this->assertEquals($index->getAdded(array('ID', '_versionedstage')), array());
// Check that publish updates Live
$index->reset();
$item->publish("Stage", "Live");
SearchUpdater::flush_dirty_indexes();
$this->assertEquals($index->getAdded(array('ID', '_versionedstage')), array(
array('ID' => $item->ID, '_versionedstage' => 'Live')
));
}
}