Issues (50)

src/States/SiteState.php (1 issue)

Labels
Severity
1
<?php
2
/**
3
 * class SiteState|Firesphere\SearchBackend\States\SiteState Base implementation of SiteState to be used by e.g.
4
 * the Fluent extension
5
 *
6
 * @package Firesphere\Search\Backend
7
 * @author Simon `Firesphere` Erkelens; Marco `Sheepy` Hermo
8
 * @copyright Copyright (c) 2018 - now() Firesphere & Sheepy
9
 */
10
11
namespace Firesphere\SearchBackend\States;
12
13
use Firesphere\SearchBackend\Helpers\FieldResolver;
14
use Firesphere\SearchBackend\Interfaces\SiteStateInterface;
15
use ReflectionClass;
16
use ReflectionException;
17
use SilverStripe\Core\ClassInfo;
18
use SilverStripe\Core\Config\Configurable;
19
use SilverStripe\Core\Injector\Injectable;
20
use SilverStripe\ORM\DataObject;
21
22
/**
23
 * Class SiteState
24
 *
25
 * Determine and apply the state of the site currently. This is used at index-time to figure out what state to index.
26
 * An example of this is the FluentSearchVariant extension from Fluent.
27
 *
28
 * Fluent uses the old SearchVariant method, which is actually not that bad a concept. These "Variants", now called
29
 * "States" set the state of the site to a required setting for each available state.
30
 *
31
 * States SHOULD add their own states through an extension of this class and implement {@link SiteStateInterface},
32
 * otherwise it won't be called.
33
 * {@link FluentIndexExtension::onBeforeInit()}
34
 *
35
 * States, options, etc. are simplified for a more streamlined approach
36
 *
37
 * @package Firesphere\Search\Backend
38
 */
