silverstripe-fulltextsearch/code/search/FullTextSearch.php

127 lines
3.4 KiB
PHP
Raw Normal View History

<?php
/**
* Base class to manage active search indexes.
*/
class FullTextSearch {
static protected $all_indexes = null;
static protected $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
*/
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')
?: ClassInfo::subclassesFor('SearchIndex');
$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.
*/
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;
}
}
}