Elliot Sawyer 1728a62af5 WIP: Silverstripe 4 compatibility
Thanks to Marco Hermo and Brett Tasker for helping with this
* Bump framework/cms to ^4.0@dev
* WIP Silverstripe 4 compatibility fixes
* more replacements and patches to migrate this module to 4.0
* Update composer.json
* remove php <5.5 from travis.yml
* WIP more SS4 compatibility fixes
* WIP fix solr path to use DIR, avoid hardcoded module name
* WIP respect current include path
* WIP Namespacing and use on SearchIndex class
* Namespacing for tests
* WIP add namespaces to all classes
* Second push of Test changes + namespacing
* WIP split Solr files with multiple classes into single file / single class. Adjust namespaces
* Fix PHP errors in test
* break out search components with multiple classes into individual files and change namespaces
* Update namespacing for Search indexes and variants in tests
* Batch fixes for tests #2
* Update _config.php to use namespace
* Use root namespace in referencing Apache_Solr_Document
* Migrate task names so that the name is not fully qualified
2017-04-25 20:46:35 +12:00

147 lines
4.3 KiB
PHP

<?php
namespace SilverStripe\FullTextSearch\Search\Processors;
abstract class SearchUpdateProcessor
{
/**
* List of dirty records to process in format
*
* array(
* '$BaseClass' => array(
* '$State Key' => array(
* 'state' => array(
* 'key1' => 'value',
* 'key2' => 'value'
* ),
* 'ids' => array(
* '*id*' => array(
* '*Index Name 1*',
* '*Index Name 2*'
* )
* )
* )
* )
* )
*
* @var array
*/
protected $dirty;
public function __construct()
{
$this->dirty = array();
}
public function addDirtyIDs($class, $statefulids, $index)
{
$base = ClassInfo::baseDataClass($class);
$forclass = isset($this->dirty[$base]) ? $this->dirty[$base] : array();
foreach ($statefulids as $statefulid) {
$id = $statefulid['id'];
$state = $statefulid['state'];
$statekey = serialize($state);
if (!isset($forclass[$statekey])) {
$forclass[$statekey] = array('state' => $state, 'ids' => array($id => array($index)));
} elseif (!isset($forclass[$statekey]['ids'][$id])) {
$forclass[$statekey]['ids'][$id] = array($index);
} elseif (array_search($index, $forclass[$statekey]['ids'][$id]) === false) {
$forclass[$statekey]['ids'][$id][] = $index;
// dirty count stays the same
}
}
$this->dirty[$base] = $forclass;
}
/**
* Generates the list of indexes to process for the dirty items
*
* @return array
*/
protected function prepareIndexes()
{
$originalState = SearchVariant::current_state();
$dirtyIndexes = array();
$dirty = $this->getSource();
$indexes = FullTextSearch::get_indexes();
foreach ($dirty as $base => $statefulids) {
if (!$statefulids) {
continue;
}
foreach ($statefulids as $statefulid) {
$state = $statefulid['state'];
$ids = $statefulid['ids'];
SearchVariant::activate_state($state);
// Ensure that indexes for all new / updated objects are included
$objs = DataObject::get($base)->byIDs(array_keys($ids));
foreach ($objs as $obj) {
foreach ($ids[$obj->ID] as $index) {
if (!$indexes[$index]->variantStateExcluded($state)) {
$indexes[$index]->add($obj);
$dirtyIndexes[$index] = $indexes[$index];
}
}
unset($ids[$obj->ID]);
}
// Generate list of records that do not exist and should be removed
foreach ($ids as $id => $fromindexes) {
foreach ($fromindexes as $index) {
if (!$indexes[$index]->variantStateExcluded($state)) {
$indexes[$index]->delete($base, $id, $state);
$dirtyIndexes[$index] = $indexes[$index];
}
}
}
}
}
SearchVariant::activate_state($originalState);
return $dirtyIndexes;
}
/**
* Commits the specified index to the Solr service
*
* @param SolrIndex $index Index object
* @return bool Flag indicating success
*/
protected function commitIndex($index)
{
return $index->commit() !== false;
}
/**
* Gets the record data source to process
*
* @return array
*/
protected function getSource()
{
return $this->dirty;
}
/**
* Process all indexes, returning true if successful
*
* @return bool Flag indicating success
*/
public function process()
{
// Generate and commit all instances
$indexes = $this->prepareIndexes();
foreach ($indexes as $index) {
if (!$this->commitIndex($index)) {
return false;
}
}
return true;
}
abstract public function triggerProcessing();
}