FIX Escape backslashes in class namespaces when performing queries, tidy up SearchVariantVersioned a bit

This commit is contained in:
Robbie Averill 2017-11-16 13:59:15 +13:00
parent a26f4370e4
commit fbc4c0e81d
4 changed files with 46 additions and 21 deletions

View File

@ -11,6 +11,7 @@ use SilverStripe\FullTextSearch\Search\SearchIntrospection;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant;
use SilverStripe\FullTextSearch\Utils\MultipleArrayIterator;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBString;
use SilverStripe\ORM\Queries\SQLSelect;
use SilverStripe\View\ViewableData;
@ -356,17 +357,16 @@ abstract class SearchIndex extends ViewableData
public function addAllFulltextFields($includeSubclasses = true)
{
foreach ($this->getClasses() as $class => $options) {
foreach (SearchIntrospection::hierarchy($class, $includeSubclasses, true) as $dataclass) {
$fields = DataObject::getSchema()->databaseFields($class);
$classHierarchy = SearchIntrospection::hierarchy($class, $includeSubclasses, true);
foreach ($classHierarchy as $dataClass) {
$fields = DataObject::getSchema()->databaseFields($dataClass);
foreach ($fields as $field => $type) {
if (preg_match('/^(\w+)\(/', $type, $match)) {
$type = $match[1];
}
list($type, $args) = ClassInfo::parse_class_spec($type);
// Get class from shortName
/** @var DBField $object */
$object = Injector::inst()->get($type, false, ['Name' => 'test']);
if ($object instanceof DBString) {
$this->addFulltextField($field);
}

View File

@ -21,7 +21,7 @@ class SearchVariantVersioned extends SearchVariant
}
public function reindexStates()
{
return array('Stage', 'Live');
return [Versioned::DRAFT, Versioned::LIVE];
}
public function activateState($state)
{
@ -30,23 +30,29 @@ class SearchVariantVersioned extends SearchVariant
public function alterDefinition($class, $index)
{
$self = get_class($this);
$this->addFilterField($index, '_versionedstage', array(
$this->addFilterField($index, '_versionedstage', [
'name' => '_versionedstage',
'field' => '_versionedstage',
'fullfield' => '_versionedstage',
'base' => DataObject::getSchema()->baseDataClass($class),
'origin' => $class,
'type' => 'String',
'lookup_chain' => array(array('call' => 'variant', 'variant' => $self, 'method' => 'currentState'))
));
'lookup_chain' => [
[
'call' => 'variant',
'variant' => get_class($this),
'method' => 'currentState'
]
]
]);
}
public function alterQuery($query, $index)
{
$stage = $this->currentState();
$query->filter('_versionedstage', array($stage, SearchQuery::$missing));
$query->filter('_versionedstage', [
$this->currentState(),
SearchQuery::$missing
]);
}
public function extractManipulationState(&$manipulation)
@ -55,11 +61,11 @@ class SearchVariantVersioned extends SearchVariant
foreach ($manipulation as $table => $details) {
$class = $details['class'];
$stage = 'Stage';
$stage = Versioned::DRAFT;
if (preg_match('/^(.*)_Live$/', $table, $matches)) {
if (preg_match('/^(.*)_' . Versioned::LIVE . '$/', $table, $matches)) {
$class = DataObject::getSchema()->tableClass($matches[1]);
$stage = 'Live';
$stage = Versioned::LIVE;
}
if (ClassInfo::exists($class) && $this->appliesTo($class, false)) {
@ -80,7 +86,7 @@ class SearchVariantVersioned extends SearchVariant
$self = get_class($this);
foreach ($ids as $i => $statefulid) {
$ids[$i]['state'][$self] = $suffix ? $suffix : 'Stage';
$ids[$i]['state'][$self] = $suffix ? $suffix : Versioned::DRAFT;
}
}
}

View File

@ -711,9 +711,9 @@ abstract class SolrIndex extends SearchIndex
$classq = array();
foreach ($query->classes as $class) {
if (!empty($class['includeSubclasses'])) {
$classq[] = 'ClassHierarchy:'.$class['class'];
$classq[] = 'ClassHierarchy:' . $this->sanitiseClassName($class['class']);
} else {
$classq[] = 'ClassName:'.$class['class'];
$classq[] = 'ClassName:' . $this->sanitiseClassName($class['class']);
}
}
if ($classq) {
@ -845,6 +845,16 @@ abstract class SolrIndex extends SearchIndex
return $ret;
}
/**
* Solr requires namespaced classes to have double escaped backslashes
*
* @param string $className E.g. My\Object\Here
* @return string E.g. My\\Object\\Here
*/
public function sanitiseClassName($className)
{
return str_replace('\\', '\\\\', $className);
}
/**
* Get the query (q) component for this search

View File

@ -328,6 +328,15 @@ class SolrIndexTest extends SapphireTest
);
}
public function testSanitiseClassName()
{
$index = new SolrIndexTest_FakeIndex2;
$this->assertSame(
'SilverStripe\\\\FullTextSearch\\\\Tests\\\\SolrIndexTest',
$index->sanitiseClassName(static::class)
);
}
protected function getFakeRawSolrResponse()
{
return new \Apache_Solr_Response(