mirror of
https://github.com/silverstripe/silverstripe-fulltextsearch
synced 2024-10-22 14:05:29 +02:00
Merge remote-tracking branch 'upstream/compat4/btasker' into compat/4marco
This commit is contained in:
commit
572c17a00e
24
.travis.yml
24
.travis.yml
@ -7,24 +7,38 @@ sudo: false
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
|
||||
env:
|
||||
- DB=MYSQL CORE_RELEASE=3.2
|
||||
- DB=MYSQL CORE_RELEASE=4
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- php: 5.6
|
||||
env: DB=MYSQL CORE_RELEASE=3.2
|
||||
env: DB=MYSQL CORE_RELEASE=4
|
||||
- php: 5.6
|
||||
env: DB=MYSQL CORE_RELEASE=3.3 SUBSITES=1
|
||||
# env: DB=MYSQL CORE_RELEASE=4 SUBSITES=1
|
||||
- php: 5.6
|
||||
env: DB=MYSQL CORE_RELEASE=3.3 QUEUEDJOBS=1
|
||||
env: DB=MYSQL CORE_RELEASE=4 QUEUEDJOBS=1
|
||||
- php: 7.0
|
||||
env: DB=MYSQL CORE_RELEASE=4
|
||||
- php: 7.0
|
||||
# env: DB=MYSQL CORE_RELEASE=4 SUBSITES=1
|
||||
- php: 7.0
|
||||
env: DB=MYSQL CORE_RELEASE=4 QUEUEDJOBS=1
|
||||
- php: 7.1
|
||||
env: DB=MYSQL CORE_RELEASE=4
|
||||
- php: 7.1
|
||||
# env: DB=MYSQL CORE_RELEASE=4 SUBSITES=1
|
||||
- php: 7.1
|
||||
env: DB=MYSQL CORE_RELEASE=4 QUEUEDJOBS=1
|
||||
|
||||
before_script:
|
||||
- composer self-update || true
|
||||
- git clone git://github.com/silverstripe-labs/silverstripe-travis-support.git ~/travis-support
|
||||
- "if [ \"$SUBSITES\" = \"\" -a \"$QUEUEDJOBS\" = \"\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss; fi"
|
||||
- "if [ \"$SUBSITES\" = \"1\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/subsites; fi"
|
||||
# - "if [ \"$SUBSITES\" = \"1\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/subsites; fi"
|
||||
- "if [ \"$QUEUEDJOBS\" = \"1\" ]; then php ~/travis-support/travis_setup.php --source `pwd` --target ~/builds/ss --require silverstripe/queuedjobs; fi"
|
||||
- cd ~/builds/ss
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
SilverStripe\Core\Injector\Injector:
|
||||
RequestProcessor:
|
||||
SilverStripe\Control\RequestProcessor:
|
||||
properties:
|
||||
filters:
|
||||
- '%$SearchUpdater_BindManipulationCaptureFilter'
|
||||
- '%$SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater_BindManipulationCaptureFilter'
|
||||
|
@ -1,3 +1,3 @@
|
||||
SilverStripe\ORM\DataObject\DataObject:
|
||||
SilverStripe\ORM\DataObject:
|
||||
extensions:
|
||||
- 'SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater_ObjectHandler'
|
||||
|
@ -7,23 +7,11 @@ SilverStripe\Core\Injector\Injector:
|
||||
SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexHandler:
|
||||
class: SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexImmediateHandler
|
||||
SilverStripe\FullTextSearch\Utils\Logging\SearchLogFactory:
|
||||
class: 'SilverStripe\FullTextSearch\Utils\Logging\MonologFactory'
|
||||
---
|
||||
Name: messagequeueprocessor
|
||||
Only:
|
||||
ModuleExists: messagequeue
|
||||
Except:
|
||||
Environment: 'dev'
|
||||
---
|
||||
SilverStripe\Core\Injector\Injector:
|
||||
SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor:
|
||||
class: SilverStripe\FullTextSearch\Search\Processors\SearchUpdateMessageQueueProcessor
|
||||
SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexHandler:
|
||||
class: SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexMessageHandler
|
||||
class: SilverStripe\FullTextSearch\Utils\Logging\MonologFactory
|
||||
---
|
||||
Name: queuedjobprocessor
|
||||
Only:
|
||||
ModuleExists: queuedjobs
|
||||
ModuleExists: silverstripe/queuedjobs
|
||||
Except:
|
||||
Environment: 'dev'
|
||||
---
|
||||
|
@ -1,11 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search;
|
||||
|
||||
use ReflectionClass;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\FullTextSearch\Solr\SearchIndex;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* Base class to manage active search indexes.
|
||||
*/
|
||||
|
@ -43,15 +43,11 @@ class SearchIntrospection
|
||||
$classes = array_unique(array_merge($classes, array_values(ClassInfo::subclassesFor($class))));
|
||||
}
|
||||
|
||||
$idx = array_search('SilverStripe\View\ViewableData', $classes);
|
||||
$idx = array_search('SilverStripe\ORM\DataObject', $classes);
|
||||
if ($idx !== false) {
|
||||
array_splice($classes, 0, $idx+1);
|
||||
}
|
||||
|
||||
$idx = array_search('SilverStripe\Core\Object', $classes);
|
||||
if ($idx !== false) {
|
||||
array_splice($classes, 0, $idx+1);
|
||||
}
|
||||
//@todo find another way to determine if a dataobject does not have a table
|
||||
// if ($dataOnly) {
|
||||
// foreach ($classes as $i => $class) {
|
||||
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Captures;
|
||||
|
||||
use SilverStripe\ORM\Connect\MySQLDatabase;
|
||||
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
|
||||
|
||||
class SearchManipulateCapture_MySQLDatabase extends MySQLDatabase {
|
||||
|
||||
public $isManipulationCapture = true;
|
||||
|
||||
public function manipulate($manipulation) {
|
||||
$res = parent::manipulate($manipulation);
|
||||
SearchUpdater::handle_manipulation($manipulation);
|
||||
return $res;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Captures;
|
||||
|
||||
use SilverStripe\PostgreSQL\PostgreSQLDatabase;
|
||||
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
|
||||
|
||||
if (!class_exists('PostgreSQLDatabase')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class SearchManipulateCapture_PostgreSQLDatabase extends PostgreSQLDatabase {
|
||||
|
||||
public $isManipulationCapture = true;
|
||||
|
||||
public function manipulate($manipulation) {
|
||||
$res = parent::manipulate($manipulation);
|
||||
SearchUpdater::handle_manipulation($manipulation);
|
||||
return $res;
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Captures;
|
||||
|
||||
use SilverStripe\SQLite\SQLite3Database;
|
||||
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
|
||||
|
||||
if (!class_exists('SQLite3Database')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class SearchManipulateCapture_SQLite3Database extends SQLite3Database {
|
||||
|
||||
public $isManipulationCapture = true;
|
||||
|
||||
public function manipulate($manipulation) {
|
||||
$res = parent::manipulate($manipulation);
|
||||
SearchUpdater::handle_manipulation($manipulation);
|
||||
return $res;
|
||||
}
|
||||
}
|
@ -6,12 +6,14 @@ use Exception;
|
||||
use InvalidArgumentException;
|
||||
use SilverStripe\View\ViewableData;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectSchema;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\FullTextSearch\Utils\MultipleArrayIterator;
|
||||
use SilverStripe\ORM\Queries\SQLSelect;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
|
||||
/**
|
||||
* SearchIndex is the base index class. Each connector will provide a subclass of this that
|
||||
* provides search engine specific behavior.
|
||||
@ -76,7 +78,7 @@ abstract class SearchIndex extends ViewableData
|
||||
$sources = $this->getClasses();
|
||||
|
||||
foreach ($sources as $source => $options) {
|
||||
$sources[$source]['base'] = ClassInfo::baseDataClass($source);
|
||||
$sources[$source]['base'] = DataObject::getSchema()->baseDataClass($source);
|
||||
$sources[$source]['lookup_chain'] = array();
|
||||
}
|
||||
|
||||
@ -94,22 +96,24 @@ abstract class SearchIndex extends ViewableData
|
||||
|
||||
foreach (SearchIntrospection::hierarchy($source, $options['include_children']) as $dataclass) {
|
||||
$singleton = singleton($dataclass);
|
||||
$schema = DataObject::getSchema();
|
||||
$className = $singleton->getClassName();
|
||||
|
||||
if ($hasOne = $singleton->hasOne($lookup)) {
|
||||
if ($hasOne = $schema->hasOneComponent($className, $lookup)) {
|
||||
$class = $hasOne;
|
||||
$options['lookup_chain'][] = array(
|
||||
'call' => 'method', 'method' => $lookup,
|
||||
'through' => 'has_one', 'class' => $dataclass, 'otherclass' => $class, 'foreignkey' => "{$lookup}ID"
|
||||
);
|
||||
} elseif ($hasMany = $singleton->hasMany($lookup)) {
|
||||
} elseif ($hasMany = $schema->hasManyComponent($className, $lookup)) {
|
||||
$class = $hasMany;
|
||||
$options['multi_valued'] = true;
|
||||
$options['lookup_chain'][] = array(
|
||||
'call' => 'method', 'method' => $lookup,
|
||||
'through' => 'has_many', 'class' => $dataclass, 'otherclass' => $class, 'foreignkey' => $singleton->getRemoteJoinField($lookup, 'has_many')
|
||||
'through' => 'has_many', 'class' => $dataclass, 'otherclass' => $class, 'foreignkey' => $schema->getRemoteJoinField($className, $lookup, 'has_many')
|
||||
);
|
||||
} elseif ($manyMany = $singleton->manyMany($lookup)) {
|
||||
$class = $manyMany[1];
|
||||
} elseif ($manyMany = $schema->manyManyComponent($className, $lookup)) {
|
||||
$class = $manyMany[2];
|
||||
$options['multi_valued'] = true;
|
||||
$options['lookup_chain'][] = array(
|
||||
'call' => 'method', 'method' => $lookup,
|
||||
@ -222,7 +226,7 @@ abstract class SearchIndex extends ViewableData
|
||||
}
|
||||
|
||||
if (!DataObject::getSchema()->classHasTable($class)) {
|
||||
throw new InvalidArgumentException('Can\'t add classes which don\'t have data tables (no $db or $has_one set on the class)');
|
||||
throw new \InvalidArgumentException('Can\'t add classes which don\'t have data tables (no $db or $has_one set on the class)');
|
||||
}
|
||||
|
||||
$options = array_merge(array(
|
||||
@ -299,13 +303,16 @@ abstract class SearchIndex extends ViewableData
|
||||
foreach ($this->getClasses() as $class => $options) {
|
||||
foreach (SearchIntrospection::hierarchy($class, $includeSubclasses, true) as $dataclass) {
|
||||
$fields = DataObject::getSchema()->databaseFields($class);
|
||||
|
||||
foreach ($fields as $field => $type) {
|
||||
if (preg_match('/^(\w+)\(/', $type, $match)) {
|
||||
$type = $match[1];
|
||||
}
|
||||
list($type, $args) = Object::parse_class_spec($type);
|
||||
if (is_subclass_of($type, 'SilverStripe\ORM\FieldType\DBString')) {
|
||||
|
||||
// Get class from shortName
|
||||
$object = Injector::inst()->get($type, false, ['Name' => 'test']);
|
||||
|
||||
if (is_subclass_of(get_class($object), 'SilverStripe\ORM\FieldType\DBString')) {
|
||||
$this->addFulltextField($field);
|
||||
}
|
||||
}
|
||||
@ -470,9 +477,8 @@ abstract class SearchIndex extends ViewableData
|
||||
}
|
||||
|
||||
$object = $next;
|
||||
}
|
||||
// Otherwise, just call
|
||||
else {
|
||||
} else {
|
||||
// Otherwise, just call
|
||||
if ($step['call'] == 'method') {
|
||||
$method = $step['method'];
|
||||
$object = $object->$method();
|
||||
@ -502,9 +508,10 @@ abstract class SearchIndex extends ViewableData
|
||||
* @param Exception $e
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function warn($e) {
|
||||
public static function warn($e)
|
||||
{
|
||||
// Noisy errors during testing
|
||||
if(class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
|
||||
if (class_exists('SapphireTest', false) && SapphireTest::is_running_test()) {
|
||||
throw $e;
|
||||
}
|
||||
SS_Log::log($e, SS_Log::WARN);
|
||||
@ -529,7 +536,7 @@ abstract class SearchIndex extends ViewableData
|
||||
// First, if this object is directly contained in the index, add it
|
||||
foreach ($this->classes as $searchclass => $options) {
|
||||
if ($searchclass == $class || ($options['include_children'] && is_subclass_of($class, $searchclass))) {
|
||||
$base = ClassInfo::baseDataClass($searchclass);
|
||||
$base = DataObject::getSchema()->baseDataClass($searchclass);
|
||||
$dirty[$base] = array();
|
||||
foreach ($statefulids as $statefulid) {
|
||||
$key = serialize($statefulid);
|
||||
@ -557,19 +564,25 @@ abstract class SearchIndex extends ViewableData
|
||||
$ids = array($id);
|
||||
|
||||
foreach ($derivation['chain'] as $step) {
|
||||
// Use TableName for queries
|
||||
$tableName = DataObject::getSchema()->tableName($step['class']);
|
||||
|
||||
if ($step['through'] == 'has_one') {
|
||||
$sql = new SQLQuery('"ID"', '"'.$step['class'].'"', '"'.$step['foreignkey'].'" IN ('.implode(',', $ids).')');
|
||||
$sql = new SQLSelect('"ID"', '"'.$tableName.'"', '"'.$step['foreignkey'].'" IN ('.implode(',', $ids).')');
|
||||
singleton($step['class'])->extend('augmentSQL', $sql);
|
||||
|
||||
$ids = $sql->execute()->column();
|
||||
} elseif ($step['through'] == 'has_many') {
|
||||
$sql = new SQLQuery('"'.$step['class'].'"."ID"', '"'.$step['class'].'"', '"'.$step['otherclass'].'"."ID" IN ('.implode(',', $ids).')');
|
||||
$sql->addInnerJoin($step['otherclass'], '"'.$step['class'].'"."ID" = "'.$step['otherclass'].'"."'.$step['foreignkey'].'"');
|
||||
// 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();
|
||||
}
|
||||
|
||||
|
||||
if (empty($ids)) {
|
||||
break;
|
||||
}
|
||||
@ -597,8 +610,8 @@ abstract class SearchIndex extends ViewableData
|
||||
|
||||
/** !! These should be implemented by the full text search engine */
|
||||
|
||||
abstract public function add($object) ;
|
||||
abstract public function delete($base, $id, $state) ;
|
||||
abstract public function add($object);
|
||||
abstract public function delete($base, $id, $state);
|
||||
|
||||
abstract public function commit();
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Indexes;
|
||||
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex;
|
||||
|
||||
/**
|
||||
* A search index that does nothing. Useful for testing
|
||||
*/
|
||||
|
@ -1,5 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Processors;
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
|
||||
/**
|
||||
* Provides batching of search updates
|
||||
*/
|
||||
|
@ -1,9 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Processors;
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\FieldType\DBDatetime;
|
||||
use DateTime;
|
||||
use DateInterval;
|
||||
use stdClass;
|
||||
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJobService;
|
||||
|
||||
class SearchUpdateCommitJobProcessor implements QueuedJob
|
||||
{
|
||||
/**
|
||||
@ -81,7 +94,7 @@ class SearchUpdateCommitJobProcessor implements QueuedJob
|
||||
public static function queue($dirty = true, $startAfter = null)
|
||||
{
|
||||
$commit = Injector::inst()->create(__CLASS__);
|
||||
$id = singleton('QueuedJobService')->queueJob($commit, $startAfter);
|
||||
$id = singleton(QueuedJobService::class)->queueJob($commit, $startAfter);
|
||||
|
||||
if ($dirty) {
|
||||
$indexes = FullTextSearch::get_indexes();
|
||||
@ -159,7 +172,7 @@ class SearchUpdateCommitJobProcessor implements QueuedJob
|
||||
// This could occur if we completed a searchupdate job in a prior request, as well as in
|
||||
// the current request
|
||||
$cooldown = Config::inst()->get(__CLASS__, 'cooldown');
|
||||
$now = new DateTime(SS_Datetime::now()->getValue());
|
||||
$now = new DateTime(DBDatetime::now()->getValue());
|
||||
$now->add(new DateInterval('PT'.$cooldown.'S'));
|
||||
$runat = $now->Format('Y-m-d H:i:s');
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Processors;
|
||||
|
||||
class SearchUpdateImmediateProcessor extends SearchUpdateProcessor
|
||||
{
|
||||
public function triggerProcessing()
|
||||
|
@ -1,19 +0,0 @@
|
||||
<?php
|
||||
namespace SilverStripe\FullTextSearch\Search\Processors;
|
||||
class SearchUpdateMessageQueueProcessor extends SearchUpdateProcessor
|
||||
{
|
||||
/**
|
||||
* The MessageQueue to use when processing updates
|
||||
* @config
|
||||
* @var string
|
||||
*/
|
||||
private static $reindex_queue = "search_indexing";
|
||||
|
||||
public function triggerProcessing()
|
||||
{
|
||||
MessageQueue::send(
|
||||
Config::inst()->get('SearchMessageQueueUpdater', 'reindex_queue'),
|
||||
new MethodInvocationMessage($this, "process")
|
||||
);
|
||||
}
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Processors;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
|
||||
abstract class SearchUpdateProcessor
|
||||
{
|
||||
/**
|
||||
@ -33,7 +39,7 @@ abstract class SearchUpdateProcessor
|
||||
|
||||
public function addDirtyIDs($class, $statefulids, $index)
|
||||
{
|
||||
$base = ClassInfo::baseDataClass($class);
|
||||
$base = DataObject::getSchema()->baseDataClass($class);
|
||||
$forclass = isset($this->dirty[$base]) ? $this->dirty[$base] : array();
|
||||
|
||||
foreach ($statefulids as $statefulid) {
|
||||
|
@ -1,9 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Processors;
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use stdClass;
|
||||
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJobService;
|
||||
|
||||
class SearchUpdateQueuedJobProcessor extends SearchUpdateBatchedProcessor implements QueuedJob
|
||||
{
|
||||
/**
|
||||
@ -18,7 +26,7 @@ class SearchUpdateQueuedJobProcessor extends SearchUpdateBatchedProcessor implem
|
||||
public function triggerProcessing()
|
||||
{
|
||||
parent::triggerProcessing();
|
||||
singleton('QueuedJobService')->queueJob($this);
|
||||
singleton(QueuedJobService::class)->queueJob($this);
|
||||
}
|
||||
|
||||
public function getTitle()
|
||||
|
@ -1,11 +1,15 @@
|
||||
<?php
|
||||
namespace SilverStripe\FullTextSearch\Search\Indexes;
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Queries;
|
||||
|
||||
use SilverStripe\View\ViewableData;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Represents a search query
|
||||
*
|
||||
* API very much still in flux.
|
||||
*/
|
||||
use SilverStripe\View\ViewableData;
|
||||
class SearchQuery extends ViewableData
|
||||
{
|
||||
public static $missing = null;
|
||||
|
@ -2,12 +2,17 @@
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Updaters;
|
||||
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateImmediateProcessor;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* This class is responsible for capturing changes to DataObjects and triggering index updates of the resulting dirty index
|
||||
* items.
|
||||
@ -20,8 +25,6 @@ use SilverStripe\Core\ClassInfo;
|
||||
*
|
||||
* TODO: The way we bind in is awful hacky.
|
||||
*/
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
|
||||
class SearchUpdater extends Object
|
||||
{
|
||||
@ -32,44 +35,30 @@ class SearchUpdater extends Object
|
||||
{
|
||||
global $databaseConfig;
|
||||
|
||||
$current = DB::getConn();
|
||||
if (!$current || !$current->currentDatabase() || @$current->isManipulationCapture) {
|
||||
$current = DB::get_conn();
|
||||
|
||||
if (!$current || !$current->getSelectedDatabase() || @$current->isManipulationCapture) {
|
||||
return;
|
||||
} // If not yet set, or its already captured, just return
|
||||
|
||||
$type = get_class($current);
|
||||
$file = TEMP_FOLDER."/.cache.SMC.$type";
|
||||
$type = (new ReflectionClass($current))->getShortName();
|
||||
$dbClass = 'SilverStripe\FullTextSearch\Captures\SearchManipulateCapture_' . $type;
|
||||
|
||||
if (!is_file($file)) {
|
||||
file_put_contents($file, "<?php
|
||||
class SearchManipulateCapture_$type extends $type {
|
||||
public \$isManipulationCapture = true;
|
||||
|
||||
function manipulate(\$manipulation) {
|
||||
\$res = parent::manipulate(\$manipulation);
|
||||
SearchUpdater::handle_manipulation(\$manipulation);
|
||||
return \$res;
|
||||
}
|
||||
}
|
||||
");
|
||||
// Check if Capture class exists.
|
||||
if (!class_exists($dbClass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
require_once($file);
|
||||
$dbClass = 'SearchManipulateCapture_'.$type;
|
||||
|
||||
/** @var SS_Database $captured */
|
||||
$captured = new $dbClass($databaseConfig);
|
||||
|
||||
// Framework 3.2+ ORM needs some dependencies set
|
||||
if (method_exists($captured, "setConnector")) {
|
||||
$captured->setConnector($current->getConnector());
|
||||
$captured->setQueryBuilder($current->getQueryBuilder());
|
||||
$captured->setSchemaManager($current->getSchemaManager());
|
||||
}
|
||||
$captured->setConnector($current->getConnector());
|
||||
$captured->setQueryBuilder($current->getQueryBuilder());
|
||||
$captured->setSchemaManager($current->getSchemaManager());
|
||||
|
||||
// The connection might have had it's name changed (like if we're currently in a test)
|
||||
$captured->selectDatabase($current->currentDatabase());
|
||||
DB::setConn($captured);
|
||||
$captured->selectDatabase($current->getSelectedDatabase());
|
||||
DB::set_conn($captured);
|
||||
}
|
||||
|
||||
public static $registered = false;
|
||||
@ -90,7 +79,9 @@ class SearchUpdater extends Object
|
||||
{
|
||||
// First, extract any state that is in the manipulation itself
|
||||
foreach ($manipulation as $table => $details) {
|
||||
$manipulation[$table]['class'] = $table;
|
||||
if (!isset($manipulation[$table]['class'])) {
|
||||
$manipulation[$table]['class'] = DataObject::getSchema()->tableClass($table);
|
||||
}
|
||||
$manipulation[$table]['state'] = array();
|
||||
}
|
||||
|
||||
@ -110,7 +101,7 @@ class SearchUpdater extends Object
|
||||
$class = $details['class'];
|
||||
$fields = isset($details['fields']) ? $details['fields'] : array();
|
||||
|
||||
$base = ClassInfo::baseDataClass($class);
|
||||
$base = DataObject::getSchema()->baseDataClass($class);
|
||||
$key = "$id:$base:".serialize($state);
|
||||
|
||||
$statefulids = array(array('id' => $id, 'state' => $state));
|
||||
@ -171,7 +162,7 @@ class SearchUpdater extends Object
|
||||
foreach ($dirtyids as $dirtyclass => $ids) {
|
||||
if ($ids) {
|
||||
if (!self::$processor) {
|
||||
self::$processor = Injector::inst()->create('SearchUpdateProcessor');
|
||||
self::$processor = Injector::inst()->create(SearchUpdateImmediateProcessor::class);
|
||||
}
|
||||
self::$processor->addDirtyIDs($dirtyclass, $ids, $index);
|
||||
}
|
||||
@ -184,10 +175,9 @@ class SearchUpdater extends Object
|
||||
|
||||
// Don't do it if we're testing - there's no database connection outside the test methods, so we'd
|
||||
// just get errors
|
||||
$runningTests = class_exists('SapphireTest', false) && SapphireTest::is_running_test();
|
||||
|
||||
if (self::$processor && !self::$registered && !$runningTests) {
|
||||
register_shutdown_function(array("SearchUpdater", "flush_dirty_indexes"));
|
||||
if (self::$processor && !self::$registered && !SapphireTest::is_running_test()) {
|
||||
register_shutdown_function(array(SearchUpdater::class, "flush_dirty_indexes"));
|
||||
self::$registered = true;
|
||||
}
|
||||
}
|
||||
@ -214,6 +204,3 @@ class SearchUpdater extends Object
|
||||
self::$processor = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Updaters;
|
||||
|
||||
use SilverStripe\ORM\DataExtension;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
/**
|
||||
* Delete operations do not use database manipulations.
|
||||
@ -43,7 +46,7 @@ class SearchUpdater_ObjectHandler extends DataExtension
|
||||
$id = $this->owner->ID;
|
||||
$class = $this->owner->ClassName;
|
||||
$state = SearchVariant::current_state($class);
|
||||
$base = ClassInfo::baseDataClass($class);
|
||||
$base = DataObject::getSchema()->baseDataClass($class);
|
||||
$key = "$id:$base:".serialize($state);
|
||||
|
||||
$statefulids = array(array(
|
||||
@ -63,4 +66,4 @@ class SearchUpdater_ObjectHandler extends DataExtension
|
||||
|
||||
SearchUpdater::process_writes($writes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Variants;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\FullTextSearch\Utils\CombinationsArrayIterator;
|
||||
use ReflectionClass;
|
||||
|
||||
/**
|
||||
* A Search Variant handles decorators and other situations where the items to reindex or search through are modified
|
||||
* from the default state - for instance, dealing with Versioned or Subsite
|
||||
@ -22,7 +28,10 @@ abstract class SearchVariant
|
||||
* Return false if there is something missing from the environment (probably a
|
||||
* not installed module) that means this variant can't apply to any class
|
||||
*/
|
||||
abstract public function appliesToEnvironment();
|
||||
public function appliesToEnvironment()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this variant applies to the passed class & subclass
|
||||
@ -74,7 +83,7 @@ abstract class SearchVariant
|
||||
{
|
||||
if (!$class) {
|
||||
if (self::$variants === null) {
|
||||
$classes = ClassInfo::subclassesFor('SearchVariant');
|
||||
$classes = ClassInfo::subclassesFor(static::class);
|
||||
|
||||
$concrete = array();
|
||||
foreach ($classes as $variantclass) {
|
||||
|
@ -1,6 +1,13 @@
|
||||
<?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()
|
||||
@ -49,7 +56,7 @@ class SearchVariantSiteTreeSubsitesPolyhome extends SearchVariant
|
||||
'name' => '_subsite',
|
||||
'field' => '_subsite',
|
||||
'fullfield' => '_subsite',
|
||||
'base' => ClassInfo::baseDataClass($class),
|
||||
'base' => DataObject::getSchema()->baseDataClass($class),
|
||||
'origin' => $class,
|
||||
'type' => 'Int',
|
||||
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
|
||||
@ -78,7 +85,7 @@ class SearchVariantSiteTreeSubsitesPolyhome extends SearchVariant
|
||||
}
|
||||
|
||||
if (self::$subsites === null) {
|
||||
$query = new SQLQuery('ID', 'Subsite');
|
||||
$query = new SQLSelect('ID', 'Subsite');
|
||||
self::$subsites = array_merge(array('0'), $query->execute()->column());
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Variants;
|
||||
|
||||
use SilverStripe\ORM\Queries\SQLSelect;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Security\Permission;
|
||||
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
|
||||
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
|
||||
|
||||
if (!class_exists('Subsite')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class SearchVariantSubsites extends SearchVariant
|
||||
{
|
||||
public function appliesToEnvironment()
|
||||
@ -53,7 +65,7 @@ class SearchVariantSubsites extends SearchVariant
|
||||
'name' => '_subsite',
|
||||
'field' => '_subsite',
|
||||
'fullfield' => '_subsite',
|
||||
'base' => ClassInfo::baseDataClass($class),
|
||||
'base' => DataObject::getSchema()->baseDataClass($class),
|
||||
'origin' => $class,
|
||||
'type' => 'Int',
|
||||
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
|
||||
@ -74,7 +86,7 @@ class SearchVariantSubsites extends SearchVariant
|
||||
public function extractManipulationWriteState(&$writes)
|
||||
{
|
||||
$self = get_class($this);
|
||||
$query = new SQLQuery('"ID"', '"Subsite"');
|
||||
$query = new SQLSelect('"ID"', '"Subsite"');
|
||||
$subsites = array_merge(array('0'), $query->execute()->column());
|
||||
|
||||
foreach ($writes as $key => $write) {
|
||||
|
@ -1,21 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Variants;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
|
||||
|
||||
class SearchVariantVersioned extends SearchVariant
|
||||
{
|
||||
public function appliesToEnvironment()
|
||||
{
|
||||
return class_exists('Versioned');
|
||||
}
|
||||
|
||||
public function appliesTo($class, $includeSubclasses)
|
||||
{
|
||||
return SearchIntrospection::has_extension($class, 'Versioned', $includeSubclasses);
|
||||
return SearchIntrospection::has_extension($class, Versioned::class, $includeSubclasses);
|
||||
}
|
||||
|
||||
public function currentState()
|
||||
{
|
||||
return Versioned::current_stage();
|
||||
return Versioned::get_stage();
|
||||
}
|
||||
public function reindexStates()
|
||||
{
|
||||
@ -23,7 +25,7 @@ class SearchVariantVersioned extends SearchVariant
|
||||
}
|
||||
public function activateState($state)
|
||||
{
|
||||
Versioned::reading_stage($state);
|
||||
Versioned::set_stage($state);
|
||||
}
|
||||
|
||||
public function alterDefinition($class, $index)
|
||||
@ -34,7 +36,7 @@ class SearchVariantVersioned extends SearchVariant
|
||||
'name' => '_versionedstage',
|
||||
'field' => '_versionedstage',
|
||||
'fullfield' => '_versionedstage',
|
||||
'base' => ClassInfo::baseDataClass($class),
|
||||
'base' => DataObject::getSchema()->baseDataClass($class),
|
||||
'origin' => $class,
|
||||
'type' => 'String',
|
||||
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
|
||||
@ -43,7 +45,7 @@ class SearchVariantVersioned extends SearchVariant
|
||||
|
||||
public function alterQuery($query, $index)
|
||||
{
|
||||
$stage = Versioned::current_stage();
|
||||
$stage = $this->currentState();
|
||||
$query->filter('_versionedstage', array($stage, SearchQuery::$missing));
|
||||
}
|
||||
|
||||
@ -56,7 +58,7 @@ class SearchVariantVersioned extends SearchVariant
|
||||
$stage = 'Stage';
|
||||
|
||||
if (preg_match('/^(.*)_Live$/', $table, $matches)) {
|
||||
$class = $matches[1];
|
||||
$class = DataObject::getSchema()->tableClass($matches[1]);
|
||||
$stage = 'Live';
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: elliot
|
||||
* Date: 21/04/17
|
||||
* Time: 1:13 PM
|
||||
*/
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Search\Variants;
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr;
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Object;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\FullTextSearch\Solr\Services\Solr4Service;
|
||||
use SilverStripe\FullTextSearch\Solr\Services\Solr3Service;
|
||||
|
||||
class Solr
|
||||
{
|
||||
@ -80,13 +82,13 @@ class Solr
|
||||
|
||||
if (version_compare($version, '4', '>=')) {
|
||||
$versionDefaults = array(
|
||||
'service' => 'Solr4Service',
|
||||
'service' => Solr4Service::class,
|
||||
'extraspath' => Director::baseFolder().'/fulltextsearch/conf/solr/4/extras/',
|
||||
'templatespath' => Director::baseFolder().'/fulltextsearch/conf/solr/4/templates/',
|
||||
);
|
||||
} else {
|
||||
$versionDefaults = array(
|
||||
'service' => 'Solr3Service',
|
||||
'service' => Solr3Service::class,
|
||||
'extraspath' => Director::baseFolder().'/fulltextsearch/conf/solr/3/extras/',
|
||||
'templatespath' => Director::baseFolder().'/fulltextsearch/conf/solr/3/templates/',
|
||||
);
|
||||
|
@ -1,9 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr;
|
||||
Solr::include_client_api();
|
||||
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\FulltextSearch\Search\Indexes\SearchIndex;
|
||||
use SilverStripe\FullTextSearch\Solr\Services\SolrService;
|
||||
use SilverStripe\FulltextSearch\Search\Queries\SearchQuery;
|
||||
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery_Range;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\FulltextSearch\Search\SearchIntrospection;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\FieldType\DBField;
|
||||
use SilverStripe\ORM\PaginatedList;
|
||||
use SilverStripe\View\ArrayData;
|
||||
|
||||
abstract class SolrIndex extends SearchIndex
|
||||
{
|
||||
@ -319,7 +330,7 @@ abstract class SolrIndex extends SearchIndex
|
||||
public function setFieldBoosting($field, $level)
|
||||
{
|
||||
if (!isset($this->fulltextFields[$field])) {
|
||||
throw new InvalidArgumentException("No fulltext field $field exists on ".$this->getIndexName());
|
||||
throw new \InvalidArgumentException("No fulltext field $field exists on ".$this->getIndexName());
|
||||
}
|
||||
if ($level === null) {
|
||||
unset($this->boostedFields[$field]);
|
||||
@ -538,7 +549,10 @@ abstract class SolrIndex extends SearchIndex
|
||||
return;
|
||||
}
|
||||
|
||||
$doc->setField($field['name'], $value);
|
||||
// Only index fields that are not null
|
||||
if ($value !== null) {
|
||||
$doc->setField($field['name'], $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -546,7 +560,7 @@ abstract class SolrIndex extends SearchIndex
|
||||
{
|
||||
$includeSubs = $options['include_children'];
|
||||
|
||||
$doc = new Apache_Solr_Document();
|
||||
$doc = new \Apache_Solr_Document();
|
||||
|
||||
// Always present fields
|
||||
|
||||
@ -583,7 +597,7 @@ abstract class SolrIndex extends SearchIndex
|
||||
|
||||
foreach ($this->getClasses() as $searchclass => $options) {
|
||||
if ($searchclass == $class || ($options['include_children'] && is_subclass_of($class, $searchclass))) {
|
||||
$base = ClassInfo::baseDataClass($searchclass);
|
||||
$base = DataObject::getSchema()->baseDataClass($searchclass);
|
||||
$docs[] = $this->_addAs($object, $base, $options);
|
||||
}
|
||||
}
|
||||
@ -748,7 +762,7 @@ abstract class SolrIndex extends SearchIndex
|
||||
$offset,
|
||||
$limit,
|
||||
$params,
|
||||
Apache_Solr_Service::METHOD_POST
|
||||
\Apache_Solr_Service::METHOD_POST
|
||||
);
|
||||
|
||||
$results = new ArrayList();
|
||||
|
@ -3,9 +3,13 @@
|
||||
namespace SilverStripe\FullTextSearch\Solr\Reindex\Handlers;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\FullTextSearch\Solr\Solr;
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DB;
|
||||
|
||||
/**
|
||||
* Base class for re-indexing of solr content
|
||||
@ -18,7 +22,7 @@ abstract class SolrReindexBase implements SolrReindexHandler
|
||||
$this->processIndex($logger, $indexInstance, $batchSize, $taskName, $classes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process index for a single SolrIndex instance
|
||||
*
|
||||
@ -164,7 +168,7 @@ abstract class SolrReindexBase implements SolrReindexHandler
|
||||
|
||||
// This will slow down things a tiny bit, but it is done so that we don't timeout to the database during a reindex
|
||||
DB::query('SELECT 1');
|
||||
|
||||
|
||||
$logger->info("Done");
|
||||
}
|
||||
|
||||
@ -182,11 +186,11 @@ abstract class SolrReindexBase implements SolrReindexHandler
|
||||
protected function getRecordsInGroup(SolrIndex $indexInstance, $class, $groups, $group)
|
||||
{
|
||||
// Generate filtered list of local records
|
||||
$baseClass = ClassInfo::baseDataClass($class);
|
||||
$baseClass = DataObject::getSchema()->baseDataClass($class);
|
||||
$items = DataList::create($class)
|
||||
->where(sprintf(
|
||||
'"%s"."ID" %% \'%d\' = \'%d\'',
|
||||
$baseClass,
|
||||
DataObject::getSchema()->tableName($baseClass),
|
||||
intval($groups),
|
||||
intval($group)
|
||||
))
|
||||
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
namespace SilverStripe\FullTextSearch\Solr\Reindex\Handlers;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
if (!class_exists('MessageQueue')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class SolrReindexMessageHandler extends SolrReindexImmediateHandler
|
||||
{
|
||||
/**
|
||||
* The MessageQueue to use when processing updates
|
||||
* @config
|
||||
* @var string
|
||||
*/
|
||||
private static $reindex_queue = "search_indexing";
|
||||
|
||||
public function triggerReindex(LoggerInterface $logger, $batchSize, $taskName, $classes = null)
|
||||
{
|
||||
$queue = Config::inst()->get(__CLASS__, 'reindex_queue');
|
||||
|
||||
$logger->info('Queuing message');
|
||||
MessageQueue::send(
|
||||
$queue,
|
||||
new MethodInvocationMessage('SolrReindexMessageHandler', 'run_reindex', $batchSize, $taskName, $classes)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for message queue
|
||||
*
|
||||
* @param int $batchSize
|
||||
* @param string $taskName
|
||||
* @param array|string|null $classes
|
||||
*/
|
||||
public static function run_reindex($batchSize, $taskName, $classes = null)
|
||||
{
|
||||
// @todo Logger for message queue?
|
||||
$logger = Injector::inst()->createWithArgs('Monolog\Logger', array(strtolower(get_class())));
|
||||
|
||||
$inst = Injector::inst()->get(get_class());
|
||||
$inst->runReindex($logger, $batchSize, $taskName, $classes);
|
||||
}
|
||||
}
|
@ -4,11 +4,22 @@ namespace SilverStripe\FullTextSearch\Solr\Reindex\Handlers;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Jobs\SolrReindexQueuedJob;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Jobs\SolrReindexGroupQueuedJob;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateCommitJobProcessor;
|
||||
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJobService;
|
||||
use SilverStripe\QueuedJobs\DataObjects\QueuedJobDescriptor;
|
||||
|
||||
/**
|
||||
* Represents a queued task to start the reindex job
|
||||
*/
|
||||
@ -19,7 +30,7 @@ class SolrReindexQueuedHandler extends SolrReindexBase
|
||||
*/
|
||||
protected function getQueuedJobService()
|
||||
{
|
||||
return singleton('QueuedJobService');
|
||||
return singleton(QueuedJobService::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,7 +44,7 @@ class SolrReindexQueuedHandler extends SolrReindexBase
|
||||
$clearable = array(
|
||||
// Paused jobs need to be discarded
|
||||
QueuedJob::STATUS_PAUSED,
|
||||
|
||||
|
||||
// These types would be automatically started
|
||||
QueuedJob::STATUS_NEW,
|
||||
QueuedJob::STATUS_WAIT,
|
||||
@ -43,27 +54,28 @@ class SolrReindexQueuedHandler extends SolrReindexBase
|
||||
QueuedJob::STATUS_RUN
|
||||
);
|
||||
DB::query(sprintf(
|
||||
'UPDATE "QueuedJobDescriptor" '
|
||||
'UPDATE "%s" '
|
||||
. ' SET "JobStatus" = \'%s\''
|
||||
. ' WHERE "JobStatus" IN (\'%s\')'
|
||||
. ' AND "Implementation" = \'%s\'',
|
||||
Convert::raw2sql(DataObject::getSchema()->tableName(QueuedJobDescriptor::class)),
|
||||
Convert::raw2sql(QueuedJob::STATUS_CANCELLED),
|
||||
implode("','", Convert::raw2sql($clearable)),
|
||||
Convert::raw2sql($type)
|
||||
));
|
||||
return DB::affectedRows();
|
||||
return DB::affected_rows();
|
||||
}
|
||||
|
||||
public function triggerReindex(LoggerInterface $logger, $batchSize, $taskName, $classes = null)
|
||||
{
|
||||
// Cancel existing jobs
|
||||
$queues = $this->cancelExistingJobs('SolrReindexQueuedJob');
|
||||
$groups = $this->cancelExistingJobs('SolrReindexGroupQueuedJob');
|
||||
$queues = $this->cancelExistingJobs(SolrReindexQueuedJob::class);
|
||||
$groups = $this->cancelExistingJobs(SolrReindexGroupQueuedJob::class);
|
||||
$logger->info("Cancelled {$queues} re-index tasks and {$groups} re-index groups");
|
||||
|
||||
// Although this class is used as a service (singleton) it may also be instantiated
|
||||
// as a queuedjob
|
||||
$job = Injector::inst()->create('SolrReindexQueuedJob', $batchSize, $taskName, $classes);
|
||||
$job = Injector::inst()->create(SolrReindexQueuedJob::class, $batchSize, $taskName, $classes);
|
||||
$this
|
||||
->getQueuedJobService()
|
||||
->queueJob($job);
|
||||
@ -77,13 +89,13 @@ class SolrReindexQueuedHandler extends SolrReindexBase
|
||||
) {
|
||||
// Trigger another job for this group
|
||||
$job = Injector::inst()->create(
|
||||
'SolrReindexGroupQueuedJob',
|
||||
SolrReindexGroupQueuedJob::class,
|
||||
get_class($indexInstance), $state, $class, $groups, $group
|
||||
);
|
||||
$this
|
||||
->getQueuedJobService()
|
||||
->queueJob($job);
|
||||
|
||||
|
||||
$title = $job->getTitle();
|
||||
$logger->info("Queued {$title}");
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr\Reindex\Jobs;
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr\Reindex\Jobs;
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr\Reindex\Jobs;
|
||||
|
||||
use Monolog\Logger;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use SilverStripe\FullTextSearch\Utils\Logging\SearchLogFactory;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexHandler;
|
||||
use SilverStripe\FullTextSearch\Utils\Logging\SearchLogFactory;
|
||||
use stdClass;
|
||||
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
|
||||
/**
|
||||
* Base class for jobs which perform re-index
|
||||
*/
|
||||
|
@ -3,5 +3,5 @@ namespace SilverStripe\FullTextSearch\Solr\Services;
|
||||
|
||||
class Solr3Service extends SolrService
|
||||
{
|
||||
private static $core_class = Solr3Service::class;
|
||||
private static $core_class = Solr3Service_Core::class;
|
||||
}
|
||||
|
@ -3,5 +3,5 @@ namespace SilverStripe\FullTextSearch\Solr\Services;
|
||||
|
||||
class Solr4Service extends SolrService
|
||||
{
|
||||
private static $core_class = Solr4Service::class;
|
||||
private static $core_class = Solr4Service_Core::class;
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr\Services;
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\FullTextSearch\Solr\Solr;
|
||||
use SilverStripe\FullTextSearch\Solr\Services\SolrService_Core;
|
||||
|
||||
Solr::include_client_api();
|
||||
/**
|
||||
* The API for accessing the primary Solr installation, which includes both SolrService_Core,
|
||||
@ -16,7 +18,7 @@ class SolrService extends SolrService_Core
|
||||
/**
|
||||
* Handle encoding the GET parameters and making the HTTP call to execute a core command
|
||||
*/
|
||||
protected function coreCommand($command, $core, $params=array())
|
||||
protected function coreCommand($command, $core, $params = array())
|
||||
{
|
||||
$command = strtoupper($command);
|
||||
|
||||
@ -46,7 +48,7 @@ class SolrService extends SolrService_Core
|
||||
* @param $datadir string - The path to store data for this core on the server. Default depends on solrconfig.xml
|
||||
* @return Apache_Solr_Response
|
||||
*/
|
||||
public function coreCreate($core, $instancedir, $config=null, $schema=null, $datadir=null)
|
||||
public function coreCreate($core, $instancedir, $config = null, $schema = null, $datadir = null)
|
||||
{
|
||||
$args = array('instanceDir' => $instancedir);
|
||||
if ($config) {
|
||||
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: elliot
|
||||
* Date: 21/04/17
|
||||
* Time: 12:45 PM
|
||||
*/
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Solr\Services;
|
||||
|
||||
|
@ -25,7 +25,7 @@ class SolrConfigStore_File implements SolrConfigStore
|
||||
$worked = @mkdir($targetDir, 0770, true);
|
||||
|
||||
if (!$worked) {
|
||||
throw new RuntimeException(
|
||||
throw new \RuntimeException(
|
||||
sprintf('Failed creating target directory %s, please check permissions', $targetDir)
|
||||
);
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ namespace SilverStripe\FullTextSearch\Solr\Stores;
|
||||
use SilverStripe\FullTextSearch\Solr\Solr;
|
||||
use SilverStripe\FullTextSearch\Utils\WebDAV;
|
||||
|
||||
|
||||
/**
|
||||
* Class SolrConfigStore_WebDAV
|
||||
*
|
||||
@ -57,4 +56,4 @@ class SolrConfigStore_WebDAV implements SolrConfigStore
|
||||
{
|
||||
return $this->remote ? "{$this->remote}/$index" : $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ class Solr_BuildTask extends BuildTask
|
||||
*/
|
||||
public function getLogger()
|
||||
{
|
||||
//@todo left commented after a confusing merge conflict. Revisit if further testing is required
|
||||
//return Injector::inst()->get('Logger');
|
||||
return Injector::inst()->get(LoggerInterface::class);
|
||||
}
|
||||
|
||||
@ -43,6 +45,8 @@ class Solr_BuildTask extends BuildTask
|
||||
*/
|
||||
protected function getLoggerFactory()
|
||||
{
|
||||
//@todo left commented after a confusing merge conflict. Revisit if further testing is required
|
||||
//return Injector::inst()->get('SearchLogFactory');
|
||||
return Injector::inst()->get(SearchLogFactory::class);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use SilverStripe\FullTextSearch\Solr\Stores\SolrConfigStore;
|
||||
|
||||
class Solr_Configure extends Solr_BuildTask
|
||||
{
|
||||
private static $segment = 'Solr_Configure';
|
||||
protected $enabled = true;
|
||||
|
||||
public function run($request)
|
||||
@ -79,6 +80,8 @@ class Solr_Configure extends Solr_BuildTask
|
||||
return new SolrConfigStore_File($indexstore);
|
||||
} elseif ($mode == 'webdav') {
|
||||
return new SolrConfigStore_WebDAV($indexstore);
|
||||
//@todo left commented after confusing merge conflict. Revisit if further testing is required
|
||||
//} elseif (ClassInfo::exists($mode) && ClassInfo::classImplements($mode, 'SolrConfigStore')) {
|
||||
} elseif (ClassInfo::exists($mode) && ClassInfo::classImplements($mode, SolrConfigStore::class)) {
|
||||
return new $mode($indexstore);
|
||||
} else {
|
||||
@ -86,3 +89,4 @@ class Solr_Configure extends Solr_BuildTask
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
namespace SilverStripe\FullTextSearch\Solr\Tasks;
|
||||
|
||||
use ReflectionClass;
|
||||
use SilverStripe\Core\ClassInfo;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
@ -26,6 +25,8 @@ use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
*/
|
||||
class Solr_Reindex extends Solr_BuildTask
|
||||
{
|
||||
private static $segment = 'Solr_Reindex';
|
||||
|
||||
protected $enabled = true;
|
||||
|
||||
/**
|
||||
@ -43,6 +44,11 @@ class Solr_Reindex extends Solr_BuildTask
|
||||
*/
|
||||
protected function getHandler()
|
||||
{
|
||||
|
||||
//@todo: this needs to determine the best class from a Factory implementation
|
||||
//@todo: it was 'SolrReindexHandler' but that doesn't work on 4.0
|
||||
//@todo left commented after a confusing merge conflict. Revisit if further investigation /testing is needed
|
||||
//return Injector::inst()->get('SolrReindexImmediateHandler');
|
||||
return Injector::inst()->get(SolrReindexHandler::class);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Utils;
|
||||
|
||||
use Iterator;
|
||||
|
||||
class CombinationsArrayIterator implements Iterator
|
||||
{
|
||||
protected $arrays;
|
||||
|
@ -1,11 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Utils\Logging;
|
||||
|
||||
use Monolog\Formatter\FormatterInterface;
|
||||
use Monolog\Formatter\LineFormatter;
|
||||
use Monolog\Handler\HandlerInterface;
|
||||
use Monolog\Logger;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
|
||||
/**
|
||||
* Provides logging based on monolog
|
||||
@ -99,7 +101,7 @@ class MonologFactory implements SearchLogFactory
|
||||
protected function getJobHandler($job)
|
||||
{
|
||||
return Injector::inst()->createWithArgs(
|
||||
'QueuedJobLogHandler',
|
||||
'SilverStripe\FullTextSearch\Utils\Logging\QueuedJobLogHandler',
|
||||
array($job, Logger::INFO)
|
||||
);
|
||||
}
|
||||
|
@ -1,12 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Utils\Logging;
|
||||
|
||||
use Monolog\Handler\AbstractProcessingHandler;
|
||||
use Monolog\Logger;
|
||||
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
|
||||
/**
|
||||
* Handler for logging events into QueuedJob message data
|
||||
*/
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Utils\Logging;
|
||||
|
||||
use Psr\Log;
|
||||
|
||||
interface SearchLogFactory
|
||||
|
@ -24,8 +24,7 @@
|
||||
"monolog/monolog": "~1.15"
|
||||
},
|
||||
"require-dev": {
|
||||
"silverstripe/cms": "4.0.x-dev",
|
||||
"hafriedlander/silverstripe-phockito": "*"
|
||||
"silverstripe/cms": "4.0.x-dev"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
|
@ -4,6 +4,19 @@ namespace SilverStripe\FullTextSearch\Tests;
|
||||
|
||||
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;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateCommitJobProcessor;
|
||||
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\QueuedJobs\Services\QueuedJobService;
|
||||
|
||||
/**
|
||||
* Tests {@see SearchUpdateQueuedJobProcessor}
|
||||
@ -12,8 +25,8 @@ class BatchedProcessorTest extends SapphireTest
|
||||
{
|
||||
protected $oldProcessor;
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'BatchedProcessorTest_Object'
|
||||
protected static $extra_dataobjects = array(
|
||||
BatchedProcessorTest_Object::class
|
||||
);
|
||||
|
||||
protected $illegalExtensions = array(
|
||||
@ -26,7 +39,7 @@ class BatchedProcessorTest extends SapphireTest
|
||||
public function setUpOnce()
|
||||
{
|
||||
// Disable illegal extensions if skipping this test
|
||||
if (class_exists('Subsite') || !interface_exists('QueuedJob')) {
|
||||
if (class_exists('Subsite') || !interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
$this->illegalExtensions = array();
|
||||
}
|
||||
parent::setUpOnce();
|
||||
@ -36,7 +49,7 @@ class BatchedProcessorTest extends SapphireTest
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped("These tests need the QueuedJobs module installed to run");
|
||||
}
|
||||
@ -46,17 +59,17 @@ class BatchedProcessorTest extends SapphireTest
|
||||
$this->markTestSkipped(get_class() . ' skipped when running with subsites');
|
||||
}
|
||||
|
||||
SS_Datetime::set_mock_now('2015-05-07 06:00:00');
|
||||
DBDatetime::set_mock_now('2015-05-07 06:00:00');
|
||||
|
||||
Config::inst()->update('SearchUpdateBatchedProcessor', 'batch_size', 5);
|
||||
Config::inst()->update('SearchUpdateBatchedProcessor', 'batch_soft_cap', 0);
|
||||
Config::inst()->update('SearchUpdateCommitJobProcessor', 'cooldown', 600);
|
||||
Config::modify()->set(SearchUpdateBatchedProcessor::class, 'batch_size', 5);
|
||||
Config::modify()->set(SearchUpdateBatchedProcessor::class, 'batch_soft_cap', 0);
|
||||
Config::modify()->set(SearchUpdateCommitJobProcessor::class, 'cooldown', 600);
|
||||
|
||||
Versioned::reading_stage("Stage");
|
||||
Versioned::set_stage("Stage");
|
||||
|
||||
Injector::inst()->registerService(new BatchedProcessor_QueuedJobService(), 'QueuedJobService');
|
||||
Injector::inst()->registerService(new BatchedProcessor_QueuedJobService(), QueuedJobService::class);
|
||||
|
||||
FullTextSearch::force_index_list('BatchedProcessorTest_Index');
|
||||
FullTextSearch::force_index_list(BatchedProcessorTest_Index::class);
|
||||
|
||||
SearchUpdateCommitJobProcessor::$dirty_indexes = array();
|
||||
SearchUpdateCommitJobProcessor::$has_run = false;
|
||||
@ -87,12 +100,12 @@ class BatchedProcessorTest extends SapphireTest
|
||||
$object->write();
|
||||
// Add to index manually
|
||||
$processor->addDirtyIDs(
|
||||
'BatchedProcessorTest_Object',
|
||||
BatchedProcessorTest_Object::class,
|
||||
array(array(
|
||||
'id' => $id,
|
||||
'state' => array('SearchVariantVersioned' => 'Stage')
|
||||
'state' => array(SearchVariantVersioned::class => 'Stage')
|
||||
)),
|
||||
'BatchedProcessorTest_Index'
|
||||
BatchedProcessorTest_Index::class
|
||||
);
|
||||
}
|
||||
$processor->batchData();
|
||||
@ -104,7 +117,7 @@ class BatchedProcessorTest extends SapphireTest
|
||||
*/
|
||||
public function testBatching()
|
||||
{
|
||||
$index = singleton('BatchedProcessorTest_Index');
|
||||
$index = singleton(BatchedProcessorTest_Index::class);
|
||||
$index->reset();
|
||||
$processor = $this->generateDirtyIds();
|
||||
|
||||
@ -132,10 +145,10 @@ class BatchedProcessorTest extends SapphireTest
|
||||
|
||||
// Check any additional queued jobs
|
||||
$processor->afterComplete();
|
||||
$service = singleton('QueuedJobService');
|
||||
$service = singleton(QueuedJobService::class);
|
||||
$jobs = $service->getJobs();
|
||||
$this->assertEquals(1, count($jobs));
|
||||
$this->assertInstanceOf('SearchUpdateCommitJobProcessor', $jobs[0]['job']);
|
||||
$this->assertInstanceOf(SearchUpdateCommitJobProcessor::class, $jobs[0]['job']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -143,7 +156,7 @@ class BatchedProcessorTest extends SapphireTest
|
||||
*/
|
||||
public function testMultipleCommits()
|
||||
{
|
||||
$index = singleton('BatchedProcessorTest_Index');
|
||||
$index = singleton(BatchedProcessorTest_Index::class);
|
||||
$index->reset();
|
||||
|
||||
// Test that running a commit immediately after submitting to the indexes
|
||||
@ -190,25 +203,25 @@ class BatchedProcessorTest extends SapphireTest
|
||||
*/
|
||||
public function testSoftCap()
|
||||
{
|
||||
$index = singleton('BatchedProcessorTest_Index');
|
||||
$index = singleton(BatchedProcessorTest_Index::class);
|
||||
$index->reset();
|
||||
$processor = $this->generateDirtyIds();
|
||||
|
||||
// Test that increasing the soft cap to 2 will reduce the number of batches
|
||||
Config::inst()->update('SearchUpdateBatchedProcessor', 'batch_soft_cap', 2);
|
||||
Config::modify()->set(SearchUpdateBatchedProcessor::class, 'batch_soft_cap', 2);
|
||||
$processor->batchData();
|
||||
$data = $processor->getJobData();
|
||||
//Debug::dump($data);die;
|
||||
$this->assertEquals(8, $data->totalSteps);
|
||||
|
||||
// A soft cap of 1 should not fit in the hanging two items
|
||||
Config::inst()->update('SearchUpdateBatchedProcessor', 'batch_soft_cap', 1);
|
||||
Config::modify()->set(SearchUpdateBatchedProcessor::class, 'batch_soft_cap', 1);
|
||||
$processor->batchData();
|
||||
$data = $processor->getJobData();
|
||||
$this->assertEquals(9, $data->totalSteps);
|
||||
|
||||
// Extra large soft cap should fit both items
|
||||
Config::inst()->update('SearchUpdateBatchedProcessor', 'batch_soft_cap', 4);
|
||||
Config::modify()->set(SearchUpdateBatchedProcessor::class, 'batch_soft_cap', 4);
|
||||
$processor->batchData();
|
||||
$data = $processor->getJobData();
|
||||
$this->assertEquals(8, $data->totalSteps);
|
||||
|
@ -9,7 +9,7 @@ class BatchedProcessorTest_Index extends SearchIndex_Recording implements TestOn
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('BatchedProcessorTest_Object');
|
||||
$this->addClass(BatchedProcessorTest_Object::class);
|
||||
$this->addFilterField('TestText');
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@ use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class BatchedProcessorTest_Object extends SiteTree implements TestOnly
|
||||
{
|
||||
private static $table_name = 'BatchedProcessorTest_Object';
|
||||
|
||||
private static $db = array(
|
||||
'TestText' => 'Varchar'
|
||||
);
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\BatchedProcessorTest;
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
|
||||
class BatchedProcessor_QueuedJobService
|
||||
{
|
||||
protected $jobs = array();
|
||||
|
@ -1,78 +1,16 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
|
||||
|
||||
class SearchUpdaterTest_Container extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar',
|
||||
'MyDate' => 'Date',
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'HasOneObject' => 'SearchUpdaterTest_HasOne'
|
||||
);
|
||||
|
||||
private static $has_many = array(
|
||||
'HasManyObjects' => 'SearchUpdaterTest_HasMany'
|
||||
);
|
||||
|
||||
private static $many_many = array(
|
||||
'ManyManyObjects' => 'SearchUpdaterTest_ManyMany'
|
||||
);
|
||||
}
|
||||
|
||||
class SearchUpdaterTest_HasOne extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $has_many = array(
|
||||
'HasManyContainers' => 'SearchUpdaterTest_Container'
|
||||
);
|
||||
}
|
||||
|
||||
class SearchUpdaterTest_HasMany extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'HasManyContainer' => 'SearchUpdaterTest_Container'
|
||||
);
|
||||
}
|
||||
|
||||
class SearchUpdaterTest_ManyMany extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $belongs_many_many = array(
|
||||
'ManyManyContainer' => 'SearchUpdaterTest_Container'
|
||||
);
|
||||
}
|
||||
|
||||
class SearchUpdaterTest_Index extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchUpdaterTest_Container');
|
||||
|
||||
$this->addFilterField('Field1');
|
||||
$this->addFilterField('HasOneObject.Field1');
|
||||
$this->addFilterField('HasManyObjects.Field1');
|
||||
}
|
||||
}
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
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_Index;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateImmediateProcessor;
|
||||
|
||||
class SearchUpdaterTest extends SapphireTest
|
||||
{
|
||||
@ -85,15 +23,15 @@ class SearchUpdaterTest extends SapphireTest
|
||||
parent::setUp();
|
||||
|
||||
if (self::$index === null) {
|
||||
self::$index = singleton(get_class($this).'_Index');
|
||||
self::$index = SearchUpdaterTest_Index::singleton();
|
||||
} else {
|
||||
self::$index->reset();
|
||||
}
|
||||
|
||||
SearchUpdater::bind_manipulation_capture();
|
||||
|
||||
Config::inst()->update('Injector', 'SearchUpdateProcessor', array(
|
||||
'class' => 'SearchUpdateImmediateProcessor'
|
||||
Config::modify()->set(Injector::class, SearchUpdateProcessor::class, array(
|
||||
'class' => SearchUpdateImmediateProcessor::class
|
||||
));
|
||||
|
||||
FullTextSearch::force_index_list(self::$index);
|
||||
@ -132,7 +70,6 @@ class SearchUpdaterTest extends SapphireTest
|
||||
// Check the default "writing a document updates the document"
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
|
||||
|
||||
$added = self::$index->getAdded(array('ID'));
|
||||
// Some databases don't output $added in a consistent order; that's okay
|
||||
usort($added, function ($a, $b) {return $a['ID']-$b['ID']; });
|
||||
@ -152,6 +89,7 @@ class SearchUpdaterTest extends SapphireTest
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
$added = self::$index->getAdded(array('ID'));
|
||||
|
||||
// Some databases don't output $added in a consistent order; that's okay
|
||||
usort($added, function ($a, $b) {return $a['ID']-$b['ID']; });
|
||||
|
||||
|
31
tests/SearchUpdaterTest/SearchUpdaterTest_Container.php
Normal file
31
tests/SearchUpdaterTest/SearchUpdaterTest_Container.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchUpdaterTest;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasOne;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_HasMany;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_ManyMany;
|
||||
|
||||
class SearchUpdaterTest_Container extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar',
|
||||
'MyDate' => 'Date',
|
||||
);
|
||||
|
||||
private static $table_name = 'SearchUpdaterTest_Container';
|
||||
|
||||
private static $has_one = array(
|
||||
'HasOneObject' => SearchUpdaterTest_HasOne::class
|
||||
);
|
||||
|
||||
private static $has_many = array(
|
||||
'HasManyObjects' => SearchUpdaterTest_HasMany::class
|
||||
);
|
||||
|
||||
private static $many_many = array(
|
||||
'ManyManyObjects' => SearchUpdaterTest_ManyMany::class
|
||||
);
|
||||
}
|
20
tests/SearchUpdaterTest/SearchUpdaterTest_HasMany.php
Normal file
20
tests/SearchUpdaterTest/SearchUpdaterTest_HasMany.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchUpdaterTest;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
|
||||
|
||||
class SearchUpdaterTest_HasMany extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $table_name = 'SearchUpdaterTest_HasMany';
|
||||
|
||||
private static $has_one = array(
|
||||
'HasManyContainer' => SearchUpdaterTest_Container::class
|
||||
);
|
||||
}
|
20
tests/SearchUpdaterTest/SearchUpdaterTest_HasOne.php
Normal file
20
tests/SearchUpdaterTest/SearchUpdaterTest_HasOne.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchUpdaterTest;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
|
||||
|
||||
class SearchUpdaterTest_HasOne extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $table_name = 'SearchUpdaterTest_HasOne';
|
||||
|
||||
private static $has_many = array(
|
||||
'HasManyContainers' => SearchUpdaterTest_Container::class
|
||||
);
|
||||
}
|
17
tests/SearchUpdaterTest/SearchUpdaterTest_Index.php
Normal file
17
tests/SearchUpdaterTest/SearchUpdaterTest_Index.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchUpdaterTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
|
||||
class SearchUpdaterTest_Index extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass(SearchUpdaterTest_Container::class);
|
||||
|
||||
$this->addFilterField('Field1');
|
||||
$this->addFilterField('HasOneObject.Field1');
|
||||
$this->addFilterField('HasManyObjects.Field1');
|
||||
}
|
||||
}
|
20
tests/SearchUpdaterTest/SearchUpdaterTest_ManyMany.php
Normal file
20
tests/SearchUpdaterTest/SearchUpdaterTest_ManyMany.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchUpdaterTest;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
|
||||
|
||||
class SearchUpdaterTest_ManyMany extends DataObject
|
||||
{
|
||||
private static $db = array(
|
||||
'Field1' => 'Varchar',
|
||||
'Field2' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $table_name = 'SearchUpdaterTest_ManyMany';
|
||||
|
||||
private static $belongs_many_many = array(
|
||||
'ManyManyContainer' => SearchUpdaterTest_Container::class
|
||||
);
|
||||
}
|
@ -3,23 +3,10 @@
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantSiteTreeSubsitesPolyhomeTest\SearchVariantSiteTreeSubsitesPolyhomeTest_Index;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantSiteTreeSubsitesPolyhomeTest\SearchVariantSiteTreeSubsitesPolyhomeTest_Item;
|
||||
|
||||
class SearchVariantSiteTreeSubsitesPolyhomeTest_Item extends SiteTree
|
||||
{
|
||||
// TODO: Currently theres a failure if you addClass a non-table class
|
||||
private static $db = array(
|
||||
'TestText' => 'Varchar'
|
||||
);
|
||||
}
|
||||
|
||||
class SearchVariantSiteTreeSubsitesPolyhomeTest_Index extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchVariantSiteTreeSubsitesPolyhomeTest_Item');
|
||||
$this->addFilterField('TestText');
|
||||
}
|
||||
}
|
||||
|
||||
class SearchVariantSiteTreeSubsitesPolyhomeTest extends SapphireTest
|
||||
{
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?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');
|
||||
}
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
<?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'
|
||||
);
|
||||
}
|
@ -1,9 +1,15 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest\SearchVariantVersionedTest_Index;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest\SearchVariantVersionedTest_Item;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest\SearchVariantVersionedTest_IndexNoStage;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateImmediateProcessor;
|
||||
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
|
||||
|
||||
class SearchVariantVersionedTest extends SapphireTest
|
||||
{
|
||||
@ -12,27 +18,22 @@ class SearchVariantVersionedTest extends SapphireTest
|
||||
*/
|
||||
private static $index = null;
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'SearchVariantVersionedTest_Item'
|
||||
protected static $extra_dataobjects = array(
|
||||
SearchVariantVersionedTest_Item::class
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
// Check versioned available
|
||||
if (!class_exists('Versioned')) {
|
||||
return $this->markTestSkipped('The versioned decorator is not installed');
|
||||
}
|
||||
|
||||
if (self::$index === null) {
|
||||
self::$index = singleton('SearchVariantVersionedTest_Index');
|
||||
self::$index = singleton(SearchVariantVersionedTest_Index::class);
|
||||
}
|
||||
|
||||
SearchUpdater::bind_manipulation_capture();
|
||||
|
||||
Config::inst()->update('Injector', 'SearchUpdateProcessor', array(
|
||||
'class' => 'SearchUpdateImmediateProcessor'
|
||||
Config::modify()->set('Injector', SearchUpdateProcessor::class, array(
|
||||
'class' => SearchUpdateImmediateProcessor::class
|
||||
));
|
||||
|
||||
FullTextSearch::force_index_list(self::$index);
|
||||
@ -47,20 +48,21 @@ class SearchVariantVersionedTest extends SapphireTest
|
||||
$item->write();
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
$this->assertEquals(self::$index->getAdded(array('ID', '_versionedstage')), array(
|
||||
$this->assertEquals(array(
|
||||
array('ID' => $item->ID, '_versionedstage' => 'Stage')
|
||||
));
|
||||
), self::$index->getAdded(array('ID', '_versionedstage')));
|
||||
|
||||
// Check that publish updates Live
|
||||
|
||||
self::$index->reset();
|
||||
|
||||
$item->publish("Stage", "Live");
|
||||
$item->copyVersionToStage('Stage', 'Live');
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
$this->assertEquals(self::$index->getAdded(array('ID', '_versionedstage')), array(
|
||||
$this->assertEquals(array(
|
||||
array('ID' => $item->ID, '_versionedstage' => 'Stage'),
|
||||
array('ID' => $item->ID, '_versionedstage' => 'Live')
|
||||
));
|
||||
), self::$index->getAdded(array('ID', '_versionedstage')));
|
||||
|
||||
// Just update a SiteTree field, and check it updates Stage
|
||||
|
||||
@ -81,48 +83,23 @@ class SearchVariantVersionedTest extends SapphireTest
|
||||
|
||||
public function testExcludeVariantState()
|
||||
{
|
||||
$index = singleton('SearchVariantVersionedTest_IndexNoStage');
|
||||
$index = singleton(SearchVariantVersionedTest_IndexNoStage::class);
|
||||
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());
|
||||
$this->assertEquals(array(), $index->getAdded(array('ID', '_versionedstage')));
|
||||
|
||||
// Check that publish updates Live
|
||||
$index->reset();
|
||||
$item->publish("Stage", "Live");
|
||||
|
||||
$item->copyVersionToStage('Stage', 'Live');
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
$this->assertEquals($index->getAdded(array('ID', '_versionedstage')), array(
|
||||
$this->assertEquals(array(
|
||||
array('ID' => $item->ID, '_versionedstage' => 'Live')
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class SearchVariantVersionedTest_Item extends SiteTree implements TestOnly
|
||||
{
|
||||
// TODO: Currently theres a failure if you addClass a non-table class
|
||||
private static $db = array(
|
||||
'TestText' => 'Varchar'
|
||||
);
|
||||
}
|
||||
|
||||
class SearchVariantVersionedTest_Index extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchVariantVersionedTest_Item');
|
||||
$this->addFilterField('TestText');
|
||||
}
|
||||
}
|
||||
|
||||
class SearchVariantVersionedTest_IndexNoStage extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchVariantVersionedTest_Item');
|
||||
$this->addFilterField('TestText');
|
||||
$this->excludeVariantState(array('SearchVariantVersioned' => 'Stage'));
|
||||
), $index->getAdded(array('ID', '_versionedstage')));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
|
||||
class SearchVariantVersionedTest_Index extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass(SearchVariantVersionedTest_Item::class);
|
||||
$this->addFilterField('TestText');
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantVersioned;
|
||||
|
||||
class SearchVariantVersionedTest_IndexNoStage extends SearchIndex_Recording
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass(SearchVariantVersionedTest_Item::class);
|
||||
$this->addFilterField('TestText');
|
||||
$this->excludeVariantState(array(SearchVariantVersioned::class => 'Stage'));
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest;
|
||||
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class SearchVariantVersionedTest_Item extends SiteTree implements TestOnly
|
||||
{
|
||||
private static $table_name = 'SearchVariantVersionedTest_Item';
|
||||
|
||||
// TODO: Currently theres a failure if you addClass a non-table class
|
||||
private static $db = array(
|
||||
'TestText' => 'Varchar'
|
||||
);
|
||||
}
|
@ -3,8 +3,8 @@
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexSubsitesTest\SolrIndexSubsitesTest_Index;
|
||||
|
||||
if (class_exists('Phockito')) {
|
||||
Phockito::include_hamcrest(false);
|
||||
if (class_exists('\Phockito')) {
|
||||
\Phockito::include_hamcrest(false);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -26,15 +26,16 @@ class SolrIndexSubsitesTest extends SapphireTest {
|
||||
// Prevent parent::setUp() crashing on db build
|
||||
if (!class_exists('Subsite')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped("These tests need the Subsite module installed to run");
|
||||
}
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->server = $_SERVER;
|
||||
|
||||
if (!class_exists('Phockito')) {
|
||||
if (!class_exists('\Phockito')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped("These tests need the Phockito module installed to run");
|
||||
$this->markTestSkipped("These tests need the \Phockito module installed to run");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -51,7 +52,7 @@ class SolrIndexSubsitesTest extends SapphireTest {
|
||||
|
||||
SearchUpdater::bind_manipulation_capture();
|
||||
|
||||
Config::inst()->update('Injector', 'SearchUpdateProcessor', array(
|
||||
Config::modify()->set('Injector', 'SearchUpdateProcessor', array(
|
||||
'class' => 'SearchUpdateImmediateProcessor'
|
||||
));
|
||||
|
||||
@ -70,7 +71,7 @@ class SolrIndexSubsitesTest extends SapphireTest {
|
||||
|
||||
protected function getServiceMock()
|
||||
{
|
||||
return Phockito::mock('Solr4Service');
|
||||
return \Phockito::mock('Solr4Service');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -82,11 +83,11 @@ class SolrIndexSubsitesTest extends SapphireTest {
|
||||
protected function getExpectedDocumentId($object, $subsiteID, $stage = null)
|
||||
{
|
||||
$id = $object->ID;
|
||||
$class = ClassInfo::baseDataClass($object);
|
||||
$class = DataObject::getSchema()->baseDataClass($object);
|
||||
$variants = array();
|
||||
|
||||
// Check subsite
|
||||
if(class_exists('Subsite') && $object->hasOne('Subsite')) {
|
||||
if(class_exists('Subsite') && DataObject::getSchema()->hasOneComponent($object->getClassName(), 'Subsite')) {
|
||||
$variants[] = '"SearchVariantSubsites":"' . $subsiteID. '"';
|
||||
}
|
||||
|
||||
@ -108,7 +109,7 @@ class SolrIndexSubsitesTest extends SapphireTest {
|
||||
// Add records to first subsite
|
||||
Versioned::reading_stage('Stage');
|
||||
$_SERVER['HTTP_HOST'] = 'www.subsite1.com';
|
||||
Phockito::reset($serviceMock);
|
||||
\Phockito::reset($serviceMock);
|
||||
$file = new File();
|
||||
$file->Title = 'My File';
|
||||
$file->SubsiteID = $subsite1->ID;
|
||||
@ -131,8 +132,8 @@ class SolrIndexSubsitesTest extends SapphireTest {
|
||||
'File_Title' => 'My File',
|
||||
'_subsite' => $subsite1->ID
|
||||
));
|
||||
Phockito::verify($serviceMock)->addDocument($doc1);
|
||||
Phockito::verify($serviceMock)->addDocument($doc2);
|
||||
\Phockito::verify($serviceMock)->addDocument($doc1);
|
||||
\Phockito::verify($serviceMock)->addDocument($doc2);
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,13 +3,15 @@
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexSubsitesTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\Assets\File;
|
||||
use SilverStripe\CMS\Model\SiteTree;
|
||||
|
||||
class SolrIndexSubsitesTest_Index extends SolrIndex
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('File');
|
||||
$this->addClass('SiteTree');
|
||||
$this->addClass(File::class);
|
||||
$this->addClass(SiteTree::class);
|
||||
$this->addAllFulltextFields();
|
||||
}
|
||||
}
|
||||
|
@ -4,60 +4,50 @@ use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_FakeIndex2;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexTest\SolrIndexTest_BoostedIndex;
|
||||
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\Core\Config\Config;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery;
|
||||
|
||||
|
||||
class SolrIndexTest extends SapphireTest
|
||||
{
|
||||
public function setUpOnce()
|
||||
{
|
||||
parent::setUpOnce();
|
||||
|
||||
if (class_exists('Phockito')) {
|
||||
Phockito::include_hamcrest(false);
|
||||
}
|
||||
}
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!class_exists('Phockito')) {
|
||||
$this->markTestSkipped("These tests need the Phockito module installed to run");
|
||||
$this->skipTest = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function testFieldDataHasOne()
|
||||
{
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
$data = $index->fieldData('HasOneObject.Field1');
|
||||
$data = $data['SearchUpdaterTest_Container_HasOneObject_Field1'];
|
||||
|
||||
$this->assertEquals('SearchUpdaterTest_Container', $data['origin']);
|
||||
$this->assertEquals('SearchUpdaterTest_Container', $data['base']);
|
||||
$this->assertEquals('SearchUpdaterTest_HasOne', $data['class']);
|
||||
$data = $data[SearchUpdaterTest_Container::class . '_HasOneObject_Field1'];
|
||||
|
||||
$this->assertEquals(SearchUpdaterTest_Container::class, $data['origin']);
|
||||
$this->assertEquals(SearchUpdaterTest_Container::class, $data['base']);
|
||||
$this->assertEquals(SearchUpdaterTest_HasOne::class, $data['class']);
|
||||
}
|
||||
|
||||
public function testFieldDataHasMany()
|
||||
{
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
$data = $index->fieldData('HasManyObjects.Field1');
|
||||
$data = $data['SearchUpdaterTest_Container_HasManyObjects_Field1'];
|
||||
$data = $data[SearchUpdaterTest_Container::class . '_HasManyObjects_Field1'];
|
||||
|
||||
$this->assertEquals('SearchUpdaterTest_Container', $data['origin']);
|
||||
$this->assertEquals('SearchUpdaterTest_Container', $data['base']);
|
||||
$this->assertEquals('SearchUpdaterTest_HasMany', $data['class']);
|
||||
$this->assertEquals(SearchUpdaterTest_Container::class, $data['origin']);
|
||||
$this->assertEquals(SearchUpdaterTest_Container::class, $data['base']);
|
||||
$this->assertEquals(SearchUpdaterTest_HasMany::class, $data['class']);
|
||||
}
|
||||
|
||||
public function testFieldDataManyMany()
|
||||
{
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
$data = $index->fieldData('ManyManyObjects.Field1');
|
||||
$data = $data['SearchUpdaterTest_Container_ManyManyObjects_Field1'];
|
||||
$data = $data[SearchUpdaterTest_Container::class . '_ManyManyObjects_Field1'];
|
||||
|
||||
$this->assertEquals('SearchUpdaterTest_Container', $data['origin']);
|
||||
$this->assertEquals('SearchUpdaterTest_Container', $data['base']);
|
||||
$this->assertEquals('SearchUpdaterTest_ManyMany', $data['class']);
|
||||
$this->assertEquals(SearchUpdaterTest_Container::class, $data['origin']);
|
||||
$this->assertEquals(SearchUpdaterTest_Container::class, $data['base']);
|
||||
$this->assertEquals(SearchUpdaterTest_ManyMany::class, $data['class']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -65,15 +55,19 @@ class SolrIndexTest extends SapphireTest
|
||||
*/
|
||||
public function testBoostedQuery()
|
||||
{
|
||||
$serviceMock = $this->getServiceMock();
|
||||
Phockito::when($serviceMock)
|
||||
->search(
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything()
|
||||
)->return($this->getFakeRawSolrResponse());
|
||||
/** @var Solr3Service|PHPUnit_Framework_MockObject_MockObject $serviceMock */
|
||||
$serviceMock = $this->getMockBuilder(Solr3Service::class)
|
||||
->setMethods(['search'])
|
||||
->getMock();
|
||||
|
||||
$serviceMock->expects($this->once())
|
||||
->method('search')
|
||||
->with($this->equalTo('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)'),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->anything()
|
||||
)->willReturn($this->getFakeRawSolrResponse());
|
||||
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
$index->setService($serviceMock);
|
||||
@ -85,15 +79,6 @@ class SolrIndexTest extends SapphireTest
|
||||
array('Field1' => 1.5, 'HasOneObject_Field1' => 3)
|
||||
);
|
||||
$index->search($query);
|
||||
|
||||
Phockito::verify($serviceMock)
|
||||
->search(
|
||||
'+(Field1:term^1.5 OR HasOneObject_Field1:term^3)',
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -101,15 +86,20 @@ class SolrIndexTest extends SapphireTest
|
||||
*/
|
||||
public function testBoostedField()
|
||||
{
|
||||
$serviceMock = $this->getServiceMock();
|
||||
Phockito::when($serviceMock)
|
||||
->search(
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything()
|
||||
)->return($this->getFakeRawSolrResponse());
|
||||
/** @var Solr3Service|PHPUnit_Framework_MockObject_MockObject $serviceMock */
|
||||
$serviceMock = $this->getMockBuilder(Solr3Service::class)
|
||||
->setMethods(['search'])
|
||||
->getMock();
|
||||
|
||||
$serviceMock->expects($this->once())
|
||||
->method('search')
|
||||
->with($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->anything()
|
||||
)->willReturn($this->getFakeRawSolrResponse());
|
||||
|
||||
$index = new SolrIndexTest_BoostedIndex();
|
||||
$index->setService($serviceMock);
|
||||
@ -117,32 +107,34 @@ class SolrIndexTest extends SapphireTest
|
||||
$query = new SearchQuery();
|
||||
$query->search('term');
|
||||
$index->search($query);
|
||||
|
||||
// Ensure matcher contains correct boost in 'qf' parameter
|
||||
$matcher = new Hamcrest_Array_IsArrayContainingKeyValuePair(
|
||||
new Hamcrest_Core_IsEqual('qf'),
|
||||
new Hamcrest_Core_IsEqual('SearchUpdaterTest_Container_Field1^1.5 SearchUpdaterTest_Container_Field2^2.1 _text')
|
||||
);
|
||||
Phockito::verify($serviceMock)
|
||||
->search(
|
||||
'+term',
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
$matcher,
|
||||
\Hamcrest_Matchers::anything()
|
||||
);
|
||||
}
|
||||
|
||||
public function testHighlightQueryOnBoost()
|
||||
{
|
||||
$serviceMock = $this->getServiceMock();
|
||||
Phockito::when($serviceMock)->search(
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything()
|
||||
)->return($this->getFakeRawSolrResponse());
|
||||
/** @var SilverStripe\FullTextSearch\Solr\Services\Solr3Service|ObjectProphecy $serviceMock */
|
||||
$serviceMock = $this->getMockBuilder(Solr3Service::class)
|
||||
->setMethods(['search'])
|
||||
->getMock();
|
||||
|
||||
$serviceMock->expects($this->exactly(2))
|
||||
->method('search')
|
||||
->withConsecutive([
|
||||
$this->equalTo('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)'),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->logicalNot(
|
||||
$this->arrayHasKey('hl.q')
|
||||
),
|
||||
$this->anything()
|
||||
],
|
||||
[
|
||||
$this->equalTo('+(Field1:term^1.5 OR HasOneObject_Field1:term^3)'),
|
||||
$this->anything(),
|
||||
$this->anything(),
|
||||
$this->arrayHasKey('hl.q'),
|
||||
$this->anything()
|
||||
]
|
||||
)->willReturn($this->getFakeRawSolrResponse());
|
||||
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
$index->setService($serviceMock);
|
||||
@ -155,14 +147,6 @@ class SolrIndexTest extends SapphireTest
|
||||
array('Field1' => 1.5, 'HasOneObject_Field1' => 3)
|
||||
);
|
||||
$index->search($query);
|
||||
Phockito::verify(
|
||||
$serviceMock)->search(
|
||||
'+(Field1:term^1.5 OR HasOneObject_Field1:term^3)',
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::not(\Hamcrest_Matchers::hasKeyInArray('hl.q')),
|
||||
\Hamcrest_Matchers::anything()
|
||||
);
|
||||
|
||||
// Search with highlighting
|
||||
$query = new SearchQuery();
|
||||
@ -172,19 +156,12 @@ class SolrIndexTest extends SapphireTest
|
||||
array('Field1' => 1.5, 'HasOneObject_Field1' => 3)
|
||||
);
|
||||
$index->search($query, -1, -1, array('hl' => true));
|
||||
Phockito::verify(
|
||||
$serviceMock)->search(
|
||||
'+(Field1:term^1.5 OR HasOneObject_Field1:term^3)',
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::anything(),
|
||||
\Hamcrest_Matchers::hasKeyInArray('hl.q'),
|
||||
\Hamcrest_Matchers::anything()
|
||||
);
|
||||
}
|
||||
|
||||
public function testIndexExcludesNullValues()
|
||||
{
|
||||
$serviceMock = $this->getServiceMock();
|
||||
/** @var Solr3Service|ObjectProphecy $serviceMock */
|
||||
$serviceMock = $this->createMock(Solr3Service::class);
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
$index->setService($serviceMock);
|
||||
$obj = new SearchUpdaterTest_Container();
|
||||
@ -193,36 +170,36 @@ class SolrIndexTest extends SapphireTest
|
||||
$obj->Field2 = null;
|
||||
$obj->MyDate = null;
|
||||
$docs = $index->add($obj);
|
||||
$value = $docs[0]->getField('SearchUpdaterTest_Container_Field1');
|
||||
$value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_Field1');
|
||||
$this->assertEquals('Field1 val', $value['value'], 'Writes non-NULL string fields');
|
||||
$value = $docs[0]->getField('SearchUpdaterTest_Container_Field2');
|
||||
$value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_Field2');
|
||||
$this->assertFalse($value, 'Ignores string fields if they are NULL');
|
||||
$value = $docs[0]->getField('SearchUpdaterTest_Container_MyDate');
|
||||
$value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_MyDate');
|
||||
$this->assertFalse($value, 'Ignores date fields if they are NULL');
|
||||
|
||||
$obj->MyDate = '2010-12-30';
|
||||
$docs = $index->add($obj);
|
||||
$value = $docs[0]->getField('SearchUpdaterTest_Container_MyDate');
|
||||
$value = $docs[0]->getField(SearchUpdaterTest_Container::class . '_MyDate');
|
||||
$this->assertEquals('2010-12-30T00:00:00Z', $value['value'], 'Writes non-NULL dates');
|
||||
}
|
||||
|
||||
public function testAddFieldExtraOptions()
|
||||
{
|
||||
Config::inst()->nest();
|
||||
Config::inst()->update('Director', 'environment_type', 'live'); // dev mode sets stored=true for everything
|
||||
Config::nest();
|
||||
Director::set_environment_type('live');
|
||||
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
|
||||
$defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>');
|
||||
$defField1 = $defs->xpath('field[@name="SearchUpdaterTest_Container_Field1"]');
|
||||
$defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]');
|
||||
$this->assertEquals((string)$defField1[0]['stored'], 'false');
|
||||
|
||||
$index->addFilterField('Field1', null, array('stored' => 'true'));
|
||||
$defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>');
|
||||
$defField1 = $defs->xpath('field[@name="SearchUpdaterTest_Container_Field1"]');
|
||||
$defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]');
|
||||
$this->assertEquals((string)$defField1[0]['stored'], 'true');
|
||||
|
||||
Config::inst()->unnest();
|
||||
Config::unnest();
|
||||
}
|
||||
|
||||
public function testAddAnalyzer()
|
||||
@ -230,13 +207,13 @@ class SolrIndexTest extends SapphireTest
|
||||
$index = new SolrIndexTest_FakeIndex();
|
||||
|
||||
$defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>');
|
||||
$defField1 = $defs->xpath('field[@name="SearchUpdaterTest_Container_Field1"]');
|
||||
$defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]');
|
||||
$analyzers = $defField1[0]->analyzer;
|
||||
$this->assertFalse((bool)$analyzers);
|
||||
|
||||
$index->addAnalyzer('Field1', 'charFilter', array('class' => 'solr.HTMLStripCharFilterFactory'));
|
||||
$defs = simplexml_load_string('<fields>' . $index->getFieldDefinitions() . '</fields>');
|
||||
$defField1 = $defs->xpath('field[@name="SearchUpdaterTest_Container_Field1"]');
|
||||
$defField1 = $defs->xpath('field[@name="' . SearchUpdaterTest_Container::class . '_Field1"]');
|
||||
$analyzers = $defField1[0]->analyzer;
|
||||
$this->assertTrue((bool)$analyzers);
|
||||
$this->assertEquals('solr.HTMLStripCharFilterFactory', $analyzers[0]->charFilter[0]['class']);
|
||||
@ -265,11 +242,11 @@ class SolrIndexTest extends SapphireTest
|
||||
$index->addFulltextField('Field2');
|
||||
$schema = $index->getFieldDefinitions();
|
||||
$this->assertContains(
|
||||
"<field name='SearchUpdaterTest_Container_Field1' type='text' indexed='true' stored='true'",
|
||||
"<field name='" . SearchUpdaterTest_Container::class . "_Field1' type='text' indexed='true' stored='true'",
|
||||
$schema
|
||||
);
|
||||
$this->assertContains(
|
||||
"<field name='SearchUpdaterTest_Container_Field2' type='text' indexed='true' stored='false'",
|
||||
"<field name='" . SearchUpdaterTest_Container::class . "_Field2' type='text' indexed='true' stored='false'",
|
||||
$schema
|
||||
);
|
||||
|
||||
@ -279,35 +256,19 @@ class SolrIndexTest extends SapphireTest
|
||||
$index2->addStoredField('Field2');
|
||||
$schema2 = $index2->getFieldDefinitions();
|
||||
$this->assertContains(
|
||||
"<field name='SearchUpdaterTest_Container_Field1' type='text' indexed='true' stored='false'",
|
||||
"<field name='" . SearchUpdaterTest_Container::class . "_Field1' type='text' indexed='true' stored='false'",
|
||||
$schema2
|
||||
);
|
||||
$this->assertContains(
|
||||
"<field name='SearchUpdaterTest_Container_Field2' type='text' indexed='true' stored='true'",
|
||||
"<field name='" . SearchUpdaterTest_Container::class . "_Field2' type='text' indexed='true' stored='true'",
|
||||
$schema2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Solr3Service
|
||||
*/
|
||||
protected function getServiceMock()
|
||||
{
|
||||
return Phockito::mock('Solr3Service');
|
||||
}
|
||||
|
||||
protected function getServiceSpy()
|
||||
{
|
||||
$serviceSpy = Phockito::spy('Solr3Service');
|
||||
Phockito::when($serviceSpy)->_sendRawPost()->return($this->getFakeRawSolrResponse());
|
||||
|
||||
return $serviceSpy;
|
||||
}
|
||||
|
||||
protected function getFakeRawSolrResponse()
|
||||
{
|
||||
return new Apache_Solr_Response(
|
||||
new Apache_Solr_HttpTransport_Response(
|
||||
return new \Apache_Solr_Response(
|
||||
new \Apache_Solr_HttpTransport_Response(
|
||||
null,
|
||||
null,
|
||||
'{}'
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
|
||||
|
||||
class SolrIndexTest_BoostedIndex extends SolrIndex
|
||||
{
|
||||
@ -14,9 +15,9 @@ class SolrIndexTest_BoostedIndex extends SolrIndex
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchUpdaterTest_Container');
|
||||
$this->addClass(SearchUpdaterTest_Container::class);
|
||||
$this->addAllFulltextFields();
|
||||
$this->setFieldBoosting('SearchUpdaterTest_Container_Field1', 1.5);
|
||||
$this->setFieldBoosting(SearchUpdaterTest_Container::class . '_Field1', 1.5);
|
||||
$this->addBoostedField('Field2', null, array(), 2.1);
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,13 @@
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
|
||||
|
||||
class SolrIndexTest_FakeIndex extends SolrIndex
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchUpdaterTest_Container');
|
||||
$this->addClass(SearchUpdaterTest_Container::class);
|
||||
|
||||
$this->addFilterField('Field1');
|
||||
$this->addFilterField('MyDate', 'Date');
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchUpdaterTest\SearchUpdaterTest_Container;
|
||||
|
||||
class SolrIndexTest_FakeIndex2 extends SolrIndex
|
||||
{
|
||||
@ -14,7 +15,7 @@ class SolrIndexTest_FakeIndex2 extends SolrIndex
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchUpdaterTest_Container');
|
||||
$this->addClass(SearchUpdaterTest_Container::class);
|
||||
$this->addFilterField('MyDate', 'Date');
|
||||
$this->addFilterField('HasOneObject.Field1');
|
||||
$this->addFilterField('HasManyObjects.Field1');
|
||||
|
@ -1,58 +1,51 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrVersionedTest\SolrDocumentMatcher;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrVersionedTest\SolrIndexVersionedTest_Object;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrVersionedTest\SolrVersionedTest_Index;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\FullTextSearch\Search\SearchIntrospection;
|
||||
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex_Recording;
|
||||
use SilverStripe\FullTextSearch\Solr\Services\Solr3Service;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest\SearchVariantVersionedTest_Item;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest\SolrIndexVersionedTest_Object;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest\SolrVersionedTest_Index;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateProcessor;
|
||||
use SilverStripe\FullTextSearch\Search\Processors\SearchUpdateImmediateProcessor;
|
||||
use SilverStripe\FullTextSearch\Search\Updaters\SearchUpdater;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariantVersioned;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
|
||||
if (class_exists('Phockito')) {
|
||||
Phockito::include_hamcrest(false);
|
||||
}
|
||||
|
||||
class SolrIndexVersionedTest extends SapphireTest
|
||||
{
|
||||
protected $oldMode = null;
|
||||
|
||||
protected static $index = null;
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'SearchVariantVersionedTest_Item',
|
||||
'SolrIndexVersionedTest_Object',
|
||||
protected static $extra_dataobjects = array(
|
||||
SearchVariantVersionedTest_Item::class,
|
||||
SolrIndexVersionedTest_Object::class
|
||||
);
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!class_exists('Phockito')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped("These tests need the Phockito module installed to run");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check versioned available
|
||||
if (!class_exists('Versioned')) {
|
||||
$this->skipTest = true;
|
||||
$this->markTestSkipped('The versioned decorator is not installed');
|
||||
return;
|
||||
}
|
||||
|
||||
if (self::$index === null) {
|
||||
self::$index = singleton('SolrVersionedTest_Index');
|
||||
self::$index = singleton(SolrVersionedTest_Index::class);
|
||||
}
|
||||
|
||||
SearchUpdater::bind_manipulation_capture();
|
||||
|
||||
Config::inst()->update('Injector', 'SearchUpdateProcessor', array(
|
||||
'class' => 'SearchUpdateImmediateProcessor'
|
||||
Config::modify()->set('Injector', SearchUpdateProcessor::class, array(
|
||||
'class' => SearchUpdateImmediateProcessor::class
|
||||
));
|
||||
|
||||
FullTextSearch::force_index_list(self::$index);
|
||||
SearchUpdater::clear_dirty_indexes();
|
||||
|
||||
$this->oldMode = Versioned::get_reading_mode();
|
||||
Versioned::reading_stage('Stage');
|
||||
Versioned::set_stage('Stage');
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
@ -61,9 +54,17 @@ class SolrIndexVersionedTest extends SapphireTest
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
protected function getServiceMock()
|
||||
protected function getServiceMock($setMethods = array())
|
||||
{
|
||||
return Phockito::mock('Solr3Service');
|
||||
// Setup mock
|
||||
/** @var SilverStripe\FullTextSearch\Solr\Services\Solr3Service|ObjectProphecy $serviceMock */
|
||||
$serviceMock = $this->getMockBuilder(Solr3Service::class)
|
||||
->setMethods($setMethods)
|
||||
->getMock();
|
||||
|
||||
self::$index->setService($serviceMock);
|
||||
|
||||
return $serviceMock;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,104 +75,164 @@ class SolrIndexVersionedTest extends SapphireTest
|
||||
protected function getExpectedDocumentId($object, $stage)
|
||||
{
|
||||
$id = $object->ID;
|
||||
$class = ClassInfo::baseDataClass($object);
|
||||
$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') && $object->hasOne('Subsite')) {
|
||||
if(class_exists('Subsite') && DataObject::getSchema()->hasOneComponent($object->getClassName(), 'Subsite')) {
|
||||
$subsites = '"SearchVariantSubsites":"0",';
|
||||
}
|
||||
return $id.'-'.$class.'-{'.$subsites.'"SearchVariantVersioned":"'.$stage.'"}';
|
||||
return $id.'-'.$class.'-{'.$subsites. json_encode(SearchVariantVersioned::class) . ':"'.$stage.'"}';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param DataObject $object Item being added
|
||||
* @param string $value Value for class
|
||||
* @param string $stage Stage updated
|
||||
* @return Apache_Solr_Document
|
||||
*/
|
||||
protected function getSolrDocument($class, $object, $value, $stage)
|
||||
{
|
||||
$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('ClassHierarchy', SearchIntrospection::hierarchy($class));
|
||||
$doc->setFieldBoost('ID', false);
|
||||
$doc->setFieldBoost('ClassHierarchy', false);
|
||||
|
||||
return $doc;
|
||||
}
|
||||
|
||||
public function testPublishing()
|
||||
{
|
||||
|
||||
// Setup mocks
|
||||
$serviceMock = $this->getServiceMock();
|
||||
self::$index->setService($serviceMock);
|
||||
|
||||
// Check that write updates Stage
|
||||
Versioned::reading_stage('Stage');
|
||||
Phockito::reset($serviceMock);
|
||||
Versioned::set_stage('Stage');
|
||||
|
||||
$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');
|
||||
|
||||
// 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()
|
||||
]
|
||||
);
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
$doc1 = new SolrDocumentMatcher(array(
|
||||
'_documentid' => $this->getExpectedDocumentId($item, 'Stage'),
|
||||
'ClassName' => 'SearchVariantVersionedTest_Item',
|
||||
'SearchVariantVersionedTest_Item_TestText' => 'Foo',
|
||||
'_versionedstage' => 'Stage'
|
||||
));
|
||||
$doc2 = new SolrDocumentMatcher(array(
|
||||
'_documentid' => $this->getExpectedDocumentId($object, 'Stage'),
|
||||
'ClassName' => 'SolrIndexVersionedTest_Object',
|
||||
'SolrIndexVersionedTest_Object_TestText' => 'Bar',
|
||||
'_versionedstage' => 'Stage'
|
||||
));
|
||||
Phockito::verify($serviceMock)->addDocument($doc1);
|
||||
Phockito::verify($serviceMock)->addDocument($doc2);
|
||||
|
||||
|
||||
// Check that write updates Live
|
||||
Versioned::reading_stage('Stage');
|
||||
Phockito::reset($serviceMock);
|
||||
Versioned::set_stage('Stage');
|
||||
|
||||
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Foo'));
|
||||
$item->write();
|
||||
$item->publish('Stage', 'Live');
|
||||
$item->copyVersionToStage('Stage', 'Live');
|
||||
|
||||
$object = new SolrIndexVersionedTest_Object(array('TestText' => 'Bar'));
|
||||
$object->write();
|
||||
$object->publish('Stage', 'Live');
|
||||
$object->copyVersionToStage('Stage', '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');
|
||||
|
||||
// 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()
|
||||
]
|
||||
);
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
$doc = new SolrDocumentMatcher(array(
|
||||
'_documentid' => $this->getExpectedDocumentId($item, 'Live'),
|
||||
'ClassName' => 'SearchVariantVersionedTest_Item',
|
||||
'SearchVariantVersionedTest_Item_TestText' => 'Foo',
|
||||
'_versionedstage' => 'Live'
|
||||
));
|
||||
$doc2 = new SolrDocumentMatcher(array(
|
||||
'_documentid' => $this->getExpectedDocumentId($object, 'Live'),
|
||||
'ClassName' => 'SolrIndexVersionedTest_Object',
|
||||
'SolrIndexVersionedTest_Object_TestText' => 'Bar',
|
||||
'_versionedstage' => 'Live'
|
||||
));
|
||||
Phockito::verify($serviceMock)->addDocument($doc);
|
||||
Phockito::verify($serviceMock)->addDocument($doc2);
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
// Setup mocks
|
||||
$serviceMock = $this->getServiceMock();
|
||||
self::$index->setService($serviceMock);
|
||||
|
||||
// Delete the live record (not the stage)
|
||||
Versioned::reading_stage('Stage');
|
||||
Phockito::reset($serviceMock);
|
||||
Versioned::set_stage('Stage');
|
||||
|
||||
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Too'));
|
||||
$item->write();
|
||||
$item->publish('Stage', 'Live');
|
||||
Versioned::reading_stage('Live');
|
||||
$item->copyVersionToStage('Stage', 'Live');
|
||||
Versioned::set_stage('Live');
|
||||
$id = clone $item;
|
||||
$item->delete();
|
||||
|
||||
// Check that only the 'Live' version is deleted
|
||||
$this->getServiceMock(['addDocument', 'commit', 'deleteById'])
|
||||
->expects($this->exactly(1))
|
||||
->method('deleteById')
|
||||
->with($this->equalTo($this->getExpectedDocumentId($id, 'Live')));
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
Phockito::verify($serviceMock, 1)
|
||||
->deleteById($this->getExpectedDocumentId($id, 'Live'));
|
||||
Phockito::verify($serviceMock, 0)
|
||||
->deleteById($this->getExpectedDocumentId($id, 'Stage'));
|
||||
|
||||
// Delete the stage record
|
||||
Versioned::reading_stage('Stage');
|
||||
Phockito::reset($serviceMock);
|
||||
Versioned::set_stage('Stage');
|
||||
|
||||
$item = new SearchVariantVersionedTest_Item(array('TestText' => 'Too'));
|
||||
$item->write();
|
||||
$item->publish('Stage', 'Live');
|
||||
$item->copyVersionToStage('Stage', 'Live');
|
||||
$id = clone $item;
|
||||
$item->delete();
|
||||
|
||||
// Check that only the 'Stage' version is deleted
|
||||
$this->getServiceMock(['addDocument', 'commit', 'deleteById'])
|
||||
->expects($this->exactly(1))
|
||||
->method('deleteById')
|
||||
->with($this->equalTo($this->getExpectedDocumentId($id, 'Stage')));
|
||||
|
||||
SearchUpdater::flush_dirty_indexes();
|
||||
Phockito::verify($serviceMock, 1)
|
||||
->deleteById($this->getExpectedDocumentId($id, 'Stage'));
|
||||
Phockito::verify($serviceMock, 0)
|
||||
->deleteById($this->getExpectedDocumentId($id, 'Live'));
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrVersionedTest;
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest;
|
||||
|
||||
if (!class_exists('Phockito')) {
|
||||
if (!class_exists('\Phockito')) {
|
||||
return;
|
||||
}
|
||||
|
||||
Phockito::include_hamcrest(false);
|
||||
\Phockito::include_hamcrest(false);
|
||||
|
||||
class SolrDocumentMatcher extends Hamcrest_BaseMatcher
|
||||
class SolrDocumentMatcher extends \Hamcrest_BaseMatcher
|
||||
{
|
||||
protected $properties;
|
||||
|
||||
@ -19,12 +19,12 @@ class SolrDocumentMatcher extends Hamcrest_BaseMatcher
|
||||
|
||||
public function describeTo(\Hamcrest_Description $description)
|
||||
{
|
||||
$description->appendText('Apache_Solr_Document with properties '.var_export($this->properties, true));
|
||||
$description->appendText('\Apache_Solr_Document with properties '.var_export($this->properties, true));
|
||||
}
|
||||
|
||||
public function matches($item)
|
||||
{
|
||||
if (! ($item instanceof Apache_Solr_Document)) {
|
||||
if (! ($item instanceof \Apache_Solr_Document)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrVersionedTest;
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
@ -11,6 +11,8 @@ use SilverStripe\Versioned\Versioned;
|
||||
*/
|
||||
class SolrIndexVersionedTest_Object extends DataObject implements TestOnly {
|
||||
|
||||
private static $table_name = 'SolrIndexVersionedTest_Object';
|
||||
|
||||
private static $extensions = [
|
||||
Versioned::class
|
||||
];
|
||||
|
@ -1,15 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrVersionedTest;
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Solr\SolrIndex;
|
||||
use SilverStripe\FullTextSearch\Tests\SearchVariantVersionedTest\SearchVariantVersionedTest_Item;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrIndexVersionedTest\SolrIndexVersionedTest_Object;
|
||||
|
||||
class SolrVersionedTest_Index extends SolrIndex
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SearchVariantVersionedTest_Item');
|
||||
$this->addClass('SolrIndexVersionedTest_Object');
|
||||
$this->addClass(SearchVariantVersionedTest_Item::class);
|
||||
$this->addClass(SolrIndexVersionedTest_Object::class);
|
||||
$this->addFilterField('TestText');
|
||||
$this->addFulltextField('Content');
|
||||
}
|
||||
|
@ -1,10 +1,23 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Variant;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexQueuedHandler;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexHandler;
|
||||
use SilverStripe\FullTextSearch\Solr\Services\Solr4Service;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Jobs\SolrReindexQueuedJob;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Jobs\SolrReindexGroupQueuedJob;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Variant;
|
||||
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\SolrReindexQueuedTest\SolrReindexQueuedTest_Service;
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJob;
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJobService;
|
||||
|
||||
/**
|
||||
* Additional tests of solr reindexing processes when run with queuedjobs
|
||||
@ -13,8 +26,8 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
{
|
||||
protected $usesDatabase = true;
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'SolrReindexTest_Item'
|
||||
protected static $extra_dataobjects = array(
|
||||
SolrReindexTest_Item::class
|
||||
);
|
||||
|
||||
/**
|
||||
@ -35,28 +48,23 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!class_exists('Phockito')) {
|
||||
$this->skipTest = true;
|
||||
return $this->markTestSkipped("These tests need the Phockito module installed to run");
|
||||
}
|
||||
|
||||
if (!interface_exists('QueuedJob')) {
|
||||
if (!interface_exists('SilverStripe\QueuedJobs\Services\QueuedJob')) {
|
||||
$this->skipTest = true;
|
||||
return $this->markTestSkipped("These tests need the QueuedJobs module installed to run");
|
||||
}
|
||||
|
||||
// Set queued handler for reindex
|
||||
Config::inst()->update('Injector', 'SolrReindexHandler', array(
|
||||
'class' => 'SolrReindexQueuedHandler'
|
||||
Config::modify()->set(Injector::class, SolrReindexHandler::class, array(
|
||||
'class' => SolrReindexQueuedHandler::class
|
||||
));
|
||||
Injector::inst()->registerService(new SolrReindexQueuedHandler(), 'SolrReindexHandler');
|
||||
Injector::inst()->registerService(new SolrReindexQueuedHandler(), SolrReindexHandler::class);
|
||||
|
||||
// Set test variant
|
||||
SolrReindexTest_Variant::enable();
|
||||
|
||||
// Set index list
|
||||
$this->service = $this->getServiceMock();
|
||||
$this->index = singleton('SolrReindexTest_Index');
|
||||
$this->service = $this->serviceMock();
|
||||
$this->index = singleton(SolrReindexTest_Index::class);
|
||||
$this->index->setService($this->service);
|
||||
FullTextSearch::force_index_list($this->index);
|
||||
}
|
||||
@ -69,7 +77,8 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
protected function createDummyData($number)
|
||||
{
|
||||
// Populate dataobjects. Use truncate to generate predictable IDs
|
||||
DB::query('TRUNCATE "SolrReindexTest_Item"');
|
||||
$tableName = DataObject::getSchema()->tableName(SolrReindexTest_Item::class);
|
||||
DB::get_conn()->clearTable($tableName);
|
||||
|
||||
// Note that we don't create any records in variant = 2, to represent a variant
|
||||
// that should be cleared without any re-indexes performed
|
||||
@ -88,9 +97,15 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
*
|
||||
* @return SolrService
|
||||
*/
|
||||
protected function getServiceMock()
|
||||
protected function serviceMock()
|
||||
{
|
||||
return Phockito::mock('Solr4Service');
|
||||
// Setup mock
|
||||
/** @var SilverStripe\FullTextSearch\Solr\Services\Solr4Service|ObjectProphecy $serviceMock */
|
||||
$serviceMock = $this->getMockBuilder(Solr4Service::class)
|
||||
->setMethods(['deleteByQuery', 'addDocument'])
|
||||
->getMock();
|
||||
|
||||
return $serviceMock;
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
@ -115,7 +130,7 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
*/
|
||||
protected function getQueuedJobService()
|
||||
{
|
||||
return singleton('SolrReindexQueuedTest_Service');
|
||||
return Injector::inst()->get(SolrReindexQueuedTest_Service::class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,6 +141,20 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
{
|
||||
$this->createDummyData(18);
|
||||
|
||||
// Deletes are performed in the main task prior to individual groups being processed
|
||||
// 18 records means 3 groups of 6 in each variant (6 total)
|
||||
// Ensure correct call is made to Solr
|
||||
$this->service->expects($this->exactly(2))
|
||||
->method('deleteByQuery')
|
||||
->withConsecutive(
|
||||
[
|
||||
$this->equalTo('-(ClassHierarchy:' . SolrReindexTest_Item::class . ')')
|
||||
],
|
||||
[
|
||||
$this->equalTo('+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +(_testvariant:"2")')
|
||||
]
|
||||
);
|
||||
|
||||
// Create pre-existing jobs
|
||||
$this->getQueuedJobService()->queueJob(new SolrReindexQueuedJob());
|
||||
$this->getQueuedJobService()->queueJob(new SolrReindexGroupQueuedJob());
|
||||
@ -141,7 +170,7 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
|
||||
// Next job should be queue job
|
||||
$job = $this->getQueuedJobService()->getNextJob();
|
||||
$this->assertInstanceOf('SolrReindexQueuedJob', $job);
|
||||
$this->assertInstanceOf(SolrReindexQueuedJob::class, $job);
|
||||
$this->assertEquals(6, $job->getBatchSize());
|
||||
|
||||
// Test that necessary items are created
|
||||
@ -149,28 +178,19 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
$job->setLogger($logger);
|
||||
$job->process();
|
||||
|
||||
// Deletes are performed in the main task prior to individual groups being processed
|
||||
// 18 records means 3 groups of 6 in each variant (6 total)
|
||||
Phockito::verify($this->service, 2)
|
||||
->deleteByQuery(\Hamcrest_Matchers::anything());
|
||||
$this->assertEquals(1, $logger->countMessages('Beginning init of reindex'));
|
||||
$this->assertEquals(6, $logger->countMessages('Queued Solr Reindex Group '));
|
||||
$this->assertEquals(3, $logger->countMessages(' of SolrReindexTest_Item in {"SolrReindexTest_Variant":"0"}'));
|
||||
$this->assertEquals(3, $logger->countMessages(' of SolrReindexTest_Item in {"SolrReindexTest_Variant":"1"}'));
|
||||
$this->assertEquals(3, $logger->countMessages(' of ' . SolrReindexTest_Item::class . ' in {' . json_encode(SolrReindexTest_Variant::class) . ':"0"}'));
|
||||
$this->assertEquals(3, $logger->countMessages(' of ' . SolrReindexTest_Item::class . ' in {' . json_encode(SolrReindexTest_Variant::class) . ':"1"}'));
|
||||
$this->assertEquals(1, $logger->countMessages('Completed init of reindex'));
|
||||
|
||||
|
||||
// Test that invalid classes are removed
|
||||
$this->assertNotEmpty($logger->getMessages('Clearing obsolete classes from SolrReindexTest_Index'));
|
||||
Phockito::verify($this->service, 1)
|
||||
->deleteByQuery('-(ClassHierarchy:SolrReindexTest_Item)');
|
||||
$this->assertNotEmpty($logger->getMessages('Clearing obsolete classes from ' . SolrReindexTest_Index::class));
|
||||
|
||||
// Test that valid classes in invalid variants are removed
|
||||
$this->assertNotEmpty($logger->getMessages(
|
||||
'Clearing all records of type SolrReindexTest_Item in the current state: {"SolrReindexTest_Variant":"2"}'
|
||||
'Clearing all records of type ' . SolrReindexTest_Item::class . ' in the current state: {"' . SolrReindexTest_Variant::class . '":"2"}'
|
||||
));
|
||||
Phockito::verify($this->service, 1)
|
||||
->deleteByQuery('+(ClassHierarchy:SolrReindexTest_Item) +(_testvariant:"2")');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,9 +209,9 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
|
||||
// Check next job is a group queued job
|
||||
$job = $this->getQueuedJobService()->getNextJob();
|
||||
$this->assertInstanceOf('SolrReindexGroupQueuedJob', $job);
|
||||
$this->assertInstanceOf(SolrReindexGroupQueuedJob::class, $job);
|
||||
$this->assertEquals(
|
||||
'Solr Reindex Group (1/3) of SolrReindexTest_Item in {"SolrReindexTest_Variant":"0"}',
|
||||
'Solr Reindex Group (1/3) of ' . SolrReindexTest_Item::class . ' in {' . json_encode(SolrReindexTest_Variant::class) . ':"0"}',
|
||||
$job->getTitle()
|
||||
);
|
||||
|
||||
@ -202,7 +222,7 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
|
||||
// Check tasks completed (as per non-queuedjob version)
|
||||
$this->assertEquals(1, $logger->countMessages('Beginning reindex group'));
|
||||
$this->assertEquals(1, $logger->countMessages('Adding SolrReindexTest_Item'));
|
||||
$this->assertEquals(1, $logger->countMessages('Adding ' . SolrReindexTest_Item::class . ''));
|
||||
$this->assertEquals(1, $logger->countMessages('Queuing commit on all changes'));
|
||||
$this->assertEquals(1, $logger->countMessages('Completed reindex group'));
|
||||
|
||||
@ -217,19 +237,3 @@ class SolrReindexQueuedTest extends SapphireTest
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!class_exists('QueuedJobService')) {
|
||||
return;
|
||||
}
|
||||
|
||||
class SolrReindexQueuedTest_Service extends QueuedJobService implements TestOnly
|
||||
{
|
||||
/**
|
||||
* @return QueuedJob
|
||||
*/
|
||||
public function getNextJob()
|
||||
{
|
||||
$job = $this->getNextPendingJob();
|
||||
return $this->initialiseJob($job);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\FullTextSearch\Tests\SolrReindexQueuedTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
if (!class_exists('SilverStripe\QueuedJobs\Services\QueuedJobService')) {
|
||||
return;
|
||||
}
|
||||
|
||||
use SilverStripe\QueuedJobs\Services\QueuedJobService;
|
||||
|
||||
class SolrReindexQueuedTest_Service extends QueuedJobService implements TestOnly
|
||||
{
|
||||
private static $dependencies = [
|
||||
'queueHandler' => '%$QueueHandler'
|
||||
];
|
||||
|
||||
/**
|
||||
* @return QueuedJob
|
||||
*/
|
||||
public function getNextJob()
|
||||
{
|
||||
$job = $this->getNextPendingJob();
|
||||
return $this->initialiseJob($job);
|
||||
}
|
||||
}
|
@ -1,21 +1,27 @@
|
||||
<?php
|
||||
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
|
||||
use SilverStripe\FullTextSearch\Search\FullTextSearch;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Variant;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Index;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_TestHandler;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_Item;
|
||||
use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_RecordingLogger;
|
||||
use SilverStripe\FullTextSearch\Solr\Reindex\Handlers\SolrReindexHandler;
|
||||
|
||||
if (class_exists('Phockito')) {
|
||||
Phockito::include_hamcrest(false);
|
||||
}
|
||||
use SilverStripe\FullTextSearch\Solr\Services\Solr4Service;
|
||||
use SilverStripe\FullTextSearch\Solr\Tasks\Solr_Reindex;
|
||||
use SilverStripe\Core\Config\Config;
|
||||
use SilverStripe\Core\Injector\Injector;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DB;
|
||||
|
||||
class SolrReindexTest extends SapphireTest
|
||||
{
|
||||
protected $usesDatabase = true;
|
||||
|
||||
protected $extraDataObjects = array(
|
||||
'SolrReindexTest_Item'
|
||||
protected static $extra_dataobjects = array(
|
||||
SolrReindexTest_Item::class
|
||||
);
|
||||
|
||||
/**
|
||||
@ -36,23 +42,18 @@ class SolrReindexTest extends SapphireTest
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if (!class_exists('Phockito')) {
|
||||
$this->skipTest = true;
|
||||
return $this->markTestSkipped("These tests need the Phockito module installed to run");
|
||||
}
|
||||
|
||||
// Set test handler for reindex
|
||||
Config::inst()->update('Injector', 'SolrReindexHandler', array(
|
||||
'class' => 'SolrReindexTest_TestHandler'
|
||||
Config::modify()->set('Injector', SolrReindexHandler::class, array(
|
||||
'class' => SolrReindexTest_TestHandler::class
|
||||
));
|
||||
Injector::inst()->registerService(new SolrReindexTest_TestHandler(), 'SolrReindexHandler');
|
||||
Injector::inst()->registerService(new SolrReindexTest_TestHandler(), SolrReindexHandler::class);
|
||||
|
||||
// Set test variant
|
||||
SolrReindexTest_Variant::enable();
|
||||
|
||||
// Set index list
|
||||
$this->service = $this->getServiceMock();
|
||||
$this->index = singleton('SolrReindexTest_Index');
|
||||
$this->index = singleton(SolrReindexTest_Index::class);
|
||||
$this->index->setService($this->service);
|
||||
FullTextSearch::force_index_list($this->index);
|
||||
}
|
||||
@ -64,8 +65,7 @@ class SolrReindexTest extends SapphireTest
|
||||
*/
|
||||
protected function createDummyData($number)
|
||||
{
|
||||
// Populate dataobjects. Use truncate to generate predictable IDs
|
||||
DB::query('TRUNCATE "SolrReindexTest_Item"');
|
||||
self::resetDBSchema();
|
||||
|
||||
// Note that we don't create any records in variant = 2, to represent a variant
|
||||
// that should be cleared without any re-indexes performed
|
||||
@ -86,7 +86,10 @@ class SolrReindexTest extends SapphireTest
|
||||
*/
|
||||
protected function getServiceMock()
|
||||
{
|
||||
return Phockito::mock('Solr4Service');
|
||||
$serviceMock = $this->getMockBuilder(Solr4Service::class)
|
||||
->setMethods(['deleteByQuery', 'addDocument']);
|
||||
|
||||
return $serviceMock->getMock();
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
@ -115,7 +118,7 @@ class SolrReindexTest extends SapphireTest
|
||||
$variant = SearchVariant::current_state();
|
||||
$this->assertEquals(
|
||||
array(
|
||||
"SolrReindexTest_Variant" => "0"
|
||||
SolrReindexTest_Variant::class => "0"
|
||||
),
|
||||
$variant
|
||||
);
|
||||
@ -125,13 +128,13 @@ class SolrReindexTest extends SapphireTest
|
||||
$this->assertEquals(
|
||||
array(
|
||||
array(
|
||||
"SolrReindexTest_Variant" => "0"
|
||||
SolrReindexTest_Variant::class => "0"
|
||||
),
|
||||
array(
|
||||
"SolrReindexTest_Variant" => "1"
|
||||
SolrReindexTest_Variant::class => "1"
|
||||
),
|
||||
array(
|
||||
"SolrReindexTest_Variant" => "2"
|
||||
SolrReindexTest_Variant::class => "2"
|
||||
)
|
||||
),
|
||||
$allStates
|
||||
@ -158,36 +161,36 @@ class SolrReindexTest extends SapphireTest
|
||||
*/
|
||||
public function testReindexSegmentsGroups()
|
||||
{
|
||||
$this->service->method('deleteByQuery')
|
||||
->withConsecutive(
|
||||
['-(ClassHierarchy:' . SolrReindexTest_Item::class . ')'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +(_testvariant:"2")']
|
||||
);
|
||||
|
||||
$this->createDummyData(120);
|
||||
|
||||
// Initiate re-index
|
||||
$logger = new SolrReindexTest_RecordingLogger();
|
||||
$this->getHandler()->runReindex($logger, 21, 'Solr_Reindex');
|
||||
$this->getHandler()->runReindex($logger, 21, Solr_Reindex::class);
|
||||
|
||||
// Test that invalid classes are removed
|
||||
$this->assertNotEmpty($logger->getMessages('Clearing obsolete classes from SolrReindexTest_Index'));
|
||||
Phockito::verify($this->service, 1)
|
||||
->deleteByQuery('-(ClassHierarchy:SolrReindexTest_Item)');
|
||||
|
||||
$this->assertContains('Clearing obsolete classes from ' . SolrReindexTest_Index::class, $logger->getMessages());
|
||||
//var_dump($logger->getMessages());
|
||||
// Test that valid classes in invalid variants are removed
|
||||
$this->assertNotEmpty($logger->getMessages(
|
||||
'Clearing all records of type SolrReindexTest_Item in the current state: {"SolrReindexTest_Variant":"2"}'
|
||||
));
|
||||
Phockito::verify($this->service, 1)
|
||||
->deleteByQuery('+(ClassHierarchy:SolrReindexTest_Item) +(_testvariant:"2")');
|
||||
$this->assertContains('Clearing all records of type ' . SolrReindexTest_Item::class . ' in the current state: {' . json_encode(SolrReindexTest_Variant::class) . ':"2"}', $logger->getMessages());
|
||||
|
||||
// 120x2 grouped into groups of 21 results in 12 groups
|
||||
$this->assertEquals(12, $logger->countMessages('Called processGroup with '));
|
||||
$this->assertEquals(6, $logger->countMessages('{"SolrReindexTest_Variant":"0"}'));
|
||||
$this->assertEquals(6, $logger->countMessages('{"SolrReindexTest_Variant":"1"}'));
|
||||
$this->assertEquals(6, $logger->countMessages('{' . json_encode(SolrReindexTest_Variant::class) . ':"0"}'));
|
||||
$this->assertEquals(6, $logger->countMessages('{' . json_encode(SolrReindexTest_Variant::class) . ':"1"}'));
|
||||
|
||||
// Given that there are two variants, there should be two group ids of each number
|
||||
$this->assertEquals(2, $logger->countMessages(' SolrReindexTest_Item, group 0 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' SolrReindexTest_Item, group 1 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' SolrReindexTest_Item, group 2 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' SolrReindexTest_Item, group 3 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' SolrReindexTest_Item, group 4 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' SolrReindexTest_Item, group 5 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' ' . SolrReindexTest_Item::class . ', group 0 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' ' . SolrReindexTest_Item::class . ', group 1 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' ' . SolrReindexTest_Item::class . ', group 2 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' ' . SolrReindexTest_Item::class . ', group 3 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' ' . SolrReindexTest_Item::class . ', group 4 of 6'));
|
||||
$this->assertEquals(2, $logger->countMessages(' ' . SolrReindexTest_Item::class . ', group 5 of 6'));
|
||||
|
||||
// Check various group sizes
|
||||
$logger->clear();
|
||||
@ -209,25 +212,23 @@ class SolrReindexTest extends SapphireTest
|
||||
*/
|
||||
public function testRunGroup()
|
||||
{
|
||||
$this->service->method('deleteByQuery')
|
||||
->with('+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=2 u=2}mod(ID, 6)" +(_testvariant:"1")');
|
||||
|
||||
$this->createDummyData(120);
|
||||
$logger = new SolrReindexTest_RecordingLogger();
|
||||
|
||||
// Initiate re-index of third group (index 2 of 6)
|
||||
$state = array('SolrReindexTest_Variant' => '1');
|
||||
$this->getHandler()->runGroup($logger, $this->index, $state, 'SolrReindexTest_Item', 6, 2);
|
||||
$state = array(SolrReindexTest_Variant::class => '1');
|
||||
$this->getHandler()->runGroup($logger, $this->index, $state, SolrReindexTest_Item::class, 6, 2);
|
||||
$idMessage = $logger->filterMessages('Updated ');
|
||||
$this->assertNotEmpty(preg_match('/^Updated (?<ids>[,\d]+)/i', $idMessage[0], $matches));
|
||||
$ids = array_unique(explode(',', $matches['ids']));
|
||||
|
||||
// Test successful
|
||||
$this->assertNotEmpty($logger->getMessages('Adding SolrReindexTest_Item'));
|
||||
$this->assertNotEmpty($logger->getMessages('Adding ' . SolrReindexTest_Item::class));
|
||||
$this->assertNotEmpty($logger->getMessages('Done'));
|
||||
|
||||
// Test that items in this variant / group are cleared from solr
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=2 u=2}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
|
||||
// Test that items in this variant / group are re-indexed
|
||||
// 120 divided into 6 groups should be 20 at least (max 21)
|
||||
$this->assertEquals(21, count($ids), 'Group size is about 20', 1);
|
||||
@ -242,16 +243,27 @@ class SolrReindexTest extends SapphireTest
|
||||
*/
|
||||
public function testRunAllGroups()
|
||||
{
|
||||
$this->service->method('deleteByQuery')
|
||||
->withConsecutive(
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=0 u=0}mod(ID, 6)" +(_testvariant:"1")'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=1 u=1}mod(ID, 6)" +(_testvariant:"1")'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=2 u=2}mod(ID, 6)" +(_testvariant:"1")'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=3 u=3}mod(ID, 6)" +(_testvariant:"1")'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=4 u=4}mod(ID, 6)" +(_testvariant:"1")'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=5 u=5}mod(ID, 6)" +(_testvariant:"1")'],
|
||||
['+(ClassHierarchy:' . SolrReindexTest_Item::class . ') +_query_:"{!frange l=6 u=6}mod(ID, 6)" +(_testvariant:"1")']
|
||||
);
|
||||
|
||||
$this->createDummyData(120);
|
||||
$logger = new SolrReindexTest_RecordingLogger();
|
||||
|
||||
// Test that running all groups covers the complete set of ids
|
||||
$state = array('SolrReindexTest_Variant' => '1');
|
||||
$state = array(SolrReindexTest_Variant::class => '1');
|
||||
for ($i = 0; $i < 6; $i++) {
|
||||
// See testReindexSegmentsGroups for test that each of these states is invoked during a full reindex
|
||||
$this
|
||||
->getHandler()
|
||||
->runGroup($logger, $this->index, $state, 'SolrReindexTest_Item', 6, $i);
|
||||
->runGroup($logger, $this->index, $state, SolrReindexTest_Item::class, 6, $i);
|
||||
}
|
||||
|
||||
// Count all ids updated
|
||||
@ -263,24 +275,5 @@ class SolrReindexTest extends SapphireTest
|
||||
|
||||
// Check ids
|
||||
$this->assertEquals(120, count($ids));
|
||||
Phockito::verify($this->service, 6)->deleteByQuery(\Hamcrest_Matchers::anything());
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=0 u=0}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=1 u=1}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=2 u=2}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=3 u=3}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=4 u=4}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
Phockito::verify($this->service, 1)->deleteByQuery(
|
||||
'+(ClassHierarchy:SolrReindexTest_Item) +_query_:"{!frange l=5 u=5}mod(ID, 6)" +(_testvariant:"1")'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ class SolrReindexTest_Index extends SolrIndex implements TestOnly
|
||||
{
|
||||
public function init()
|
||||
{
|
||||
$this->addClass('SolrReindexTest_Item');
|
||||
$this->addClass(SolrReindexTest_Item::class);
|
||||
$this->addAllFulltextFields();
|
||||
}
|
||||
}
|
||||
|
@ -9,8 +9,10 @@ use SilverStripe\FullTextSearch\Tests\SolrReindexTest\SolrReindexTest_ItemExtens
|
||||
/**
|
||||
* Does not have any variant extensions
|
||||
*/
|
||||
class SolrReindexTest_Item extends DataObject implements TestOnly
|
||||
class SolrReindexTest_Item extends DataObject
|
||||
{
|
||||
private static $table_name = 'SolrReindexTest_Item';
|
||||
|
||||
private static $extensions = [
|
||||
SolrReindexTest_ItemExtension::class
|
||||
];
|
||||
|
@ -17,7 +17,7 @@ class SolrReindexTest_ItemExtension extends DataExtension implements TestOnly
|
||||
/**
|
||||
* Filter records on the current variant
|
||||
*
|
||||
* @param SQLQuery $query
|
||||
* @param SQLSelect $query
|
||||
* @param DataQuery $dataQuery
|
||||
*/
|
||||
public function augmentSQL(SQLSelect $query, DataQuery $dataQuery = NULL)
|
||||
|
@ -4,6 +4,7 @@ namespace SilverStripe\FullTextSearch\Tests\SolrReindexTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
/**
|
||||
* Dummy variant that selects items with field Varient matching the current value
|
||||
@ -28,7 +29,7 @@ class SolrReindexTest_Variant extends SearchVariant implements TestOnly
|
||||
|
||||
self::$current = 0;
|
||||
self::$variants = array(
|
||||
'SolrReindexTest_Variant' => singleton('SolrReindexTest_Variant')
|
||||
self::class => singleton(self::class)
|
||||
);
|
||||
}
|
||||
|
||||
@ -79,7 +80,7 @@ class SolrReindexTest_Variant extends SearchVariant implements TestOnly
|
||||
'name' => '_testvariant',
|
||||
'field' => '_testvariant',
|
||||
'fullfield' => '_testvariant',
|
||||
'base' => ClassInfo::baseDataClass($class),
|
||||
'base' => DataObject::getSchema()->baseDataClass($class),
|
||||
'origin' => $class,
|
||||
'type' => 'Int',
|
||||
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
|
||||
@ -94,8 +95,8 @@ class SolrReindexTest_Variant extends SearchVariant implements TestOnly
|
||||
|
||||
public function appliesTo($class, $includeSubclasses)
|
||||
{
|
||||
return $class === 'SolrReindexTest_Item' ||
|
||||
($includeSubclasses && is_subclass_of($class, 'SolrReindexTest_Item', true));
|
||||
return $class === SolrReindexTest_Item::class ||
|
||||
($includeSubclasses && is_subclass_of($class, SolrReindexTest_Item::class, true));
|
||||
}
|
||||
|
||||
public function appliesToEnvironment()
|
||||
|
Loading…
Reference in New Issue
Block a user