Merge branch '3'

This commit is contained in:
Dan Hensby 2020-04-17 22:11:40 +01:00
commit c0b818fc49
No known key found for this signature in database
GPG Key ID: F76D6B5FE0626A99
16 changed files with 520 additions and 28 deletions

View File

@ -8,15 +8,15 @@ env:
matrix:
include:
- php: 5.6
- php: 7.1
env: DB=MYSQL INSTALLER_VERSION=4.2.x-dev PHPCS_TEST=1 PHPUNIT_TEST=1
- php: 7.0
- php: 7.1
env: DB=PGSQL INSTALLER_VERSION=4.3.x-dev PHPUNIT_TEST=1
- php: 7.1
env: DB=MYSQL INSTALLER_VERSION=4.3.x-dev PHPUNIT_COVERAGE_TEST=1
- php: 7.1
env: DB=MYSQL INSTALLER_VERSION=4.4.x-dev PHPUNIT_TEST=1 SUBSITES=1
- php: 7.2
env: DB=MYSQL INSTALLER_VERSION=4.3.x-dev PHPUNIT_COVERAGE_TEST=1
- php: 7.3
env: DB=MYSQL INSTALLER_VERSION=4.4.x-dev PHPUNIT_TEST=1 SUBSITES=1
- php: 7.3
env: DB=MYSQL INSTALLER_VERSION=4.x-dev PHPUNIT_TEST=1
before_script:

View File

@ -21,6 +21,7 @@
}
],
"require": {
"php": ">=7.1",
"silverstripe/framework": "^4.0",
"monolog/monolog": "~1.15",
"ptcinc/solr-php-client": "^1.0",

View File

@ -147,7 +147,7 @@ to render properly in the search results:
* `Link()` needs to return the URL to follow from the search results to actually view the object.
* `Name` (as a DB field) will be used as the result title.
* `Abstract` (as a DB field) will show under the search result title.
* `getShowInSearch()` is required to get the record to show in search, since all results are filtered by `ShowInSearch`.
* `ShowInSearch` (as a DB field) or `getShowInSearch()` is recommended to allow the optional exclusion of DataObjects from being added to the search index. If omitted, then all DataObjects of this type will be added to the search index.
So with that, you can add your class to your index:
@ -172,6 +172,28 @@ you've just created, this will add `SearchableDataObject` and the text fields it
on the site using `MySolrSearchIndex->search()`, the `SearchableDataObject` results will show alongside normal `Page`
results.
### ShowInSearch and getShowInSearch() filtering
The fulltextsearch module checks the value of `ShowInSearch` on each object it operates against, and if this evaluates
to `false`, the object is excluded from the index / results. You can implement a `getShowInSearch` method on your
DataObject to control the way this is computed. This check happens in two places:
a) When attempting to add the object to the search index (or update it)
b) Before returning results from the search index. Note: this only applies to Solr 4 implementations.
The second check is an additional layer to ensure that a result is excluded if the evaluated response changes between
index and query time. For example, a getShowInSearch() implementation that filters out objects after a certain date
might return `true` when the object is added to the index, but `false` when a user later performs a search.
This filtering is applied to all Page (SiteTree) and File records since they have a ShowInSearch database column.
This will also be applied to any DataObjects that have a ShowInSearch database column or a getShowInSearch() function.
This is a compulsory check and there is no opt-out available.
Note: If you implement a custom getShowInSearch() method on a Page, the database column 'ShowInSearch' will not be used
and the 'Show In Search?' settings in the CMS admin found under Page > Settings will no longer work. Either incorporate
the ShowInSearch column in your getShowInSearch() logic, or remove the field from the CMS to minimise confusion.
## Solr dev tasks
There are two dev/tasks that are central to the operation of the module - `Solr_Configure` and `Solr_Reindex`. You can access these through the web, or via CLI. Running via the web will return "quiet" output by default, but you can increase verbosity by adding `?verbose=1` to the `dev/tasks` URL; CLI will return verbose output by default.

