Index now supports multiple relations with the same name.

This commit is contained in:
Mojmir Fendek 2017-06-16 09:39:37 +12:00 committed by Daniel Hensby
parent a6d1988e50
commit 2b3357565e
No known key found for this signature in database
GPG Key ID: B00D1E9767F0B06E
1 changed files with 52 additions and 5 deletions

View File

@ -37,6 +37,27 @@ abstract class SearchIndex extends ViewableData
*/
private static $hide_ancestor;
/**
* Used to separate class name and relation name in the sources array
* this string must not be present in class name
* @var string
* @config
*/
private static $class_delimiter = '_|_';
/**
* This is used to clean the source name from suffix
* suffixes are needed to support multiple relations with the same name on different page types
* @param string $source
* @return string
*/
private function getSourceName($source)
{
$source = explode(self::config()->get('class_delimiter'), $source);
return $source[0];
}
public function __construct()
{
parent::__construct();
@ -77,19 +98,35 @@ abstract class SearchIndex extends ViewableData
foreach ($lookups as $lookup) {
$next = array();
foreach ($sources as $source => $options) {
$class = null;
foreach ($sources as $source => $baseOptions) {
$source = $this->getSourceName($source);
foreach (SearchIntrospection::hierarchy($source, $options['include_children']) as $dataclass) {
foreach (SearchIntrospection::hierarchy($source, $baseOptions['include_children']) as $dataclass) {
$class = null;
$options = $baseOptions;
$singleton = singleton($dataclass);
if ($hasOne = $singleton->has_one($lookup)) {
// we only want to include base class for relation, omit classes that inherited the relation
$relationList = Config::inst()->get($dataclass, 'has_one', Config::UNINHERITED);
$relationList = (!is_null($relationList)) ? $relationList : array();
if (!array_key_exists($lookup, $relationList)) {
continue;
}
$class = $hasOne;
$options['lookup_chain'][] = array(
'call' => 'method', 'method' => $lookup,
'through' => 'has_one', 'class' => $dataclass, 'otherclass' => $class, 'foreignkey' => "{$lookup}ID"
);
} elseif ($hasMany = $singleton->has_many($lookup)) {
// we only want to include base class for relation, omit classes that inherited the relation
$relationList = Config::inst()->get($dataclass, 'has_many', Config::UNINHERITED);
$relationList = (!is_null($relationList)) ? $relationList : array();
if (!array_key_exists($lookup, $relationList)) {
continue;
}
$class = $hasMany;
$options['multi_valued'] = true;
$options['lookup_chain'][] = array(
@ -97,6 +134,13 @@ abstract class SearchIndex extends ViewableData
'through' => 'has_many', 'class' => $dataclass, 'otherclass' => $class, 'foreignkey' => $singleton->getRemoteJoinField($lookup, 'has_many')
);
} elseif ($manyMany = $singleton->many_many($lookup)) {
// we only want to include base class for relation, omit classes that inherited the relation
$relationList = Config::inst()->get($dataclass, 'many_many', Config::UNINHERITED);
$relationList = (!is_null($relationList)) ? $relationList : array();
if (!array_key_exists($lookup, $relationList)) {
continue;
}
$class = $manyMany[1];
$options['multi_valued'] = true;
$options['lookup_chain'][] = array(
@ -109,8 +153,10 @@ abstract class SearchIndex extends ViewableData
if (!isset($options['origin'])) {
$options['origin'] = $dataclass;
}
$next[$class] = $options;
continue 2;
// we add suffix here to prevent the relation to be overwritten by other instances
// all sources lookups must clean the source name before reading it via getSourceName()
$next[$class . self::config()->get('class_delimiter') . $dataclass] = $options;
}
}
}
@ -123,6 +169,7 @@ abstract class SearchIndex extends ViewableData
}
foreach ($sources as $class => $options) {
$class = $this->getSourceName($class);
$dataclasses = SearchIntrospection::hierarchy($class, $options['include_children']);
while (count($dataclasses)) {