Merge pull request #187 from creative-commoners/pulls/3.0/subsites-compat

API Update Subsite integration, remove Polyhome variant
This commit is contained in:
Dylan Wagstaff 2017-12-05 15:10:45 +13:00 committed by GitHub
commit 3e491088b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 377 additions and 524 deletions

View File

@ -12,6 +12,8 @@ matrix:
env: DB=MYSQL PHPUNIT_TEST=1
- php: 7.1
env: DB=MYSQL PHPUNIT_COVERAGE_TEST=1
- php: 7.1
env: DB=MYSQL PHPUNIT_TEST=1 SUBSITES=1
- php: 7.2
env: DB=MYSQL PHPUNIT_TEST=1
@ -21,7 +23,7 @@ before_script:
- composer validate
- composer require --no-update symbiote/silverstripe-queuedjobs ^4.0
# todo: Add Subsites in
- if [[ $SUBSITES ]]; then composer require --no-update silverstripe/subsites 2.0.x-dev; fi
- composer require --no-update silverstripe/installer 4.0.x-dev
- composer install --prefer-dist --no-interaction --no-progress --no-suggest --optimize-autoloader --verbose --profile

View File

@ -16,7 +16,6 @@ mappings:
SearchUpdater_ObjectHandler: SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater_ObjectHandler
SearchVariant: SilverStripe\FullTextSearch\Search\Variants\SearchVariant
SearchVariant_Caller: SilverStripe\FullTextSearch\Search\Variants\SearchVariant_Caller
SearchVariantSiteTreeSubsitesPolyhome: SilverStripe\FullTextSearch\Search\Variants\SearchVariantSiteTreeSubsitesPolyhome
SearchVariantSubsites: SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites
SearchVariantVersioned: SilverStripe\FullTextSearch\Search\Variants\SearchVariantVersioned
SolrReindexBase: SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexBase

View File

