2011-05-02 06:33:05 +02:00
|
|
|
<?php
|
|
|
|
|
2017-04-21 02:23:27 +02:00
|
|
|
namespace SilverStripe\FullTextSearch\Search;
|
|
|
|
|
2017-04-22 20:21:06 +02:00
|
|
|
use ReflectionClass;
|
2017-02-17 04:27:38 +01:00
|
|
|
use SilverStripe\Core\Config\Config;
|
|
|
|
use SilverStripe\Core\ClassInfo;
|
2011-05-02 06:33:05 +02:00
|
|
|
/**
|
|
|
|
* Base class to manage active search indexes.
|
|
|
|
*/
|
2015-11-21 07:19:20 +01:00
|
|
|
class FullTextSearch
|
|
|
|
{
|
|
|
|
protected static $all_indexes = null;
|
|
|
|
|
|
|
|
protected static $indexes_by_subclass = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Optional list of index names to limit to. If left empty, all subclasses of SearchIndex
|
|
|
|
* will be used
|
|
|
|
*
|
|
|
|
* @var array
|
|
|
|
* @config
|
|
|
|
*/
|
|
|
|
private static $indexes = array();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get all the instantiable search indexes (so all the user created indexes, but not the connector or library level
|
|
|
|
* abstract indexes). Can optionally be filtered to only return indexes that are subclasses of some class
|
|
|
|
*
|
|
|
|
* @static
|
|
|
|
* @param String $class - Class name to filter indexes by, so that all returned indexes are subclasses of provided class
|
|
|
|
* @param bool $rebuild - If true, don't use cached values
|
|
|
|
*/
|
|
|
|
public static function get_indexes($class = null, $rebuild = false)
|
|
|
|
{
|
|
|
|
if ($rebuild) {
|
|
|
|
self::$all_indexes = null;
|
|
|
|
self::$indexes_by_subclass = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$class) {
|
|
|
|
if (self::$all_indexes === null) {
|
|
|
|
// Get declared indexes, or otherwise default to all subclasses of SearchIndex
|
|
|
|
$classes = Config::inst()->get(__CLASS__, 'indexes')
|
2017-04-22 20:21:06 +02:00
|
|
|
?: ClassInfo::subclassesFor('SilverStripe\FullTextSearch\Solr\SearchIndex');
|
2015-11-21 07:19:20 +01:00
|
|
|
|
|
|
|
$hidden = array();
|
|
|
|
$candidates = array();
|
|
|
|
foreach ($classes as $class) {
|
|
|
|
// Check if this index is disabled
|
|
|
|
$hides = $class::config()->hide_ancestor;
|
|
|
|
if ($hides) {
|
|
|
|
$hidden[] = $hides;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if this index is abstract
|
|
|
|
$ref = new ReflectionClass($class);
|
|
|
|
if (!$ref->isInstantiable()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$candidates[] = $class;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($hidden) {
|
|
|
|
$candidates = array_diff($candidates, $hidden);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create all indexes
|
|
|
|
$concrete = array();
|
|
|
|
foreach ($candidates as $class) {
|
|
|
|
$concrete[$class] = singleton($class);
|
|
|
|
}
|
|
|
|
|
|
|
|
self::$all_indexes = $concrete;
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::$all_indexes;
|
|
|
|
} else {
|
|
|
|
if (!isset(self::$indexes_by_subclass[$class])) {
|
|
|
|
$all = self::get_indexes();
|
|
|
|
|
|
|
|
$valid = array();
|
|
|
|
foreach ($all as $indexclass => $instance) {
|
|
|
|
if (is_subclass_of($indexclass, $class)) {
|
|
|
|
$valid[$indexclass] = $instance;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self::$indexes_by_subclass[$class] = $valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::$indexes_by_subclass[$class];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sometimes, like when in tests, you want to restrain the actual indexes to a subset
|
|
|
|
*
|
|
|
|
* Call with one argument - an array of class names, index instances or classname => indexinstance pairs (can be mixed).
|
|
|
|
* Alternatively call with multiple arguments, each of which is a class name or index instance
|
|
|
|
*
|
|
|
|
* From then on, fulltext search system will only see those indexes passed in this most recent call.
|
|
|
|
*
|
|
|
|
* Passing in no arguments resets back to automatic index list
|
|
|
|
*
|
|
|
|
* Alternatively you can use `FullTextSearch.indexes` to configure a list of indexes via config.
|
|
|
|
*/
|
|
|
|
public static function force_index_list()
|
|
|
|
{
|
|
|
|
$indexes = func_get_args();
|
|
|
|
|
|
|
|
// No arguments = back to automatic
|
|
|
|
if (!$indexes) {
|
|
|
|
self::get_indexes(null, true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Arguments can be a single array
|
|
|
|
if (is_array($indexes[0])) {
|
|
|
|
$indexes = $indexes[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset to empty first
|
|
|
|
self::$all_indexes = array();
|
|
|
|
self::$indexes_by_subclass = array();
|
|
|
|
|
|
|
|
// And parse out alternative type combos for arguments and add to allIndexes
|
|
|
|
foreach ($indexes as $class => $index) {
|
|
|
|
if (is_string($index)) {
|
|
|
|
$class = $index;
|
|
|
|
$index = singleton($class);
|
|
|
|
}
|
|
|
|
if (is_numeric($class)) {
|
|
|
|
$class = get_class($index);
|
|
|
|
}
|
|
|
|
|
|
|
|
self::$all_indexes[$class] = $index;
|
|
|
|
}
|
|
|
|
}
|
2011-05-02 06:33:05 +02:00
|
|
|
}
|