PluginProbe
ElasticPress / 4.4.0
ElasticPress v4.4.0
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
elasticpress / includes / classes / Features.php

Features.php in ElasticPress 4.4.0, at includes/classes/Features.php

300 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Handles registering and storing feature instances
4 *
5 * @since 2.1
6 * @package elasticpress
7 */
8
9 namespace ElasticPress;
10
11 use ElasticPress\Utils as Utils;
12
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit; // Exit if accessed directly.
15 }
16
17 /**
18 * Class for storing and managing features
19 */
20 class Features {
21
22 /**
23 * Stores all features that have been properly included (both active and inactive)
24 *
25 * @since 2.1
26 * @var array
27 */
28 public $registered_features = [];
29
30 /**
31 * Initiate class actions
32 *
33 * @since 2.1
34 */
35 public function setup() {
36 // hooks order matters, make sure feature activation goes before features setup
37 add_action( 'init', array( $this, 'handle_feature_activation' ), 0 );
38 add_action( 'init', array( $this, 'setup_features' ), 0 );
39 }
40
41 /**
42 * Activate a feature
43 *
44 * @param string $slug Feature slug
45 * @since 2.2
46 */
47 public function activate_feature( $slug ) {
48 $this->update_feature( $slug, array( 'active' => true ) );
49 }
50
51 /**
52 * Dectivate a feature
53 *
54 * @param string $slug Feature slug
55 * @param bool $force Whether to force deactivation
56 * @since 2.2
57 */
58 public function deactivate_feature( $slug, $force = true ) {
59 $this->update_feature( $slug, array( 'active' => false ), $force );
60 }
61
62 /**
63 * Registers a feature for use in ElasticPress
64 *
65 * @param Feature $feature An instance of the Feature class
66 * @since 3.0
67 * @return boolean
68 */
69 public function register_feature( Feature $feature ) {
70 $feature_args['slug'] = $feature->slug;
71
72 $this->registered_features[ $feature->slug ] = $feature;
73
74 return true;
75 }
76
77 /**
78 * Easy access function to get a Feature object from a slug
79 *
80 * @param string $slug Feature slug
81 * @since 2.1
82 * @return Feature
83 */
84 public function get_registered_feature( $slug ) {
85 if ( empty( $this->registered_features[ $slug ] ) ) {
86 return false;
87 }
88
89 return $this->registered_features[ $slug ];
90 }
91
92 /**
93 * Activate or deactivate a feature
94 *
95 * @param string $slug Feature slug
96 * @param array $settings Array of settings
97 * @param bool $force Whether to force activate/deactivate
98 * @since 2.2
99 * @return array|bool
100 */
101 public function update_feature( $slug, $settings, $force = true ) {
102 $feature = $this->get_registered_feature( $slug );
103
104 if ( empty( $feature ) ) {
105 return false;
106 }
107
108 $original_state = $feature->is_active();
109
110 $feature_settings = Utils\get_option( 'ep_feature_settings', [] );
111
112 if ( empty( $feature_settings[ $slug ] ) ) {
113 // If doesn't exist, merge with feature defaults
114 $feature_settings[ $slug ] = wp_parse_args( $settings, $feature->default_settings );
115 } else {
116 // If exist just merge changed values into current
117 $feature_settings[ $slug ] = wp_parse_args( $settings, $feature_settings[ $slug ] );
118 }
119
120 // Make sure active is a proper bool
121 $feature_settings[ $slug ]['active'] = (bool) $feature_settings[ $slug ]['active'];
122
123 if ( $feature_settings[ $slug ]['active'] ) {
124 $feature_settings[ $slug ]['force_inactive'] = false;
125 }
126
127 // This means someone has explicitly deactivated the feature
128 if ( $force ) {
129 if ( ! (bool) $settings['active'] && $original_state ) {
130 $feature_settings[ $slug ]['force_inactive'] = true;
131 }
132 }
133
134 $sanitize_feature_settings = apply_filters( 'ep_sanitize_feature_settings', $feature_settings, $feature );
135
136 Utils\update_option( 'ep_feature_settings', $sanitize_feature_settings );
137
138 $data = array(
139 'active' => $sanitize_feature_settings[ $slug ]['active'],
140 'reindex' => false,
141 );
142
143 if ( $feature_settings[ $slug ]['active'] && ! $original_state ) {
144 if ( ! empty( $feature->requires_install_reindex ) ) {
145 $data['reindex'] = true;
146 }
147
148 $feature->post_activation();
149 }
150
151 /**
152 * Fires after activating, inactivating, or just updating a feature.
153 *
154 * @hook ep_after_update_feature
155 * @param {string} $feature Feature slug
156 * @param {array} $settings Feature settings
157 * @param {array} $data Feature activation data
158 *
159 * @since 3.5.5
160 */
161 do_action(
162 'ep_after_update_feature',
163 $slug,
164 $settings,
165 $data
166 );
167
168 return $data;
169 }
170
171 /**
172 * When plugins are adjusted, we need to determine how to activate/deactivate features
173 *
174 * @since 2.2
175 */
176 public function handle_feature_activation() {
177 /**
178 * Save our current requirement statuses for later
179 */
180
181 $old_requirement_statuses = Utils\get_option( 'ep_feature_requirement_statuses', false );
182
183 $new_requirement_statuses = [];
184
185 foreach ( $this->registered_features as $slug => $feature ) {
186 $status = $feature->requirements_status();
187 $new_requirement_statuses[ $slug ] = (int) $status->code;
188 }
189
190 $is_wp_cli = defined( 'WP_CLI' ) && \WP_CLI;
191
192 if ( $is_wp_cli || is_admin() ) {
193 Utils\update_option( 'ep_feature_requirement_statuses', $new_requirement_statuses );
194 }
195
196 /**
197 * If feature settings aren't created, let's create them and finish
198 */
199
200 $feature_settings = Utils\get_option( 'ep_feature_settings', false );
201
202 if ( false === $feature_settings ) {
203 $registered_features = $this->registered_features;
204
205 foreach ( $registered_features as $slug => $feature ) {
206 if ( 0 === $feature->requirements_status()->code ) {
207 $this->activate_feature( $slug );
208 }
209 }
210
211 /**
212 * Nothing else to do since we are doing initial activation
213 */
214 return;
215 }
216
217 /**
218 * If a requirement status changes, we need to handle that by activating/deactivating/showing notification
219 */
220
221 if ( ( $is_wp_cli || is_admin() ) && ! empty( $old_requirement_statuses ) ) {
222 foreach ( $new_requirement_statuses as $slug => $code ) {
223 $feature = $this->get_registered_feature( $slug );
224
225 // If a feature is forced inactive, do nothing
226 $feature_settings = $feature->get_settings();
227 if ( is_array( $feature_settings ) && ! empty( $feature_settings['force_inactive'] ) ) {
228 continue;
229 }
230
231 // This is a new feature
232 if ( ! isset( $old_requirement_statuses[ $slug ] ) ) {
233 if ( 0 === $code ) {
234 $this->activate_feature( $slug );
235
236 if ( $feature->requires_install_reindex ) {
237 Utils\update_option( 'ep_feature_auto_activated_sync', sanitize_text_field( $slug ) );
238 }
239 }
240 } else {
241 // This feature has a 0 "ok" code when it did not before
242 if ( $old_requirement_statuses[ $slug ] !== $code && ( 0 === $code || 2 === $code ) ) {
243 $active = ( 0 === $code );
244
245 if ( ! $feature->is_active() && $active ) {
246 $this->activate_feature( $slug );
247
248 // Need to activate and maybe set a sync notice
249 if ( $feature->requires_install_reindex ) {
250 Utils\update_option( 'ep_feature_auto_activated_sync', sanitize_text_field( $slug ) );
251 }
252 } elseif ( $feature->is_active() && ! $active ) {
253 // Just deactivate, don't force
254 $this->deactivate_feature( $slug, false );
255 }
256 }
257 }
258 }
259 }
260 }
261
262 /**
263 * Set up all active features
264 *
265 * @since 2.1
266 */
267 public function setup_features() {
268 /**
269 * Fires before features are setup
270 *
271 * @hook ep_setup_features
272 * @since 2.1
273 */
274 do_action( 'ep_setup_features' );
275
276 foreach ( $this->registered_features as $feature_slug => $feature ) {
277 if ( $feature->is_active() ) {
278 $feature->setup();
279 }
280 }
281 }
282
283 /**
284 * Return singleton instance of class
285 *
286 * @return object
287 * @since 2.1
288 */
289 public static function factory() {
290 static $instance = false;
291
292 if ( ! $instance ) {
293 $instance = new self();
294 $instance->setup();
295 }
296
297 return $instance;
298 }
299 }
300