Skip to content

Commit

Permalink
Merge pull request #202 from creative-commoners/pulls/3.0/irrelevant-…
Browse files Browse the repository at this point in the history
…variant-isolation

NEW Add SearchVariant::withCommon to run callbacks on relevant variants rather than all
  • Loading branch information
NightJar authored Mar 6, 2018
2 parents 415fdeb + c64c0c0 commit 48f3df7
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 9 deletions.
40 changes: 38 additions & 2 deletions src/Search/Variants/SearchVariant.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -93,6 +92,7 @@ abstract public function alterQuery($query, $index);
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);

Expand Down Expand Up @@ -166,6 +166,42 @@ public static function with($class = null, $includeSubclasses = true)
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,
*
Expand Down
23 changes: 17 additions & 6 deletions src/Solr/SolrIndex.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;
Expand Down Expand Up @@ -710,12 +711,7 @@ public function commit()
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
Expand Down Expand Up @@ -870,6 +866,21 @@ public function search(SearchQuery $query, $offset = -1, $limit = -1, $params =
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
*
Expand Down
2 changes: 1 addition & 1 deletion tests/SolrIndexTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ public function testBoostedField()
$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());
Expand Down

0 comments on commit 48f3df7

Please sign in to comment.