Passed
Push — hans/state-improvements ( a8d3b7...09b1b8 )
by Simon
07:43
created

SiteState::setDefaultStates()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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