39
abstract class SiteState
40
{
41
    use Configurable;
42
    use Injectable;
43
44
    public const DEFAULT_STATE = 'default';
45
    /**
46
     * States that can be applied
47
     *
48
     * @var array
49
     */
50
    public static $states = [
51
        self::DEFAULT_STATE,
52
    ];
53
    /**
54
     * Variants of SiteState that can be activated
55
     *
56
     * @var array
57
     */
58
    public static $variants = [];
59
    /**
60
     * @var array Default states
61
     */
62
    protected static $defaultStates = [];
63
    /**
64
     * @var bool Is this State enabled
65
     */
66
    public $enabled = true;
67
    /**
68
     * @var string current state
69
     */
70
    protected $state;
71
72
    /**
73
     * Get available states
74
     *
75
     * @static
76
     * @return array
77
     */
78
    public static function getStates(): array
79
    {
80
        return self::$states;
81
    }
82
83
    /**
84
     * Set states
85
     *
86
     * @static
87
     * @param array $states
88
     */
89
    public static function setStates(array $states): void
90
    {
91
        self::$states = $states;
92
    }
93
94
    /**
95
     * Add a state
96
     *
97
     * @static
98
     * @param $state
99
     */
100
    public static function addState($state): void
101
    {
102
        self::$states[] = $state;
103
    }
104
105
    /**
106
     * Add multiple states
107
     *
108
     * @static
109
     * @param array $states
110
     */
111
    public static function addStates(array $states): void
112
    {
113
        self::$states = array_merge(self::$states, $states);
114
    }
115
116
    /**
117
     * Does this class, it's parent (or optionally one of it's children) have the passed extension attached?
118
     *
119
     * @static
120
     * @param string $class
121
     * @param string $extension
122
     * @return bool
123
     * @throws ReflectionException
124
     */
125
    public static function hasExtension($class, $extension): bool
126
    {
127
        /** @var DataObject $relatedclass */
128
        foreach (FieldResolver::gethierarchy($class) as $relatedclass) {
129
            if ($relatedclass::has_extension($extension)) {
130
                return true;
131
            }
132
        }
133
134
        return false;
135
    }
136
137
    /**
138
     * Get the current state of every variant
139
     *
140
     * @static
141
     * @return array
142
     * @throws ReflectionException
143
     */
144
    public static function currentStates(): array
145
    {
146
        foreach (self::variants() as $variant => $instance) {
147
            self::$defaultStates[$variant] = $instance->currentState();
148
        }
149
150
        return self::$defaultStates;
151
    }
152
153
    /**
154
     * Returns an array of variants.
155
     *
156
     * @static
157
     * @param bool $force Force updating the variants
158
     * @return array - An array of (string)$variantClassName => (Object)$variantInstance pairs
159
     * @throws ReflectionException
160
     */
161
    public static function variants($force = false): array
162
    {
163
        // Build up and cache a list of all search variants (subclasses of SearchVariant)
164
        if (empty(self::$variants) || $force) {
165
            $classes = ClassInfo::subclassesFor(static::class);
166
167
            foreach ($classes as $variantclass) {
168
                self::isApplicable($variantclass);
169
            }
170
        }
171
172
        return self::$variants;
173
    }
174
175
    /**
176
     * Is this extension applied and instantiable, and should it be applied to
177
     * the current state of the site
178
     *
179
     * @static
180
     * @param $variantClass
181
     * @return bool
182
     * @throws ReflectionException
183
     */
184
    public static function isApplicable($variantClass): bool
185
    {
186
        $ref = new ReflectionClass($variantClass);
187
        if ($ref->isInstantiable()) {
188
            /** @var SiteState $variant */
189
            $variant = singleton($variantClass);
190
            if ($variant->appliesToEnvironment() && $variant->isEnabled()) {
191
                self::$variants[$variantClass] = $variant;
192
193
                return true;
194
            }
195
        }
196
197
        return false;
198
    }
199
200
    /**
201
     * Does this state apply to the current object/environment settings
202
     *
203
     * @return bool
204
     */
205
    public function appliesToEnvironment(): bool
206
    {
207
        return $this->enabled;
208
    }
209
210
    /**
211
     * Is this state enabled
212
     *
213
     * @return bool
214
     */
215
    public function isEnabled(): bool
216
    {
217
        return $this->enabled;
218
    }
219
220
    /**
221
     * Set the state to whatever is required. Most commonly true
222
     *
223
     * @param bool $enabled
224
     */
225
    public function setEnabled(bool $enabled): void
226
    {
227
        $this->enabled = $enabled;
228
    }
229
230
    /**
231
     * Activate a site state for indexing
232
     *
233
     * @param $state
234
     * @throws ReflectionException
235
     */
236
    public static function withState($state): void
237
    {
238
        /**
239
         * @var string $variant
240
         * @var SiteStateInterface $instance
241
         */
242
        foreach (self::variants() as $variant => $instance) {
243
            if ($state === self::DEFAULT_STATE) {
244
                $instance->setDefaultState(self::$defaultStates[$variant]);
245
            } elseif ($instance->stateIsApplicable($state)) {
246
                $instance->activateState($state);
247
            }
248
        }
249
    }
250
251
    /**
252
     * Alter the query for each instance
253
     *
254
     * @param BaseQuery $query
0 ignored issues
show
The type Firesphere\SearchBackend\States\BaseQuery was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
255
     * @throws ReflectionException
256
     */
257
    public static function alterQuery(&$query): void
258
    {
259
        /**
260
         * @var string $variant
261
         * @var SiteStateInterface $instance
262
         */
263
        foreach (self::variants() as $variant => $instance) {
264
            $instance->updateQuery($query);
265
        }
266
    }
267
268
    /**
269
     * Get the states set as default
270
     *
271
     * @return array
272
     */
273
    public static function getDefaultStates(): array
274
    {
275
        return self::$defaultStates;
276
    }
277
278
    /**
279
     * Set the default states
280
     *
281
     * @param array $defaultStates
282
     */
283
    public static function setDefaultStates(array $defaultStates): void
284
    {
285
        self::$defaultStates = $defaultStates;
286
    }
287
}
288