Issues (186)

src/Search/FullTextSearch.php (2 issues)

1
<?php
2
3
namespace SilverStripe\FullTextSearch\Search;
4
5
use SilverStripe\Core\ClassInfo;
6
use SilverStripe\Core\Config\Config;
7
use SilverStripe\ORM\DataObject;
8
use SilverStripe\FullTextSearch\Search\Indexes\SearchIndex;
9
use ReflectionClass;
10
11
/**
12
 * Base class to manage active search indexes.
13
 */
14
class FullTextSearch
15
{
16
    protected static $all_indexes = null;
17
18
    protected static $indexes_by_subclass = array();
19
20
    /**
21
     * Optional list of index names to limit to. If left empty, all subclasses of SearchIndex
22
     * will be used
23
     *
24
     * @var array
25
     * @config
26
     */
27
    private static $indexes = array();
0 ignored issues
show
The private property $indexes is not used, and could be removed.
Loading history...
28
29
    /**
30
     * Get all the instantiable search indexes (so all the user created indexes, but not the connector or library level
31
     * abstract indexes). Can optionally be filtered to only return indexes that are subclasses of some class
32
     *
33
     * @static
34
     * @param string $class - Class name to filter indexes by, so that all returned indexes are subclasses of provided
35
     * class
36
     * @param bool $rebuild - If true, don't use cached values
37
     */
38
    public static function get_indexes($class = null, $rebuild = false)
39
    {
40
        if ($rebuild) {
41
            self::$all_indexes = null;
42
            self::$indexes_by_subclass = array();
43
        }
44
45
        if (!$class) {
46
            if (self::$all_indexes === null) {
47
                // Get declared indexes, or otherwise default to all subclasses of SearchIndex
48
                $classes = Config::inst()->get(__CLASS__, 'indexes')
49
                    ?: ClassInfo::subclassesFor(SearchIndex::class);
50
51
                $hidden = array();
52
                $candidates = array();
53
                foreach ($classes as $class) {
54
                    // Check if this index is disabled
55
                    $hides = $class::config()->hide_ancestor;
56
                    if ($hides) {
57
                        $hidden[] = $hides;
58
                    }
59
60
                    // Check if this index is abstract
61
                    $ref = new ReflectionClass($class);
62
                    if (!$ref->isInstantiable()) {
63
                        continue;
64
                    }
65
66
                    $candidates[] = $class;
67
                }
68
69
                if ($hidden) {
70
                    $candidates = array_diff($candidates, $hidden);
71
                }
72
73
                // Create all indexes
74
                $concrete = array();
75
                foreach ($candidates as $class) {
76
                    $concrete[$class] = singleton($class);
77
                }
78
79
                self::$all_indexes = $concrete;
80
            }
81
82
            return self::$all_indexes;
83
        } else {
84
            if (!isset(self::$indexes_by_subclass[$class])) {
85
                $all = self::get_indexes();
86
87
                $valid = array();
88
                foreach ($all as $indexclass => $instance) {
89
                    if (is_subclass_of($indexclass, $class)) {
90
                        $valid[$indexclass] = $instance;
91
                    }
92
                }
93
94
                self::$indexes_by_subclass[$class] = $valid;
95
            }
96
97
            return self::$indexes_by_subclass[$class];
98
        }
99
    }
100
101
    /**
102
     * Sometimes, like when in tests, you want to restrain the actual indexes to a subset
103
     *
104
     * Call with one argument - an array of class names, index instances or classname => indexinstance pairs (can be
105
     * mixed).
106
     * Alternatively call with multiple arguments, each of which is a class name or index instance
107
     *
108
     * From then on, fulltext search system will only see those indexes passed in this most recent call.
109
     *
110
     * Passing in no arguments resets back to automatic index list
111
     *
112
     * Alternatively you can use `FullTextSearch.indexes` to configure a list of indexes via config.
113
     */
114
    public static function force_index_list()
115
    {
116
        $indexes = func_get_args();
117
118
        // No arguments = back to automatic
119
        if (!$indexes) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $indexes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
120
            self::get_indexes(null, true);
121
            return;
122
        }
123
124
        // Arguments can be a single array
125
        if (is_array($indexes[0])) {
126
            $indexes = $indexes[0];
127
        }
128
129
        // Reset to empty first
130
        self::$all_indexes = array();
131
        self::$indexes_by_subclass = array();
132
133
        // And parse out alternative type combos for arguments and add to allIndexes
134
        foreach ($indexes as $class => $index) {
135
            if (is_string($index)) {
136
                $class = $index;
137
                $index = singleton($class);
138
            }
139
            if (is_numeric($class)) {
140
                $class = get_class($index);
141
            }
142
143
            self::$all_indexes[$class] = $index;
144
        }
145
    }
146
}
147