Passed
Push — hans/state-improvements ( 259e4b...c3787a )
by Simon
07:20
created

SiteState::setDefaultStates()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

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