Merge pull request #202 from creative-commoners/pulls/3.0/irrelevant-variant-isolation

NEW Add SearchVariant::withCommon to run callbacks on relevant variants rather than all
This commit is contained in:
Dylan Wagstaff 2018-03-06 13:27:21 +13:00 committed by GitHub
commit 48f3df725a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 56 additions and 9 deletions

View File

@ -2,11 +2,10 @@
namespace SilverStripe\FullTextSearch\Search\Variants;
use SilverStripe\ORM\DataObject;
use ReflectionClass;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Config\Configurable;
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
@ -93,6 +92,7 @@ abstract class SearchVariant
public static function variants($class = null, $includeSubclasses = true)
{
if (!$class) {
// Build up and cache a list of all search variants (subclasses of SearchVariant)
if (self::$variants === null) {
$classes = ClassInfo::subclassesFor(static::class);
@ -166,6 +166,42 @@ abstract class SearchVariant
return self::$call_instances[$key];
}
/**
* Similar to {@link SearchVariant::with}, except will only use variants that apply to at least one of the classes
* in the input array, where {@link SearchVariant::with} will run the query on the specific class you give it.
*
* @param string[] $classes
* @return SearchVariant_Caller
*/
public static function withCommon(array $classes = [])
{
// Allow caching
$cacheKey = sha1(serialize($classes));
if (isset(self::$call_instances[$cacheKey])) {
return self::$call_instances[$cacheKey];
}
// Construct new array of variants applicable to at least one class in the list
$commonVariants = [];
foreach ($classes as $class => $options) {
// Extract relevant class options
$includeSubclasses = isset($options['include_children']) ? $options['include_children'] : true;
// Get the variants for the current class
$variantsForClass = self::variants($class, $includeSubclasses);
// Merge the variants applicable to the current class into the list of common variants, using
// the variant instance to replace any previous versions for the same class name (should be singleton
// anyway).
$commonVariants = array_replace($commonVariants, $variantsForClass);
}
// Cache for future calls
self::$call_instances[$cacheKey] = new SearchVariant_Caller($commonVariants);
return self::$call_instances[$cacheKey];
}
/**
* A shortcut to with when calling without passing in a class,
*

View File

@ -5,6 +5,7 @@ namespace SilverStripe\FullTextSearch\Solr;
use SilverStripe\Control\Director;
use SilverStripe\Core\Environment;
use SilverStripe\FulltextSearch\Search\Indexes\SearchIndex;
use SilverStripe\FullTextSearch\Search\Variants\SearchVariant_Caller;
use SilverStripe\FullTextSearch\Solr\Services\SolrService;
use SilverStripe\FulltextSearch\Search\Queries\SearchQuery;
use SilverStripe\FullTextSearch\Search\Queries\SearchQuery_Range;
@ -710,12 +711,7 @@ abstract class SolrIndex extends SearchIndex
public function search(SearchQuery $query, $offset = -1, $limit = -1, $params = array())
{
$service = $this->getService();
$searchClass = count($query->classes) == 1
? $query->classes[0]['class']
: null;
SearchVariant::with($searchClass)
->call('alterQuery', $query, $this);
$this->applySearchVariants($query);
$q = array(); // Query
$fq = array(); // Filter query
@ -870,6 +866,21 @@ abstract class SolrIndex extends SearchIndex
return $ret;
}
/**
* With a common set of variants that are relevant to at least one class in the list (from either the query or
* the current index), allow them to alter the query to add their variant column conditions.
*
* @param SearchQuery $query
*/
protected function applySearchVariants(SearchQuery $query)
{
$classes = count($query->classes) ? $query->classes : $this->getClasses();
/** @var SearchVariant_Caller $variantCaller */
$variantCaller = SearchVariant::withCommon($classes);
$variantCaller->call('alterQuery', $query, $this);
}
/**
* Solr requires namespaced classes to have double escaped backslashes
*

View File

@ -172,7 +172,7 @@ class SolrIndexTest extends SapphireTest
$this->equalTo([
'qf' => SearchUpdaterTest_Container::class . '_Field1^1.5 '
. SearchUpdaterTest_Container::class . '_Field2^2.1 _text',
'fq' => '+(_versionedstage:"" (*:* -_versionedstage:[* TO *]))',
'fq' => '',
]),
$this->anything()
)->willReturn($this->getFakeRawSolrResponse());