@ -13,7 +13,6 @@ Adds support for fulltext search engines like Sphinx and Solr to SilverStripe CM
## Requirements
* SilverStripe 4.0+
* (optional) [silverstripe-phockito](https://github.com/hafriedlander/silverstripe-phockito) (for testing)
**Note:** For SilverStripe 3.x, please use the [2.x release line](https://github.com/silverstripe/silverstripe-fulltextsearch/tree/2).

8
_config/tests.yml Normal file
View File

@ -0,0 +1,8 @@
---
Name: fulltextsearchtests
---
SilverStripe\Core\Injector\Injector:
SilverStripe\Dev\State\SapphireTestState:
properties:
States:
fulltextsearch: '%$SilverStripe\FullTextSearch\Tests\State\FullTextSearchState'

View File

@ -1,4 +1,5 @@
<?php
namespace SilverStripe\FullTextSearch\Search;
use SilverStripe\Core\ClassInfo;

View File

@ -4,6 +4,7 @@ namespace SilverStripe\FullTextSearch\Search\Variants;
use SilverStripe\ORM\DataObject;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Configurable;
use SilverStripe\FullTextSearch\Utils\CombinationsArrayIterator;
use ReflectionClass;
@ -13,6 +14,16 @@ use ReflectionClass;
*/
abstract class SearchVariant
{
use Configurable;
/**
* Whether this variant is enabled
*
* @config
* @var boolean
*/
private static $enabled = true;
public function __construct()
{
}
@ -30,7 +41,7 @@ abstract class SearchVariant
*/
public function appliesToEnvironment()
{
return true;
return $this->config()->get('enabled');
}
/**
@ -117,6 +128,14 @@ abstract class SearchVariant
}
}
/**
* Clear the cached variants
*/
public static function clear_variant_cache()
{
self::$class_variants = [];
}
/** Holds a cache of SearchVariant_Caller instances, one for each class/includeSubclasses setting */
protected static $call_instances = array();
@ -175,14 +194,14 @@ abstract class SearchVariant
/**
* Activate all the states in the passed argument
* @static
* @param (array) $state. A set of (string)$variantClass => (any)$state pairs , e.g. as returned by
* @param array $state A set of (string)$variantClass => (any)$state pairs , e.g. as returned by
* SearchVariant::current_state()
* @return void
*/
public static function activate_state($state)
{
foreach (self::variants() as $variant => $instance) {
if (isset($state[$variant])) {
if (isset($state[$variant]) && $instance->appliesToEnvironment()) {
$instance->activateState($state[$variant]);
}
}

View File

@ -1,103 +0,0 @@
<?php
namespace SilverStripe\FullTextSearch\Search\Variants;
use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
if (!class_exists('Subsite') || !class_exists('SubsitePolyhome')) {
return;
}
class SearchVariantSiteTreeSubsitesPolyhome extends SearchVariant
{
public function appliesToEnvironment()
{
return class_exists('Subsite') && class_exists('SubsitePolyhome');
}
public function appliesTo($class, $includeSubclasses)
{
return SearchIntrospection::has_extension($class, 'SiteTreeSubsitesPolyhome', $includeSubclasses);
}
public function currentState()
{
return Subsite::currentSubsiteID();
}
public function reindexStates()
{
static $ids = null;
if ($ids === null) {
$ids = array(0);
foreach (DataObject::get('Subsite') as $subsite) {
$ids[] = $subsite->ID;
}
}
return $ids;
}
public function activateState($state)
{
if (Controller::has_curr()) {
Subsite::changeSubsite($state);
} else {
// TODO: This is a nasty hack - calling Subsite::changeSubsite after request ends
// throws error because no current controller to access session on
$_REQUEST['SubsiteID'] = $state;
}
}
public function alterDefinition($class, $index)
{
$self = get_class($this);
$this->addFilterField($index, '_subsite', array(
'name' => '_subsite',
'field' => '_subsite',
'fullfield' => '_subsite',
'base' => DataObject::getSchema()->baseDataClass($class),
'origin' => $class,
'type' => 'Int',
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
));
}
public function alterQuery($query, $index)
{
$subsite = Subsite::currentSubsiteID();
$query->filter('_subsite', array($subsite, SearchQuery::$missing));
}
public static $subsites = null;
/**
* We need _really_ complicated logic to find just the changed subsites (because we use versions there's no explicit
* deletes, just new versions with different members) so just always use all of them
*/
public function extractManipulationWriteState(&$writes)
{
$self = get_class($this);
foreach ($writes as $key => $write) {
if (!$this->appliesTo($write['class'], true)) {
continue;
}
if (self::$subsites === null) {
$query = new SQLSelect('ID', 'Subsite');
self::$subsites = array_merge(array('0'), $query->execute()->column());
}
$next = array();
foreach ($write['statefulids'] as $i => $statefulid) {
foreach (self::$subsites as $subsiteID) {
$next[] = array('id' => $statefulid['id'], 'state' => array_merge($statefulid['state'], array($self => $subsiteID)));
}
}
$writes[$key]['statefulids'] = $next;
}
}
}

View File

@ -2,13 +2,21 @@
namespace SilverStripe\FullTextSearch\Search\Variants;
use SilverStripe\Assets\File;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Permission;
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\Subsites\Extensions\SiteTreeSubsites;
use SilverStripe\Subsites\Extensions\GroupSubsites;
use SilverStripe\Subsites\Extensions\FileSubsites;
use SilverStripe\Subsites\Extensions\SiteConfigSubsites;
use SilverStripe\Subsites\State\SubsiteState;
if (!class_exists('Subsite')) {
if (!class_exists(Subsite::class)) {
return;
}
@ -16,22 +24,26 @@ class SearchVariantSubsites extends SearchVariant
{
public function appliesToEnvironment()
{
return class_exists('Subsite');
return class_exists(Subsite::class) && parent::appliesToEnvironment();
}
public function appliesTo($class, $includeSubclasses)
{
if (!$this->appliesToEnvironment()) {
return false;
}
// Include all DataExtensions that contain a SubsiteID.
// TODO: refactor subsites to inherit a common interface, so we can run introspection once only.
return SearchIntrospection::has_extension($class, 'SiteTreeSubsites', $includeSubclasses) ||
SearchIntrospection::has_extension($class, 'GroupSubsites', $includeSubclasses) ||
SearchIntrospection::has_extension($class, 'FileSubsites', $includeSubclasses) ||
SearchIntrospection::has_extension($class, 'SiteConfigSubsites', $includeSubclasses);
return SearchIntrospection::has_extension($class, SiteTreeSubsites::class, $includeSubclasses)
|| SearchIntrospection::has_extension($class, GroupSubsites::class, $includeSubclasses)
|| SearchIntrospection::has_extension($class, FileSubsites::class, $includeSubclasses)
|| SearchIntrospection::has_extension($class, SiteConfigSubsites::class, $includeSubclasses);
}
public function currentState()
{
return (string)Subsite::currentSubsiteID();
return (string) SubsiteState::singleton()->getSubsiteId();
}
public function reindexStates()
@ -39,9 +51,9 @@ class SearchVariantSubsites extends SearchVariant
static $ids = null;
if ($ids === null) {
$ids = array('0');
foreach (DataObject::get('Subsite') as $subsite) {
$ids[] = (string)$subsite->ID;
$ids = ['0'];
foreach (Subsite::get() as $subsite) {
$ids[] = (string) $subsite->ID;
}
}
@ -50,26 +62,34 @@ class SearchVariantSubsites extends SearchVariant
public function activateState($state)
{
// We always just set the $_GET variable rather than store in Session - this always works, has highest priority
// in Subsite::currentSubsiteID() and doesn't persist unlike Subsite::changeSubsite
$_GET['SubsiteID'] = $state;
Permission::flush_permission_cache();
if (!$this->appliesToEnvironment()) {
return;
}
// Note: Setting directly to the SubsiteState because we don't want the subsite ID to be persisted
// like Subsite::changeSubsite would do.
SubsiteState::singleton()->setSubsiteId($state);
Permission::reset();
}
public function alterDefinition($class, $index)
{
$self = get_class($this);
if (!$this->appliesTo($class, true)) {
return;
}
// Add field to root
$this->addFilterField($index, '_subsite', array(
$this->addFilterField($index, '_subsite', [
'name' => '_subsite',
'field' => '_subsite',
'fullfield' => '_subsite',
'base' => DataObject::getSchema()->baseDataClass($class),
'origin' => $class,
'type' => 'Int',
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
));
'lookup_chain' => [['call' => 'variant', 'variant' => $self, 'method' => 'currentState']],
]);
}
/**
@ -83,12 +103,12 @@ class SearchVariantSubsites extends SearchVariant
*/
public function alterQuery($query, $index)
{
if ($this->isFieldFiltered('_subsite', $query)) {
if ($this->isFieldFiltered('_subsite', $query) || !$this->appliesToEnvironment()) {
return;
}
$subsite = Subsite::currentSubsiteID();
$query->filter('_subsite', array($subsite, SearchQuery::$missing));
$subsite = $this->currentState();
$query->filter('_subsite', [$subsite, SearchQuery::$missing]);
}
/**
@ -98,8 +118,9 @@ class SearchVariantSubsites extends SearchVariant
public function extractManipulationWriteState(&$writes)
{
$self = get_class($this);
$query = new SQLSelect('"ID"', '"Subsite"');
$subsites = array_merge(array('0'), $query->execute()->column());
$tableName = DataObject::getSchema()->tableName(Subsite::class);
$query = SQLSelect::create('"ID"', '"' . $tableName . '"');
$subsites = array_merge(['0'], $query->execute()->column());
foreach ($writes as $key => $write) {
$applies = $this->appliesTo($write['class'], true);
@ -107,25 +128,27 @@ class SearchVariantSubsites extends SearchVariant
continue;
}
if (isset($write['fields']['SiteTree:SubsiteID'])) {
$subsitesForWrite = array($write['fields']['SiteTree:SubsiteID']);
} // files in subsite 0 should be in all subsites as they are global
elseif (isset($write['fields']['File:SubsiteID']) && intval($write['fields']['File:SubsiteID']) !== 0) {
$subsitesForWrite = array($write['fields']['File:SubsiteID']);
if (isset($write['fields'][SiteTree::class . ':SubsiteID'])) {
$subsitesForWrite = [$write['fields'][SiteTree::class . ':SubsiteID']];
} elseif (isset($write['fields'][File::class . ':SubsiteID'])
&& (int) $write['fields'][File::class . ':SubsiteID'] !== 0
) {
// files in subsite 0 should be in all subsites as they are global
$subsitesForWrite = [$write['fields'][File::class . ':SubsiteID']];
} else {
$subsitesForWrite = $subsites;
}
$next = array();
$next = [];
foreach ($write['statefulids'] as $i => $statefulid) {
foreach ($subsitesForWrite as $subsiteID) {
$next[] = array(
$next[] = [
'id' => $statefulid['id'],
'state' => array_merge(
$statefulid['state'],
array($self => (string)$subsiteID)
)
);
[$self => (string) $subsiteID]
),
];
}
}
$writes[$key]['statefulids'] = $next;

View File

@ -12,6 +12,10 @@ class SearchVariantVersioned extends SearchVariant
{
public function appliesTo($class, $includeSubclasses)
{
if (!$this->appliesToEnvironment()) {
return false;
}
return SearchIntrospection::has_extension($class, Versioned::class, $includeSubclasses);
}
@ -57,8 +61,6 @@ class SearchVariantVersioned extends SearchVariant
public function extractManipulationState(&$manipulation)
{
$self = get_class($this);
foreach ($manipulation as $table => $details) {
$class = $details['class'];
$stage = Versioned::DRAFT;
@ -70,7 +72,7 @@ class SearchVariantVersioned extends SearchVariant
if (ClassInfo::exists($class) && $this->appliesTo($class, false)) {
$manipulation[$table]['class'] = $class;
$manipulation[$table]['state'][$self] = $stage;
$manipulation[$table]['state'][get_class($this)] = $stage;
}
}
}
@ -83,10 +85,9 @@ class SearchVariantVersioned extends SearchVariant
if (ClassInfo::exists($class) && $this->appliesTo($class, false)) {
$table = $class;
$self = get_class($this);
foreach ($ids as $i => $statefulid) {
$ids[$i]['state'][$self] = $suffix ? $suffix : Versioned::DRAFT;
$ids[$i]['state'][get_class($this)] = $suffix ?: Versioned::DRAFT;
}
}
}

View File

@ -1,4 +1,5 @@
<?php
namespace SilverStripe\FullTextSearch\Solr\Services;
class Solr4Service extends SolrService

View File

@ -2,12 +2,11 @@
namespace SilverStripe\FullTextSearch\Tests;
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\ORM\FieldType\DBDatetime;
use SilverStripe\Core\Config\Config;
use SilverStripe\Versioned\Versioned;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\FullTextSearch\Tests\BatchedProcessorTest\BatchedProcessor_QueuedJobService;
use SilverStripe\FullTextSearch\Tests\BatchedProcessorTest\BatchedProcessorTest_Index;
use SilverStripe\FullTextSearch\Tests\BatchedProcessorTest\BatchedProcessorTest_Object;
@ -16,6 +15,9 @@ use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateQueuedJobProcessor
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateBatchedProcessor;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantVersioned;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Versioned\Versioned;
use Symbiote\QueuedJobs\Services\QueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJobService;
/**
@ -29,37 +31,30 @@ class BatchedProcessorTest extends SapphireTest
BatchedProcessorTest_Object::class
);
protected $illegalExtensions = array(
'SiteTree' => array(
'SiteTreeSubsites',
'Translatable'
)
);
protected static $illegal_extensions = [
SiteTree::class => [
SiteTreeSubsites::class,
],
];
public function setUpOnce()
public static function setUpBeforeClass()
{
// Disable illegal extensions if skipping this test
if (class_exists('Subsite') || !interface_exists('Symbiote\QueuedJobs\Services\QueuedJob')) {
$this->illegalExtensions = array();
if (class_exists(Subsite::class) || !interface_exists(QueuedJob::class)) {
static::$illegal_extensions = [];
}
parent::setUpOnce();
parent::setUpBeforeClass();
}
protected function setUp()
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
parent::setUp();
if (!interface_exists('Symbiote\QueuedJobs\Services\QueuedJob')) {
$this->skipTest = true;
if (!interface_exists(QueuedJob::class)) {
$this->markTestSkipped("These tests need the QueuedJobs module installed to run");
}
Config::modify()->set(QueuedJobService::class, 'use_shutdown_function', false);
if (class_exists('Subsite')) {
$this->skipTest = true;
if (class_exists(Subsite::class)) {
$this->markTestSkipped(get_class() . ' skipped when running with subsites');
}
@ -69,7 +64,7 @@ class BatchedProcessorTest extends SapphireTest
Config::modify()->set(SearchUpdateBatchedProcessor::class, 'batch_soft_cap', 0);
Config::modify()->set(SearchUpdateCommitJobProcessor::class, 'cooldown', 600);
Versioned::set_stage("Stage");
Versioned::set_stage(Versioned::DRAFT);
Injector::inst()->registerService(new BatchedProcessor_QueuedJobService(), QueuedJobService::class);

View File

@ -22,8 +22,6 @@ class SearchUpdaterTest extends SapphireTest
protected function setUp()
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
parent::setUp();
if (self::$index === null) {

View File

@ -1,74 +0,0 @@
<?php
namespace SilverStripe\FullTextSearch\Tests;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
use SilverStripe\FullTextSearch\Tests\SearchVariantSiteTreeSubsitesPolyhomeTest\SearchVariantSiteTreeSubsitesPolyhomeTest_Index;
use SilverStripe\FullTextSearch\Tests\SearchVariantSiteTreeSubsitesPolyhomeTest\SearchVariantSiteTreeSubsitesPolyhomeTest_Item;
class SearchVariantSiteTreeSubsitesPolyhomeTest extends SapphireTest
{
private static $index = null;
private static $subsite_a = null;
private static $subsite_b = null;
public function setUp()
{
parent::setUp();
// Check subsites installed
if (!class_exists('Subsite') || !class_exists('SubsitePolyhome')) {
return $this->markTestSkipped('The subsites polyhome module is not installed');
}
if (self::$index === null) {
self::$index = singleton('SearchVariantSiteTreeSubsitesPolyhomeTest_Index');
}
if (self::$subsite_a === null) {
self::$subsite_a = new Subsite();
self::$subsite_a->write();
self::$subsite_b = new Subsite();
self::$subsite_b->write();
}
FullTextSearch::force_index_list(self::$index);
SearchUpdater::clear_dirty_indexes();
}
public function testSavingDirect()
{
// Initial add
$item = new SearchVariantSiteTreeSubsitesPolyhomeTest_Item();
$item->write();
SearchUpdater::flush_dirty_indexes();
$this->assertEquals(self::$index->getAdded(array('ID', '_subsite')), array(
array('ID' => $item->ID, '_subsite' => 0)
));
// Check that adding to subsites works
self::$index->reset();
$item->setField('AddToSubsite[0]', 1);
$item->setField('AddToSubsite['.(self::$subsite_a->ID).']', 1);
$item->write();
SearchUpdater::flush_dirty_indexes();
$this->assertEquals(self::$index->getAdded(array('ID', '_subsite')), array(
array('ID' => $item->ID, '_subsite' => 0),
array('ID' => $item->ID, '_subsite' => self::$subsite_a->ID)
));
$this->assertEquals(self::$index->deleted, array(
array('base' => 'SiteTree', 'id' => $item->ID, 'state' => array(
'SearchVariantVersioned' => 'Stage', 'SearchVariantSiteTreeSubsitesPolyhome' => self::$subsite_b->ID
))
));
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SearchVariantSiteTreeSubsitesPolyhomeTest;
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
class SearchVariantSiteTreeSubsitesPolyhomeTest_Index extends SearchIndex_Recording
{
public function init()
{
$this->addClass(SearchVariantSiteTreeSubsitesPolyhomeTest_Item::class);
$this->addFilterField('TestText');
}
}

View File

@ -1,15 +0,0 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SearchVariantSiteTreeSubsitesPolyhomeTest;
use SilverStripe\CMS\Model\SiteTree;
class SearchVariantSiteTreeSubsitesPolyhomeTest_Item extends SiteTree
{
private static $table_name = 'SearchVariantSiteTreeSubsitesPolyhomeTest_Item';
// TODO: Currently theres a failure if you addClass a non-table class
private static $db = array(
'TestText' => 'Varchar'
);
}

View File

@ -2,32 +2,40 @@
namespace SilverStripe\FullTextSearch\Tests;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\FullTextSearch\Search\FullTextSearch;
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex;
use SilverStripe\Subsites\Model\Subsite;
class SearchVariantSubsiteTest extends SapphireTest
{
private static $index = null;
public function setUp()
protected function setUp()
{
parent::setUp();
// Check versioned available
if (!class_exists('Subsite')) {
if (!class_exists(Subsite::class)) {
return $this->markTestSkipped('The subsites module is not installed');
}
if (self::$index === null) {
self::$index = singleton('SearchVariantSubsiteTest');
self::$index = singleton(static::class);
}
SearchUpdater::bind_manipulation_capture();
Config::inst()->update('Injector', 'SearchUpdateProcessor', array(
'class' => 'SearchUpdateImmediateProcessor'
));
Config::modify()->set(Injector::class, SearchUpdateProcessor::class, [
'class' => SearchUpdateImmediateProcessor::class
]);
FullTextSearch::force_index_list(self::$index);
SearchUpdater::clear_dirty_indexes();
@ -41,13 +49,13 @@ class SearchVariantSubsiteTest extends SapphireTest
//typical behaviour: nobody is explicitly filtering on subsite, so the search variant adds a filter to the query
$this->assertArrayNotHasKey('_subsite', $query->require);
$variant = new SearchVariantSubsites();
$variant->alterDefinition('SearchUpdaterTest_Container', $index);
$variant->alterDefinition(SearchUpdaterTest_Container::class, $index);
$variant->alterQuery($query, $index);
//check that the "default" query has been put in place: it's not empty, and we're searching on Subsite ID:0 and
// an object of SearchQuery::missing
$this->assertNotEmpty($query->require['_subsite']);
$this->assertEquals(0, $query->require['_subsite'][0]);
$this->assertEmpty($query->require['_subsite'][0]);
//check that SearchQuery::missing is set (by default, it is an object of stdClass)
$this->assertInstanceOf('stdClass', $query->require['_subsite'][1]);
@ -71,7 +79,7 @@ class SearchVariantSubsiteTest extends SapphireTest
//apply the search variant's definition and query
$variant = new SearchVariantSubsites();
$variant->alterDefinition('SearchUpdaterTest_Container', $index);
$variant->alterDefinition(SearchUpdaterTest_Container::class, $index);
//the protected function isFieldFiltered is implicitly tested here
$variant->alterQuery($query, $index);

View File

@ -28,8 +28,6 @@ class SearchVariantVersionedTest extends SapphireTest
protected function setUp()
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
parent::setUp();
if (self::$index === null) {
@ -130,4 +128,15 @@ class SearchVariantVersionedTest extends SapphireTest
array('ID' => $item->ID, '_versionedstage' => 'Live')
), $index->getAdded(array('ID', '_versionedstage')));
}
public function testCanBeDisabledViaConfig()
{
$variant = new SearchVariantVersioned;
Config::modify()->set(SearchVariantVersioned::class, 'enabled', true);
$this->assertTrue($variant->appliesToEnvironment());
Config::modify()->set(SearchVariantVersioned::class, 'enabled', false);
$this->assertFalse($variant->appliesToEnvironment());
}
}

View File

@ -2,20 +2,32 @@
namespace SilverStripe\FullTextSearch\Tests;
use Apache_Solr_Document;
use Page;
use SilverStripe\Assets\File;
use SilverStripe\Assets\Image;
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\Processors\SearchUpdateImmediateProcessor;
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites;
use SilverStripe\FullTextSearch\Solr\Services\Solr4Service;
use SilverStripe\FullTextSearch\Tests\SolrIndexSubsitesTest\SolrIndexSubsitesTest_Index;
if (class_exists('\Phockito')) {
\Phockito::include_hamcrest(false);
}
use SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest\SolrDocumentMatcher;
use SilverStripe\ORM\DataObject;
use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\Versioned\Versioned;
/**
* Subsite specific solr testing
*/
class SolrIndexSubsitesTest extends SapphireTest
{
// @todo
// protected static $fixture_file = 'SolrIndexSubsitesTest/SolrIndexSubsitesTest.yml';
protected static $fixture_file = 'SolrIndexSubsitesTest/SolrIndexSubsitesTest.yml';
/**
* @var SolrIndexSubsitesTest_Index
@ -26,31 +38,28 @@ class SolrIndexSubsitesTest extends SapphireTest
protected function setUp()
{
// Prevent parent::setUp() crashing on db build
if (!class_exists(Subsite::class)) {
static::$fixture_file = null;
}
parent::setUp();
// Prevent parent::setUp() crashing on db build
if (!class_exists('Subsite')) {
$this->skipTest = true;
if (!class_exists(Subsite::class)) {
$this->markTestSkipped("These tests need the Subsite module installed to run");
}
$this->server = $_SERVER;
if (!class_exists('\Phockito')) {
$this->skipTest = true;
$this->markTestSkipped("These tests need the \Phockito module installed to run");
return;
}
if (self::$index === null) {
self::$index = singleton('SolrIndexSubsitesTest_Index');
self::$index = singleton(SolrIndexSubsitesTest_Index::class);
}
SearchUpdater::bind_manipulation_capture();
Config::modify()->set('Injector', 'SearchUpdateProcessor', array(
'class' => 'SearchUpdateImmediateProcessor'
));
Config::modify()->set(Injector::class, SearchUpdateProcessor::class, [
'class' => SearchUpdateImmediateProcessor::class,
]);
FullTextSearch::force_index_list(self::$index);
SearchUpdater::clear_dirty_indexes();
@ -67,7 +76,9 @@ class SolrIndexSubsitesTest extends SapphireTest
protected function getServiceMock()
{
return \Phockito::mock('Solr4Service');
return $this->getMockBuilder(Solr4Service::class)
->setMethods(['addDocument', 'commit'])
->getMock();
}
/**
@ -83,7 +94,9 @@ class SolrIndexSubsitesTest extends SapphireTest
$variants = array();
// Check subsite
if (class_exists('Subsite') && DataObject::getSchema()->hasOneComponent($object->getClassName(), 'Subsite')) {
if (class_exists(Subsite::class)
&& DataObject::getSchema()->hasOneComponent($object->getClassName(), 'Subsite')
) {
$variants[] = '"SearchVariantSubsites":"' . $subsiteID. '"';
}
@ -91,7 +104,7 @@ class SolrIndexSubsitesTest extends SapphireTest
if ($stage) {
$variants[] = '"SearchVariantVersioned":"' . $stage . '"';
}
return $id.'-'.$class.'-{'.implode(',', $variants).'}';
return $id . '-' . $class . '-{' . implode(',', $variants) . '}';
}
public function testPublishing()
@ -100,146 +113,163 @@ class SolrIndexSubsitesTest extends SapphireTest
$serviceMock = $this->getServiceMock();
self::$index->setService($serviceMock);
$subsite1 = $this->objFromFixture('Subsite', 'subsite1');
$subsite1 = $this->objFromFixture(Subsite::class, 'subsite1');
// Add records to first subsite
Versioned::reading_stage('Stage');
Versioned::set_stage(Versioned::DRAFT);
$_SERVER['HTTP_HOST'] = 'www.subsite1.com';
\Phockito::reset($serviceMock);
$file = new File();
$file->Title = 'My File';
$file->SubsiteID = $subsite1->ID;
$file->write();
$page = new Page();
$page->Title = 'My Page';
$page->SubsiteID = $subsite1->ID;
$page->write();
SearchUpdater::flush_dirty_indexes();
$doc1 = new SolrDocumentMatcher(array(
$doc1 = new Apache_Solr_Document([
'_documentid' => $this->getExpectedDocumentId($page, $subsite1->ID, 'Stage'),
'ClassName' => 'Page',
'SiteTree_Title' => 'My Page',
'_versionedstage' => 'Stage',
'_subsite' => $subsite1->ID
));
$doc2 = new SolrDocumentMatcher(array(
'_subsite' => $subsite1->ID,
]);
$doc2 = new Apache_Solr_Document([
'_documentid' => $this->getExpectedDocumentId($file, $subsite1->ID),
'ClassName' => 'File',
'ClassName' => File::class,
'File_Title' => 'My File',
'_subsite' => $subsite1->ID
));
\Phockito::verify($serviceMock)->addDocument($doc1);
\Phockito::verify($serviceMock)->addDocument($doc2);
'_subsite' => $subsite1->ID,
]);
$serviceMock
->expects($this->exactly(2))
->method('addDocument')
->withConsecutive($doc1, $doc2);
SearchUpdater::flush_dirty_indexes();
}
public function testCorrectSubsiteIDOnPageWrite()
{
$mockWrites = array(
'3367:SiteTree:a:1:{s:22:"SearchVariantVersioned";s:4:"Live";}' => array(
'base' => 'SiteTree',
$mockWrites = [
'3367:SiteTree:a:1:{s:22:"SearchVariantVersioned";s:4:"Live";}' => [
'base' => 'SilverStripe\\CMS\\Model\\SiteTree',
'class' => 'Page',
'id' => 3367,
'statefulids' => array(
array(
'statefulids' => [
[
'id' => 3367,
'state' => array(
'state' => [
'SearchVariantVersioned' => 'Live',
),
),
),
'fields' => array(
'SiteTree:ClassName' => 'Page',
'SiteTree:LastEdited' => '2016-12-08 23:55:30',
'SiteTree:Created' => '2016-11-30 05:23:58',
'SiteTree:URLSegment' => 'test',
'SiteTree:Title' => 'Test Title',
'SiteTree:Content' => '<p>test content</p>',
'SiteTree:MetaDescription' => 'a solr test',
'SiteTree:ShowInMenus' => 1,
'SiteTree:ShowInSearch' => 1,
'SiteTree:Sort' => 77,
'SiteTree:HasBrokenFile' => 0,
'SiteTree:HasBrokenLink' => 0,
'SiteTree:CanViewType' => 'Inherit',
'SiteTree:CanEditType' => 'Inherit',
'SiteTree:Locale' => 'en_NZ',
'SiteTree:SubsiteID' => 0,
],
],
],
'fields' => [
'SilverStripe\\CMS\\Model\\SiteTree:ClassName' => 'Page',
'SilverStripe\\CMS\\Model\\SiteTree:LastEdited' => '2016-12-08 23:55:30',
'SilverStripe\\CMS\\Model\\SiteTree:Created' => '2016-11-30 05:23:58',
'SilverStripe\\CMS\\Model\\SiteTree:URLSegment' => 'test',
'SilverStripe\\CMS\\Model\\SiteTree:Title' => 'Test Title',
'SilverStripe\\CMS\\Model\\SiteTree:Content' => '<p>test content</p>',
'SilverStripe\\CMS\\Model\\SiteTree:MetaDescription' => 'a solr test',
'SilverStripe\\CMS\\Model\\SiteTree:ShowInMenus' => 1,
'SilverStripe\\CMS\\Model\\SiteTree:ShowInSearch' => 1,
'SilverStripe\\CMS\\Model\\SiteTree:Sort' => 77,
'SilverStripe\\CMS\\Model\\SiteTree:HasBrokenFile' => 0,
'SilverStripe\\CMS\\Model\\SiteTree:HasBrokenLink' => 0,
'SilverStripe\\CMS\\Model\\SiteTree:CanViewType' => 'Inherit',
'SilverStripe\\CMS\\Model\\SiteTree:CanEditType' => 'Inherit',
'SilverStripe\\CMS\\Model\\SiteTree:Locale' => 'en_NZ',
'SilverStripe\\CMS\\Model\\SiteTree:SubsiteID' => 0,
'Page:ID' => 3367,
'Page:MetaKeywords' => null,
),
),
);
],
],
];
$variant = new SearchVariantSubsites();
$tmpMockWrites = $mockWrites;
$variant->extractManipulationWriteState($tmpMockWrites);
foreach ($tmpMockWrites as $mockWrite) {
$this->assertCount(1, $mockWrite['statefulids']);
$statefulIDs = array_shift($mockWrite['statefulids']);
$this->assertEquals(0, $statefulIDs['state']['SearchVariantSubsites']);
$this->assertArrayHasKey(SearchVariantSubsites::class, $statefulIDs['state']);
$this->assertEquals(0, $statefulIDs['state'][SearchVariantSubsites::class]);
}
$subsite = $this->objFromFixture('Subsite', 'subsite1');
$subsite = $this->objFromFixture(Subsite::class, 'subsite1');
$tmpMockWrites = $mockWrites;
$tmpMockWrites['3367:SiteTree:a:1:{s:22:"SearchVariantVersioned";s:4:"Live";}']['fields']['SiteTree:SubsiteID'] = $subsite->ID;
$tmpMockWrites['3367:SiteTree:a:1:{s:22:"SearchVariantVersioned";s:4:"Live";}']['fields'][SiteTree::class . ':SubsiteID'] = $subsite->ID;
$variant->extractManipulationWriteState($tmpMockWrites);
foreach ($tmpMockWrites as $mockWrite) {
$this->assertCount(1, $mockWrite['statefulids']);
$statefulIDs = array_shift($mockWrite['statefulids']);
$this->assertEquals($subsite->ID, $statefulIDs['state']['SearchVariantSubsites']);
$this->assertArrayHasKey(SearchVariantSubsites::class, $statefulIDs['state']);
$this->assertEquals($subsite->ID, $statefulIDs['state'][SearchVariantSubsites::class]);
}
}
public function testCorrectSubsiteIDOnFileWrite()
{
$subsiteIDs = array('0') + $this->allFixtureIDs('Subsite');
$mockWrites = array(
'35910:File:a:0:{}' => array(
'base' => 'File',
'class' => 'File',
$subsiteIDs = ['0'] + $this->allFixtureIDs(Subsite::class);
$mockWrites = [
'35910:File:a:0:{}' => [
'base' => File::class,
'class' => File::class,
'id' => 35910,
'statefulids' => array(
array(
'statefulids' => [
[
'id' => 35910,
'state' => array(),
),
),
'fields' => array(
'File:ClassName' => 'Image',
'File:ShowInSearch' => 1,
'File:ParentID' => 26470,
'File:Filename' => 'assets/Uploads/pic.jpg',
'File:Name' => 'pic.jpg',
'File:Title' => 'pic',
'File:SubsiteID' => 0,
'File:OwnerID' => 661,
'File:CurrentVersionID' => 22038,
'File:LastEdited' => '2016-12-09 00:35:13',
),
),
);
'state' => [],
],
],
'fields' => [
File::class . ':ClassName' => Image::class,
File::class . ':ShowInSearch' => 1,
File::class . ':ParentID' => 26470,
File::class . ':Filename' => 'assets/Uploads/pic.jpg',
File::class . ':Name' => 'pic.jpg',
File::class . ':Title' => 'pic',
File::class . ':SubsiteID' => 0,
File::class . ':OwnerID' => 661,
File::class . ':CurrentVersionID' => 22038,
File::class . ':LastEdited' => '2016-12-09 00:35:13',
],
],
];
$variant = new SearchVariantSubsites();
$tmpMockWrites = $mockWrites;
$variant->extractManipulationWriteState($tmpMockWrites);
foreach ($tmpMockWrites as $mockWrite) {
$this->assertCount(count($subsiteIDs), $mockWrite['statefulids']);
foreach ($mockWrite['statefulids'] as $statefulIDs) {
$this->assertTrue(
in_array($statefulIDs['state']['SearchVariantSubsites'], $subsiteIDs),
sprintf('Failed to assert that %s is in list of valid subsites: %s', $statefulIDs['state']['SearchVariantSubsites'], implode(', ', $subsiteIDs))
$this->assertContains(
$statefulIDs['state'][SearchVariantSubsites::class],
$subsiteIDs,
sprintf(
'Failed to assert that %s is in list of valid subsites: %s',
$statefulIDs['state'][SearchVariantSubsites::class],
implode(', ', $subsiteIDs)
)
);
}
}
$subsite = $this->objFromFixture('Subsite', 'subsite1');
$subsite = $this->objFromFixture(Subsite::class, 'subsite1');
$tmpMockWrites = $mockWrites;
$tmpMockWrites['35910:File:a:0:{}']['fields']['File:SubsiteID'] = $subsite->ID;
$tmpMockWrites['35910:File:a:0:{}']['fields'][File::class . ':SubsiteID'] = $subsite->ID;
$variant->extractManipulationWriteState($tmpMockWrites);
foreach ($tmpMockWrites as $mockWrite) {
$this->assertCount(1, $mockWrite['statefulids']);
$statefulIDs = array_shift($mockWrite['statefulids']);
$this->assertEquals($subsite->ID, $statefulIDs['state']['SearchVariantSubsites']);
$this->assertEquals($subsite->ID, $statefulIDs['state'][SearchVariantSubsites::class]);
}
}
}

View File

@ -1,16 +1,17 @@
Subsite:
SilverStripe\Subsites\Model\Subsite:
main:
Title: Template
subsite1:
Title: 'Subsite1 Template'
subsite2:
Title: 'Subsite2 Template'
SubsiteDomain:
SilverStripe\Subsites\Model\SubsiteDomain:
subsite1:
SubsiteID: =>Subsite.subsite1
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite1
Domain: www.subsite1.com
Protocol: automatic
subsite2:
SubsiteID: =>Subsite.subsite2
SubsiteID: =>SilverStripe\Subsites\Model\Subsite.subsite2
Domain: www.subsite2.com
Protocol: automatic

View File

@ -2,9 +2,9 @@
namespace SilverStripe\FullTextSearch\Tests\SolrIndexSubsitesTest;
use SilverStripe\FullTextSearch\Solr\SolrIndex;
use SilverStripe\Assets\File;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\FullTextSearch\Solr\SolrIndex;
class SolrIndexSubsitesTest_Index extends SolrIndex
{

View File

@ -7,18 +7,20 @@ use SilverStripe\Core\Environment;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Core\Kernel;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelationIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelationInheritedIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex2;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_BoostedIndex;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites;
use SilverStripe\FullTextSearch\Solr\Services\Solr3Service;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasOne;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasMany;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_ManyMany;
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_OtherContainer;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Solr\Services\Solr3Service;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelationIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_AmbiguousRelationInheritedIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_BoostedIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex;
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex2;
use SilverStripe\Subsites\Model\Subsite;
class SolrIndexTest extends SapphireTest
{
@ -151,6 +153,10 @@ class SolrIndexTest extends SapphireTest
*/
public function testBoostedField()
{
if (class_exists(Subsite::class)) {
Config::modify()->set(SearchVariantSubsites::class, 'enabled', false);
}
/** @var Solr3Service|PHPUnit_Framework_MockObject_MockObject $serviceMock */
$serviceMock = $this->getMockBuilder(Solr3Service::class)
->setMethods(['search'])
@ -162,8 +168,11 @@ class SolrIndexTest extends SapphireTest
$this->equalTo('+term'),
$this->anything(),
$this->anything(),
$this->equalTo(['qf' => SearchUpdaterTest_Container::class . '_Field1^1.5 ' . SearchUpdaterTest_Container::class . '_Field2^2.1 _text',
'fq' => '+(_versionedstage:"" (*:* -_versionedstage:[* TO *]))']),
$this->equalTo([
'qf' => SearchUpdaterTest_Container::class . '_Field1^1.5 '
. SearchUpdaterTest_Container::class . '_Field2^2.1 _text',
'fq' => '+(_versionedstage:"" (*:* -_versionedstage:[* TO *]))',
]),
$this->anything()
)->willReturn($this->getFakeRawSolrResponse());

View File

@ -2,8 +2,10 @@
namespace SilverStripe\FullTextSearch\Tests;
use Apache_Solr_Document;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\ORM\DataObject;
use SilverStripe\FullTextSearch\Search\FullTextSearch;
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
@ -15,23 +17,28 @@ use SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest\SolrVersionedTest_I
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor;
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateImmediateProcessor;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantSubsites;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantVersioned;
use SilverStripe\Subsites\Model\Subsite;
use SilverStripe\Versioned\Versioned;
class SolrIndexVersionedTest extends SapphireTest
{
protected $usesDatabase = true;
protected $oldMode = null;
protected static $index = null;
protected static $extra_dataobjects = array(
protected static $extra_dataobjects = [
SearchVariantVersionedTest_Item::class,
SolrIndexVersionedTest_Object::class
);
SolrIndexVersionedTest_Object::class,
];
protected function setUp()
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
// Need to be set before parent::setUp() since they're executed before the tests start
Config::modify()->set(SearchVariantSubsites::class, 'enabled', false);
parent::setUp();
@ -41,18 +48,18 @@ class SolrIndexVersionedTest extends SapphireTest
SearchUpdater::bind_manipulation_capture();
Config::modify()->set(Injector::class, SearchUpdateProcessor::class, array(
Config::modify()->set(Injector::class, SearchUpdateProcessor::class, [
'class' => SearchUpdateImmediateProcessor::class
));
]);
FullTextSearch::force_index_list(self::$index);
SearchUpdater::clear_dirty_indexes();
$this->oldMode = Versioned::get_reading_mode();
Versioned::set_stage('Stage');
Versioned::set_stage(Versioned::DRAFT);
}
public function tearDown()
protected function tearDown()
{
Versioned::set_reading_mode($this->oldMode);
parent::tearDown();
@ -80,13 +87,7 @@ class SolrIndexVersionedTest extends SapphireTest
{
$id = $object->ID;
$class = DataObject::getSchema()->baseDataClass($object);
// Prevent subsites from breaking tests
// TODO: Subsites currently isn't migrated. This needs to be fixed when subsites is fixed.
$subsites = '';
if (class_exists('Subsite') && DataObject::getSchema()->hasOneComponent($object->getClassName(), 'Subsite')) {
$subsites = '"SearchVariantSubsites":"0",';
}
return $id.'-'.$class.'-{'.$subsites. json_encode(SearchVariantVersioned::class) . ':"'.$stage.'"}';
return $id.'-'.$class.'-{'.json_encode(SearchVariantVersioned::class).':"'.$stage.'"}';
}
/**
@ -98,12 +99,12 @@ class SolrIndexVersionedTest extends SapphireTest
*/
protected function getSolrDocument($class, $object, $value, $stage)
{
$doc = new \Apache_Solr_Document();
$doc = new Apache_Solr_Document();
$doc->setField('_documentid', $this->getExpectedDocumentId($object, $stage));
$doc->setField('ClassName', $class);
$doc->setField(DataObject::getSchema()->baseDataClass($class) . '_TestText', $value);
$doc->setField('_versionedstage', $stage);
$doc->setField('ID', $object->ID);
$doc->setField('ID', (int) $object->ID);
$doc->setField('ClassHierarchy', SearchIntrospection::hierarchy($class));
$doc->setFieldBoost('ID', false);
$doc->setFieldBoost('ClassHierarchy', false);
@ -114,89 +115,52 @@ class SolrIndexVersionedTest extends SapphireTest
public function testPublishing()
{
// Check that write updates Stage
Versioned::set_stage('Stage');
Versioned::set_stage(Versioned::DRAFT);
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Foo'));
$item->write();
$object = new SolrIndexVersionedTest_Object(array('TestText' => 'Bar'));
$object->write();
$doc1 = $this->getSolrDocument(SearchVariantVersionedTest_Item::class, $item, 'Foo', 'Stage');
$doc2 = $this->getSolrDocument(SolrIndexVersionedTest_Object::class, $object, 'Bar', 'Stage');
$doc1 = $this->getSolrDocument(SearchVariantVersionedTest_Item::class, $item, 'Foo', Versioned::DRAFT);
$doc2 = $this->getSolrDocument(SolrIndexVersionedTest_Object::class, $object, 'Bar', Versioned::DRAFT);
// Ensure correct call is made to Solr
$this->getServiceMock(['addDocument', 'commit'])
->expects($this->exactly(2))
->method('addDocument')
->withConsecutive(
[
$this->equalTo($doc1),
$this->anything(),
$this->anything(),
$this->anything(),
$this->anything()
],
[
$this->equalTo($doc2),
$this->anything(),
$this->anything(),
$this->anything(),
$this->anything()
]
[$this->equalTo($doc1)],
[$this->equalTo($doc2)]
);
SearchUpdater::flush_dirty_indexes();
// Check that write updates Live
Versioned::set_stage('Stage');
Versioned::set_stage(Versioned::DRAFT);
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Foo'));
$item->write();
$item->copyVersionToStage('Stage', 'Live');
$item->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
$object = new SolrIndexVersionedTest_Object(array('TestText' => 'Bar'));
$object->write();
$object->copyVersionToStage('Stage', 'Live');
$object->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
$doc1 = $this->getSolrDocument(SearchVariantVersionedTest_Item::class, $item, 'Foo', 'Stage');
$doc2 = $this->getSolrDocument(SearchVariantVersionedTest_Item::class, $item, 'Foo', 'Live');
$doc3 = $this->getSolrDocument(SolrIndexVersionedTest_Object::class, $object, 'Bar', 'Stage');
$doc4 = $this->getSolrDocument(SolrIndexVersionedTest_Object::class, $object, 'Bar', 'Live');
$doc1 = $this->getSolrDocument(SearchVariantVersionedTest_Item::class, $item, 'Foo', Versioned::DRAFT);
$doc2 = $this->getSolrDocument(SearchVariantVersionedTest_Item::class, $item, 'Foo', Versioned::LIVE);
$doc3 = $this->getSolrDocument(SolrIndexVersionedTest_Object::class, $object, 'Bar', Versioned::DRAFT);
$doc4 = $this->getSolrDocument(SolrIndexVersionedTest_Object::class, $object, 'Bar', Versioned::LIVE);
// Ensure correct call is made to Solr
$this->getServiceMock(['addDocument', 'commit'])
->expects($this->exactly(4))
->method('addDocument')
->withConsecutive(
[
$this->equalTo($doc1),
$this->anything(),
$this->anything(),
$this->anything(),
$this->anything()
],
[
$this->equalTo($doc2),
$this->anything(),
$this->anything(),
$this->anything(),
$this->anything()
],
[
$this->equalTo($doc3),
$this->anything(),
$this->anything(),
$this->anything(),
$this->anything()
],
[
$this->equalTo($doc4),
$this->anything(),
$this->anything(),
$this->anything(),
$this->anything()
]
[$doc1],
[$doc2],
[$doc3],
[$doc4]
);
SearchUpdater::flush_dirty_indexes();
@ -205,12 +169,12 @@ class SolrIndexVersionedTest extends SapphireTest
public function testDelete()
{
// Delete the live record (not the stage)
Versioned::set_stage('Stage');
Versioned::set_stage(Versioned::DRAFT);
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Too'));
$item->write();
$item->copyVersionToStage('Stage', 'Live');
Versioned::set_stage('Live');
$item->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
Versioned::set_stage(Versioned::LIVE);
$id = clone $item;
$item->delete();
@ -218,16 +182,16 @@ class SolrIndexVersionedTest extends SapphireTest
$this->getServiceMock(['addDocument', 'commit', 'deleteById'])
->expects($this->exactly(1))
->method('deleteById')
->with($this->equalTo($this->getExpectedDocumentId($id, 'Live')));
->with($this->getExpectedDocumentId($id, Versioned::LIVE));
SearchUpdater::flush_dirty_indexes();
// Delete the stage record
Versioned::set_stage('Stage');
Versioned::set_stage(Versioned::DRAFT);
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Too'));
$item->write();
$item->copyVersionToStage('Stage', 'Live');
$item->copyVersionToStage(Versioned::DRAFT, Versioned::LIVE);
$id = clone $item;
$item->delete();
@ -235,7 +199,7 @@ class SolrIndexVersionedTest extends SapphireTest
$this->getServiceMock(['addDocument', 'commit', 'deleteById'])
->expects($this->exactly(1))
->method('deleteById')
->with($this->equalTo($this->getExpectedDocumentId($id, 'Stage')));
->with($this->getExpectedDocumentId($id, Versioned::DRAFT));
SearchUpdater::flush_dirty_indexes();
}

View File

@ -1,39 +0,0 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest;
if (!class_exists('\Phockito')) {
return;
}
\Phockito::include_hamcrest(false);
class SolrDocumentMatcher extends \Hamcrest_BaseMatcher
{
protected $properties;
public function __construct($properties)
{
$this->properties = $properties;
}
public function describeTo(\Hamcrest_Description $description)
{
$description->appendText('\Apache_Solr_Document with properties '.var_export($this->properties, true));
}
public function matches($item)
{
if (! ($item instanceof \Apache_Solr_Document)) {
return false;
}
foreach ($this->properties as $key => $value) {
if ($item->{$key} != $value) {
return false;
}
}
return true;
}
}

View File

@ -49,17 +49,13 @@ class SolrReindexQueuedTest extends SapphireTest
protected function setUp()
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
parent::setUp();
if (!interface_exists('Symbiote\QueuedJobs\Services\QueuedJob')) {
if (!interface_exists(QueuedJob::class)) {
$this->skipTest = true;
return $this->markTestSkipped("These tests need the QueuedJobs module installed to run");
}
Config::modify()->set(QueuedJobService::class, 'use_shutdown_function', false);
// Set queued handler for reindex
Config::modify()->set(Injector::class, SolrReindexHandler::class, array(
'class' => SolrReindexQueuedHandler::class

View File

@ -43,8 +43,6 @@ class SolrReindexTest extends SapphireTest
protected function setUp()
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
parent::setUp();
// Set test handler for reindex

View File

@ -0,0 +1,37 @@
<?php
namespace SilverStripe\FullTextSearch\Tests\State;
use SilverStripe\Core\Config\Config;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Dev\State\TestState;
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
use Symbiote\QueuedJobs\Services\QueuedJobService;
class FullTextSearchState implements TestState
{
public function setUp(SapphireTest $test)
{
// noop
}
public function tearDown(SapphireTest $test)
{
SearchVariant::clear_variant_cache();
}
public function setUpOnce($class)
{
Config::modify()->set(SearchUpdater::class, 'flush_on_shutdown', false);
if (class_exists(QueuedJobService::class)) {
Config::modify()->set(QueuedJobService::class, 'use_shutdown_function', false);
}
}
public function tearDownOnce($class)
{
// noop
}
}