View File

@ -619,19 +619,14 @@ abstract class SearchIndex extends ViewableData
$tableName = DataObject::getSchema()->tableName($step['class']);
if ($step['through'] == 'has_one') {
$sql = new SQLSelect('"ID"', '"' . $tableName . '"', '"' . $step['foreignkey'] . '" IN (' . implode(',', $ids) . ')');
singleton($step['class'])->extend('augmentSQL', $sql);
$ids = $sql->execute()->column();
$ids = DataObject::get($step['class'])
->filter($step['foreignkey'], $ids)
->column('ID');
} elseif ($step['through'] == 'has_many') {
// Use TableName for queries
$otherTableName = DataObject::getSchema()->tableName($step['otherclass']);
$sql = new SQLSelect('"' . $tableName . '"."ID"', '"' . $tableName . '"', '"' . $otherTableName . '"."ID" IN (' . implode(',', $ids) . ')');
$sql->addInnerJoin($otherTableName, '"' . $tableName . '"."ID" = "' . $otherTableName . '"."' . $step['foreignkey'] . '"');
singleton($step['class'])->extend('augmentSQL', $sql);
$ids = $sql->execute()->column();
// foreignkey identifies a has_one column on the model linked via the has_many relation
$ids = DataObject::get($step['otherclass'])
->filter('ID', $ids)
->column($step['foreignkey']);
}
if (empty($ids)) {

View File

@ -2,6 +2,7 @@
namespace SilverStripe\FullTextSearch\Search\Processors;
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
use SilverStripe\ORM\DataObject;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
use SilverStripe\FullTextSearch\Search\FullTextSearch;
@ -71,6 +72,7 @@ abstract class SearchUpdateProcessor
$dirtyIndexes = array();
$dirty = $this->getSource();
$indexes = FullTextSearch::get_indexes();
$indexableService = IndexableService::singleton();
foreach ($dirty as $base => $statefulids) {
if (!$statefulids) {
continue;
@ -87,7 +89,12 @@ abstract class SearchUpdateProcessor
foreach ($objs as $obj) {
foreach ($ids[$obj->ID] as $index) {
if (!$indexes[$index]->variantStateExcluded($state)) {
$indexes[$index]->add($obj);
// Remove any existing records from index if ShowInSearch is changed to false
if (!$indexableService->isIndexable($obj)) {
$indexes[$index]->delete($base, $obj->ID, $state);
} else {
$indexes[$index]->add($obj);
}
$dirtyIndexes[$index] = $indexes[$index];
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace SilverStripe\FullTextSearch\Search\Services;
use SilverStripe\Core\Extensible;
use SilverStripe\Core\Injector\Injectable;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\Tests\MySQLDatabaseTest\Data;
/**
* Checks if a DataObject is publically viewable thus able to be added or retrieved from a publically searchable index
* Caching results because these checks may be done multiple times as there a few different code paths that search
* results might follow in real-world search implementations
*/
class IndexableService
{
use Injectable;
use Extensible;
protected $cache = [];
public function clearCache(): void
{
$this->cache = [];
}
public function isIndexable(DataObject $obj): bool
{
// check if is a valid DataObject that has been persisted to the database
if (is_null($obj) || !$obj->ID) {
return false;
}
$key = $this->getCacheKey($obj);
if (isset($this->cache[$key])) {
return $this->cache[$key];
}
$value = true;
// This will also call $obj->getShowInSearch() if it exists
if (isset($obj->ShowInSearch) && !$obj->ShowInSearch) {
$value = false;
}
$this->extend('updateIsIndexable', $obj, $value);
$this->cache[$key] = $value;
return $value;
}
protected function getCacheKey(DataObject $obj): string
{
$key = $obj->ClassName . '_' . $obj->ID;
$this->extend('updateCacheKey', $obj, $key);
return $key;
}
}

View File

@ -9,6 +9,7 @@ use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\TextField;
use SilverStripe\FullTextSearch\Search\FullTextSearch;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
use SilverStripe\FullTextSearch\Solr\SolrIndex;
use SilverStripe\ORM\DataObject;
use SilverStripe\View\ArrayData;
@ -82,11 +83,13 @@ class SearchForm extends Form
$index = $indexClass::singleton();
$results = $index->search($query, -1, -1, $params);
$indexableService = IndexableService::singleton();
// filter by permission
if ($results) {
foreach ($results->Matches as $match) {
/** @var DataObject $match */
if (!$match->canView()) {
if (!$indexableService->isIndexable($match)) {
$results->Matches->remove($match);
}
}

View File

@ -4,6 +4,7 @@ namespace SilverStripe\FullTextSearch\Solr\Reindex\Handlers;
use Psr\Log\LoggerInterface;
use SilverStripe\Core\Environment;
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
use SilverStripe\FullTextSearch\Solr\Solr;
use SilverStripe\FullTextSearch\Solr\SolrIndex;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
@ -220,6 +221,7 @@ abstract class SolrReindexBase implements SolrReindexHandler
{
// Generate filtered list of local records
$baseClass = DataObject::getSchema()->baseDataClass($class);
/** @var DataList $items */
$items = DataList::create($class)
->where(sprintf(
'"%s"."ID" %% \'%d\' = \'%d\'',
@ -236,6 +238,20 @@ abstract class SolrReindexBase implements SolrReindexHandler
$items = $items->filter('ClassName', $class);
}
$indexableService = IndexableService::singleton();
// ShowInSearch filter
// we cannot use $items->remove($item), as that deletes the record from the database
$idsToRemove = [];
foreach ($items as $item) {
if (!$indexableService->isIndexable($item)) {
$idsToRemove[] = $item->ID;
}
}
if (!empty($idsToRemove)) {
sort($idsToRemove);
$items = $items->exclude(['ID' => $idsToRemove]);
}
return $items;
}

View File

@ -9,6 +9,7 @@ use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery_Range;
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant_Caller;
use SilverStripe\FullTextSearch\Solr\Services\SolrService;
@ -777,11 +778,18 @@ abstract class SolrIndex extends SearchIndex
\Apache_Solr_Service::METHOD_POST
);
$indexableService = IndexableService::singleton();
$results = new ArrayList();
if ($res->getHttpStatus() >= 200 && $res->getHttpStatus() < 300) {
foreach ($res->response->docs as $doc) {
$result = DataObject::get_by_id($doc->ClassName, $doc->ID);
if ($result) {
// Filter out any results previously added to the solr index where ShowInSearch == false
if (!$indexableService->isIndexable($result)) {
continue;
}
$results->push($result);
// Add highlighting (optional)

View File

@ -0,0 +1,55 @@
<?php
namespace SilverStripe\FullTextSearch\Tests;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
class IndexableServiceTest extends SapphireTest
{
protected $usesDatabase = true;
public function setup()
{
parent::setup();
IndexableService::singleton()->clearCache();
}
public function testIsIndexable()
{
$indexableService = IndexableService::singleton();
$page = SiteTree::create();
$page->CanViewType = 'Anyone';
$page->ShowInSearch = 1;
$page->write();
$this->assertTrue($indexableService->isIndexable($page));
$page = SiteTree::create();
$page->CanViewType = 'Anyone';
$page->ShowInSearch = 0;
$page->write();
$this->assertFalse($indexableService->isIndexable($page));
}
public function testClearCache()
{
$indexableService = IndexableService::singleton();
$page = SiteTree::create();
$page->CanViewType = 'Anyone';
$page->ShowInSearch = 0;
$page->write();
$this->assertFalse($indexableService->isIndexable($page));
// test the results are cached (expect stale result)
$page->ShowInSearch = 1;
$page->write();
$this->assertFalse($indexableService->isIndexable($page));
// after clearing cache, expect fresh result
$indexableService->clearCache();
$this->assertTrue($indexableService->isIndexable($page));
}
}

View File

@ -2,15 +2,24 @@
namespace SilverStripe\FullTextSearch\Tests;
use Apache_Solr_Document;
use Page;
use SebastianBergmann\Version;
use SilverStripe\Assets\File;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Environment;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Kernel;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\FullTextSearch\Search\FullTextSearch;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Search\Services\IndexableService;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites;
use SilverStripe\FullTextSearch\Solr\SolrIndex;
use SilverStripe\FullTextSearch\Solr\Services\Solr3Service;
use SilverStripe\FullTextSearch\Solr\Services\Solr4Service;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasOne;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasMany;
@ -21,10 +30,25 @@ use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelat
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_BoostedIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex2;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_ShowInSearchIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyPage;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyDataObjectOne;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyDataObjectTwo;
use SilverStripe\ORM\DataObject;
use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\Versioned\Versioned;
class SolrIndexTest extends SapphireTest
{
protected $usesDatabase = true;
protected static $extra_dataobjects = [
SolrIndexTest_MyPage::class,
SolrIndexTest_MyDataObjectOne::class,
SolrIndexTest_MyDataObjectTwo::class,
];
public function testFieldDataHasOne()
{
$index = new SolrIndexTest_FakeIndex();
@ -376,6 +400,125 @@ class SolrIndexTest extends SapphireTest
);
}
/**
* Test that ShowInSearch and getShowInSearch() exclude DataObjects from being added to the index
*
* Note: this code path that really being tested here is SearchUpdateProcessor->prepareIndexes()
* This code path is used for 'inlet' filtering on CMS->save()
* The results of this will show-up in SolrIndex->_addAs()
*/
public function testShowInSearch()
{
$defaultMode = Versioned::get_reading_mode();
Versioned::set_reading_mode('Stage.' . Versioned::DRAFT);
$serviceMock = $this->getMockBuilder(Solr4Service::class)
->setMethods(['addDocument', 'deleteById'])
->getMock();
$index = new SolrIndexTest_ShowInSearchIndex();
$index->setService($serviceMock);
FullTextSearch::force_index_list($index);
// will get added
$pageA = new Page();
$pageA->Title = 'Test Page true';
$pageA->ShowInSearch = true;
$pageA->write();
// will get filtered out
$page = new Page();
$page->Title = 'Test Page false';
$page->ShowInSearch = false;
$page->write();
// will get added
$fileA = new File();
$fileA->Title = 'Test File true';
$fileA->ShowInSearch = true;
$fileA->write();
// will get filtered out
$file = new File();
$file->Title = 'Test File false';
$file->ShowInSearch = false;
$file->write();
// will get added
$objOneA = new SolrIndexTest_MyDataObjectOne();
$objOneA->Title = 'Test MyDataObjectOne true';
$objOneA->ShowInSearch = true;
$objOneA->write();
// will get filtered out
$objOne = new SolrIndexTest_MyDataObjectOne();
$objOne->Title = 'Test MyDataObjectOne false';
$objOne->ShowInSearch = false;
$objOne->write();
// will get added
// this class has a getShowInSearch() == true, which will override $mypage->ShowInSearch = false
$objTwoA = new SolrIndexTest_MyDataObjectTwo();
$objTwoA->Title = 'Test MyDataObjectTwo false';
$objTwoA->ShowInSearch = false;
$objTwoA->write();
// will get added
// this class has a getShowInSearch() == true, which will override $mypage->ShowInSearch = false
$myPageA = new SolrIndexTest_MyPage();
$myPageA->Title = 'Test MyPage false';
$myPageA->ShowInSearch = false;
$myPageA->write();
$callback = function (Apache_Solr_Document $doc) use ($pageA, $myPageA, $fileA, $objOneA, $objTwoA): bool {
$validKeys = [
Page::class . $pageA->ID,
SolrIndexTest_MyPage::class . $myPageA->ID,
File::class . $fileA->ID,
SolrIndexTest_MyDataObjectOne::class . $objOneA->ID,
SolrIndexTest_MyDataObjectTwo::class . $objTwoA->ID
];
return in_array($this->createSolrDocKey($doc), $validKeys);
};
$serviceMock
->expects($this->exactly(5))
->method('addDocument')
->withConsecutive(
[$this->callback($callback)],
[$this->callback($callback)],
[$this->callback($callback)],
[$this->callback($callback)],
[$this->callback($callback)]
);
// This is what actually triggers all the solr stuff
SearchUpdater::flush_dirty_indexes();
// delete a solr doc by setting ShowInSearch to false
$pageA->ShowInSearch = false;
$pageA->write();
$serviceMock
->expects($this->exactly(1))
->method('deleteById')
->withConsecutive(
[$this->callback(function (string $docID) use ($pageA): bool {
return strpos($docID, $pageA->ID . '-' . SiteTree::class) !== false;
})]
);
IndexableService::singleton()->clearCache();
SearchUpdater::flush_dirty_indexes();
Versioned::set_reading_mode($defaultMode);
}
protected function createSolrDocKey(Apache_Solr_Document $doc)
{
return $doc->getField('ClassName')['value'] . $doc->getField('ID')['value'];
}
protected function getFakeRawSolrResponse()
{
return new \Apache_Solr_Response(

View File

@ -0,0 +1,16 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
class SolrIndexTest_MyDataObjectOne extends DataObject implements TestOnly
{
private static $db = [
'Title' => 'Varchar(255)',
'ShowInSearch' => 'Boolean'
];
private static $table_name = 'SolrIndexTestMyDataObjectOne';
}

View File

@ -0,0 +1,16 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
use SilverStripe\Dev\TestOnly;
use SilverStripe\ORM\DataObject;
class SolrIndexTest_MyDataObjectTwo extends SolrIndexTest_MyDataObjectOne implements TestOnly
{
private static $table_name = 'SolrIndexTestMyDataObjectTwo';
public function getShowInSearch()
{
return true;
}
}

View File

@ -0,0 +1,14 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
use Page;
use SilverStripe\Dev\TestOnly;
class SolrIndexTest_MyPage extends Page implements TestOnly
{
public function getShowInSearch()
{
return true;
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
use SilverStripe\Assets\File;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Dev\TestOnly;
use SilverStripe\FullTextSearch\Solr\SolrIndex;
class SolrIndexTest_ShowInSearchIndex extends SolrIndex implements TestOnly
{
public function init()
{
// adding a class here includes will include all subclasses, e.g. SolrIndexTest_MyDataObjectTwo
$this->addClass(SolrIndexTest_MyDataObjectOne::class);
$this->addClass(SiteTree::class);
$this->addClass(File::class);
$this->addFilterField('ShowInSearch');
}
}

View File

@ -2,27 +2,43 @@
namespace SilverStripe\FullTextSearch\Tests;
use Apache_Solr_Document;
use Page;
use SilverStripe\Assets\File;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\FullTextSearch\Search\FullTextSearch;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantVersioned;
use SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexHandler;
use SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexImmediateHandler;
use SilverStripe\FullTextSearch\Solr\Services\Solr4Service;
use SilverStripe\FullTextSearch\Solr\Services\SolrService;
use SilverStripe\FullTextSearch\Solr\Tasks\Solr_Reindex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyDataObjectOne;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyDataObjectTwo;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_MyPage;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_ShowInSearchIndex;
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Index;
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Item;
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_RecordingLogger;
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_TestHandler;
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Variant;
use SilverStripe\Versioned\Versioned;
class SolrReindexTest extends SapphireTest
{
protected $usesDatabase = true;
protected static $extra_dataobjects = array(
SolrReindexTest_Item::class
SolrReindexTest_Item::class,
SolrIndexTest_MyPage::class,
SolrIndexTest_MyDataObjectOne::class,
SolrIndexTest_MyDataObjectTwo::class,
);
/**
@ -153,7 +169,6 @@ class SolrReindexTest extends SapphireTest
$this->assertEquals(240, SolrReindexTest_Item::get()->count());
}
/**
* Given the invocation of a new re-index with a given set of data, ensure that the necessary
* list of groups are created and segmented for each state
@ -284,4 +299,107 @@ class SolrReindexTest extends SapphireTest
// Check ids
$this->assertEquals(120, count($ids));
}
/**
* Test that ShowInSearch filtering is working correctly
*/
public function testShowInSearch()
{
$defaultMode = Versioned::get_reading_mode();
Versioned::set_reading_mode('Stage.' . Versioned::DRAFT);
// will get added
$pageA = new Page();
$pageA->Title = 'Test Page true';
$pageA->ShowInSearch = true;
$pageA->write();
// will get filtered out
$page = new Page();
$page->Title = 'Test Page false';
$page->ShowInSearch = false;
$page->write();
// will get added
$fileA = new File();
$fileA->Title = 'Test File true';
$fileA->ShowInSearch = true;
$fileA->write();
// will get filtered out
$file = new File();
$file->Title = 'Test File false';
$file->ShowInSearch = false;
$file->write();
// will get added
$objOneA = new SolrIndexTest_MyDataObjectOne();
$objOneA->Title = 'Test MyDataObjectOne true';
$objOneA->ShowInSearch = true;
$objOneA->write();
// will get filtered out
$objOne = new SolrIndexTest_MyDataObjectOne();
$objOne->Title = 'Test MyDataObjectOne false';
$objOne->ShowInSearch = false;
$objOne->write();
// will get added
// this class has a getShowInSearch() == true, which will override $mypage->ShowInSearch = false
$objTwoA = new SolrIndexTest_MyDataObjectTwo();
$objTwoA->Title = 'Test MyDataObjectTwo false';
$objTwoA->ShowInSearch = false;
$objTwoA->write();
// will get added
// this class has a getShowInSearch() == true, which will override $mypage->ShowInSearch = false
$myPageA = new SolrIndexTest_MyPage();
$myPageA->Title = 'Test MyPage false';
$myPageA->ShowInSearch = false;
$myPageA->write();
$serviceMock = $this->getMockBuilder(Solr4Service::class)
->setMethods(['addDocument', 'deleteByQuery'])
->getMock();
$index = new SolrIndexTest_ShowInSearchIndex();
$index->setService($serviceMock);
FullTextSearch::force_index_list($index);
$callback = function (Apache_Solr_Document $doc) use ($pageA, $myPageA, $fileA, $objOneA, $objTwoA): bool {
$validKeys = [
Page::class . $pageA->ID,
SolrIndexTest_MyPage::class . $myPageA->ID,
File::class . $fileA->ID,
SolrIndexTest_MyDataObjectOne::class . $objOneA->ID,
SolrIndexTest_MyDataObjectTwo::class . $objTwoA->ID
];
return in_array($this->createSolrDocKey($doc), $validKeys);
};
$serviceMock
->expects($this->exactly(5))
->method('addDocument')
->withConsecutive(
[$this->callback($callback)],
[$this->callback($callback)],
[$this->callback($callback)],
[$this->callback($callback)],
[$this->callback($callback)]
);
$logger = new SolrReindexTest_RecordingLogger();
$state = [SearchVariantVersioned::class => Versioned::DRAFT];
$handler = Injector::inst()->get(SolrReindexImmediateHandler::class);
$handler->runGroup($logger, $index, $state, SiteTree::class, 1, 0);
$handler->runGroup($logger, $index, $state, File::class, 1, 0);
$handler->runGroup($logger, $index, $state, SolrIndexTest_MyDataObjectOne::class, 1, 0);
Versioned::set_reading_mode($defaultMode);
}
protected function createSolrDocKey(Apache_Solr_Document $doc)
{
return $doc->getField('ClassName')['value'] . $doc->getField('ID')['value'];
}
}