PluginProbe ʕ •ᴥ•ʔ
Royal Addons for Elementor – Addons and Templates Kit for Elementor / 1.7.1064
Royal Addons for Elementor – Addons and Templates Kit for Elementor v1.7.1064
1.7.1064 1.7.1063 1.7.1062 1.7.1061 1.7.1060 1.7.1059 1.7.1058 trunk 1.0.0 1.1.0 1.2 1.3 1.3.1 1.3.2 1.3.21 1.3.22 1.3.23 1.3.24 1.3.25 1.3.26 1.3.27 1.3.28 1.3.29 1.3.30 1.3.31 1.3.32 1.3.33 1.3.34 1.3.35 1.3.36 1.3.37 1.3.38 1.3.39 1.3.40 1.3.41 1.3.42 1.3.43 1.3.44 1.3.45 1.3.46 1.3.47 1.3.48 1.3.49 1.3.50 1.3.51 1.3.52 1.3.53 1.3.54 1.3.55 1.3.56 1.3.57 1.3.58 1.3.59 1.3.60 1.3.61 1.3.62 1.3.63 1.3.64 1.3.65 1.3.66 1.3.67 1.3.68 1.3.69 1.3.70 1.3.71 1.3.72 1.3.73 1.3.74 1.3.75 1.3.76 1.3.77 1.3.78 1.3.79 1.3.80 1.3.81 1.3.82 1.3.83 1.3.84 1.3.85 1.3.86 1.3.87 1.3.88 1.3.89 1.3.90 1.3.91 1.3.92 1.3.93 1.3.94 1.3.95 1.3.96 1.3.97 1.3.971 1.3.972 1.3.973 1.3.974 1.3.975 1.3.976 1.3.977 1.3.978 1.3.979 1.3.980 1.3.981 1.3.982 1.3.983 1.3.984 1.3.985 1.3.986 1.3.987 1.7.1 1.7.1001 1.7.1002 1.7.1003 1.7.1004 1.7.1005 1.7.1006 1.7.1007 1.7.1008 1.7.1009 1.7.1010 1.7.1011 1.7.1012 1.7.1013 1.7.1014 1.7.1015 1.7.1016 1.7.1017 1.7.1018 1.7.1019 1.7.1020 1.7.1021 1.7.1022 1.7.1023 1.7.1024 1.7.1025 1.7.1026 1.7.1027 1.7.1028 1.7.1029 1.7.1030 1.7.1031 1.7.1032 1.7.1033 1.7.1034 1.7.1035 1.7.1036 1.7.1037 1.7.1038 1.7.1039 1.7.1040 1.7.1041 1.7.1042 1.7.1043 1.7.1044 1.7.1045 1.7.1046 1.7.1047 1.7.1048 1.7.1049 1.7.1050 1.7.1051 1.7.1052 1.7.1053 1.7.1054 1.7.1055 1.7.1056 1.7.1057
royal-elementor-addons / freemius / includes / class-fs-options.php
royal-elementor-addons / freemius / includes Last commit date
customizer 5 days ago debug 5 days ago entities 5 days ago managers 5 days ago sdk 5 days ago supplements 5 days ago class-freemius-abstract.php 5 days ago class-freemius.php 5 days ago class-fs-admin-notices.php 5 days ago class-fs-api.php 5 days ago class-fs-garbage-collector.php 5 days ago class-fs-lock.php 5 days ago class-fs-logger.php 5 days ago class-fs-options.php 5 days ago class-fs-plugin-updater.php 5 days ago class-fs-security.php 5 days ago class-fs-storage.php 5 days ago class-fs-user-lock.php 5 days ago fs-core-functions.php 5 days ago fs-essential-functions.php 5 days ago fs-html-escaping-functions.php 5 days ago fs-plugin-info-dialog.php 5 days ago index.php 5 days ago l10n.php 5 days ago
class-fs-options.php
431 lines
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.2.3
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Class FS_Options
15 *
16 * A wrapper class for handling network level and single site level options.
17 */
18 class FS_Options {
19 /**
20 * @var string
21 */
22 private $_id;
23
24 /**
25 * @var array[string]FS_Options {
26 * @key string
27 * @value FS_Options
28 * }
29 */
30 private static $_instances;
31
32 /**
33 * @var FS_Option_Manager Site level options.
34 */
35 private $_options;
36
37 /**
38 * @var FS_Option_Manager Network level options.
39 */
40 private $_network_options;
41
42 /**
43 * @var int The ID of the blog that is associated with the current site level options.
44 */
45 private $_blog_id = 0;
46
47 /**
48 * @var bool
49 */
50 private $_is_multisite;
51
52 /**
53 * @var string[] Lazy collection of params on the site level.
54 */
55 private static $_SITE_OPTIONS_MAP;
56
57 /**
58 * @author Leo Fajardo (@leorw)
59 * @since 2.0.0
60 *
61 * @param string $id
62 * @param bool $load
63 *
64 * @return FS_Options
65 */
66 static function instance( $id, $load = false ) {
67 if ( ! isset( self::$_instances[ $id ] ) ) {
68 self::$_instances[ $id ] = new FS_Options( $id, $load );
69 }
70
71 return self::$_instances[ $id ];
72 }
73
74 /**
75 * @author Leo Fajardo (@leorw)
76 * @since 2.0.0
77 *
78 * @param string $id
79 * @param bool $load
80 */
81 private function __construct( $id, $load = false ) {
82 $this->_id = $id;
83 $this->_is_multisite = is_multisite();
84
85 if ( $this->_is_multisite ) {
86 $this->_blog_id = get_current_blog_id();
87 $this->_network_options = FS_Option_Manager::get_manager( $id, $load, true );
88 }
89
90 $this->_options = FS_Option_Manager::get_manager( $id, $load, $this->_blog_id );
91 }
92
93 /**
94 * Switch the context of the site level options manager.
95 *
96 * @author Vova Feldman (@svovaf)
97 * @since 2.0.0
98 *
99 * @param $blog_id
100 */
101 function set_site_blog_context( $blog_id ) {
102 $this->_blog_id = $blog_id;
103
104 $this->_options = FS_Option_Manager::get_manager( $this->_id, false, $this->_blog_id );
105 }
106
107 /**
108 * @author Leo Fajardo (@leorw)
109 *
110 * @param string $option
111 * @param mixed $default
112 * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
113 *
114 * @return mixed
115 */
116 function get_option( $option, $default = null, $network_level_or_blog_id = null ) {
117 if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
118 return $this->_network_options->get_option( $option, $default );
119 }
120
121 $site_options = $this->get_site_options( $network_level_or_blog_id );
122
123 return $site_options->get_option( $option, $default );
124 }
125
126 /**
127 * @author Leo Fajardo (@leorw)
128 * @since 2.0.0
129 *
130 * @param string $option
131 * @param mixed $value
132 * @param bool $flush
133 * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
134 */
135 function set_option( $option, $value, $flush = false, $network_level_or_blog_id = null ) {
136 if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
137 $this->_network_options->set_option( $option, $value, $flush );
138 } else {
139 $site_options = $this->get_site_options( $network_level_or_blog_id );
140 $site_options->set_option( $option, $value, $flush );
141 }
142 }
143
144 /**
145 * @author Vova Feldman (@svovaf)
146 * @since 2.0.0
147 *
148 * @param string $option
149 * @param bool $flush
150 * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
151 */
152 function unset_option( $option, $flush = false, $network_level_or_blog_id = null ) {
153 if ( $this->should_use_network_storage( $option, $network_level_or_blog_id ) ) {
154 $this->_network_options->unset_option( $option, $flush );
155 } else {
156 $site_options = $this->get_site_options( $network_level_or_blog_id );
157 $site_options->unset_option( $option, $flush );
158 }
159 }
160
161 /**
162 * @author Leo Fajardo (@leorw)
163 * @since 2.0.0
164 *
165 * @param bool $flush
166 * @param bool $network_level
167 */
168 function load( $flush = false, $network_level = true ) {
169 if ( $this->_is_multisite && $network_level ) {
170 $this->_network_options->load( $flush );
171 } else {
172 $this->_options->load( $flush );
173 }
174 }
175
176 /**
177 * @author Leo Fajardo (@leorw)
178 * @since 2.0.0
179 *
180 * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, store both network storage and the current context blog storage.
181 */
182 function store( $network_level_or_blog_id = null ) {
183 if ( ! $this->_is_multisite ||
184 false === $network_level_or_blog_id ||
185 0 == $network_level_or_blog_id ||
186 is_null( $network_level_or_blog_id )
187 ) {
188 $site_options = $this->get_site_options( $network_level_or_blog_id );
189 $site_options->store();
190 }
191
192 if ( $this->_is_multisite &&
193 ( is_null( $network_level_or_blog_id ) || true === $network_level_or_blog_id )
194 ) {
195 $this->_network_options->store();
196 }
197 }
198
199 /**
200 * @author Vova Feldman (@svovaf)
201 * @since 2.0.0
202 *
203 * @param int|null|bool $network_level_or_blog_id
204 * @param bool $flush
205 */
206 function clear( $network_level_or_blog_id = null, $flush = false ) {
207 if ( ! $this->_is_multisite ||
208 false === $network_level_or_blog_id ||
209 is_null( $network_level_or_blog_id ) ||
210 is_numeric( $network_level_or_blog_id )
211 ) {
212 $site_options = $this->get_site_options( $network_level_or_blog_id );
213 $site_options->clear( $flush );
214 }
215
216 if ( $this->_is_multisite &&
217 ( true === $network_level_or_blog_id || is_null( $network_level_or_blog_id ) )
218 ) {
219 $this->_network_options->clear( $flush );
220 }
221 }
222
223 /**
224 * Migration script to the new storage data structure that is network compatible.
225 *
226 * IMPORTANT:
227 * This method should be executed only after it is determined if this is a network
228 * level compatible product activation.
229 *
230 * @author Vova Feldman (@svovaf)
231 * @since 2.0.0
232 *
233 * @param int $blog_id
234 */
235 function migrate_to_network( $blog_id = 0 ) {
236 if ( ! $this->_is_multisite ) {
237 return;
238 }
239
240 $updated = false;
241
242 $site_options = $this->get_site_options( $blog_id );
243
244 $keys = $site_options->get_options_keys();
245
246 foreach ( $keys as $option ) {
247 if ( $this->is_site_option( $option ) ||
248 // Don't move admin notices to the network storage.
249 in_array($option, array(
250 // Don't move admin notices to the network storage.
251 'admin_notices',
252 // Don't migrate the module specific data, it will be migrated by the FS_Storage.
253 'plugin_data',
254 'theme_data',
255 ))
256 ) {
257 continue;
258 }
259
260 $option_updated = false;
261
262 // Migrate option to the network storage.
263 $site_option = $site_options->get_option( $option );
264
265 if ( ! $this->_network_options->has_option( $option ) ) {
266 // Option not set on the network level, so just set it.
267 $this->_network_options->set_option( $option, $site_option, false );
268
269 $option_updated = true;
270 } else {
271 // Option already set on the network level, so we need to merge it inelegantly.
272 $network_option = $this->_network_options->get_option( $option );
273
274 if ( is_array( $network_option ) && is_array( $site_option ) ) {
275 // Option is an array.
276 foreach ( $site_option as $key => $value ) {
277 if ( ! isset( $network_option[ $key ] ) ) {
278 $network_option[ $key ] = $value;
279
280 $option_updated = true;
281 } else if ( is_array( $network_option[ $key ] ) && is_array( $value ) ) {
282 if ( empty( $network_option[ $key ] ) ) {
283 $network_option[ $key ] = $value;
284
285 $option_updated = true;
286 } else if ( empty( $value ) ) {
287 // Do nothing.
288 } else {
289 reset($value);
290 $first_key = key($value);
291 if ( $value[$first_key] instanceof FS_Entity ) {
292 // Merge entities by IDs.
293 $network_entities_ids = array();
294 foreach ( $network_option[ $key ] as $entity ) {
295 $network_entities_ids[ $entity->id ] = true;
296 }
297
298 foreach ( $value as $entity ) {
299 if ( ! isset( $network_entities_ids[ $entity->id ] ) ) {
300 $network_option[ $key ][] = $entity;
301
302 $option_updated = true;
303 }
304 }
305 }
306 }
307 }
308 }
309 }
310
311 if ( $option_updated ) {
312 $this->_network_options->set_option( $option, $network_option, false );
313 }
314 }
315
316 /**
317 * Remove the option from site level storage.
318 *
319 * IMPORTANT:
320 * The line below is intentionally commented since we want to preserve the option
321 * on the site storage level for "downgrade compatibility". Basically, if the user
322 * will downgrade to an older version of the plugin with the prev storage structure,
323 * it will continue working.
324 *
325 * @todo After a few releases we can remove this.
326 */
327 // $site_options->unset_option($option, false);
328
329 if ( $option_updated ) {
330 $updated = true;
331 }
332 }
333
334 if ( ! $updated ) {
335 return;
336 }
337
338 // Update network level storage.
339 $this->_network_options->store();
340 // $site_options->store();
341 }
342
343
344 #--------------------------------------------------------------------------------
345 #region Helper Methods
346 #--------------------------------------------------------------------------------
347
348 /**
349 * We don't want to load the map right away since it's not even needed in a non-MS environment.
350 *
351 * @author Vova Feldman (@svovaf)
352 * @since 2.0.0
353 */
354 private static function load_site_options_map() {
355 self::$_SITE_OPTIONS_MAP = array(
356 'sites' => true,
357 'theme_sites' => true,
358 'unique_id' => true,
359 'active_plugins' => true,
360 );
361 }
362
363 /**
364 * @author Vova Feldman (@svovaf)
365 * @since 2.0.0
366 *
367 * @param string $option
368 *
369 * @return bool
370 */
371 private function is_site_option( $option ) {
372 if ( WP_FS__ACCOUNTS_OPTION_NAME != $this->_id ) {
373 return false;
374 }
375
376 if ( ! isset( self::$_SITE_OPTIONS_MAP ) ) {
377 self::load_site_options_map();
378 }
379
380 return isset( self::$_SITE_OPTIONS_MAP[ $option ] );
381 }
382
383 /**
384 * @author Vova Feldman (@svovaf)
385 * @since 2.0.0
386 *
387 * @param int $blog_id
388 *
389 * @return FS_Option_Manager
390 */
391 private function get_site_options( $blog_id = 0 ) {
392 if ( 0 == $blog_id || $blog_id == $this->_blog_id ) {
393 return $this->_options;
394 }
395
396 return FS_Option_Manager::get_manager( $this->_id, true, $blog_id );
397 }
398
399 /**
400 * Check if an option should be stored on the MS network storage.
401 *
402 * @author Vova Feldman (@svovaf)
403 * @since 2.0.0
404 *
405 * @param string $option
406 * @param null|bool|int $network_level_or_blog_id When an integer, use the given blog storage. When `true` use the multisite storage (if there's a network). When `false`, use the current context blog storage. When `null`, the decision which storage to use (MS vs. Current S) will be handled internally and determined based on the $option (based on self::$_SITE_LEVEL_PARAMS).
407 *
408 * @return bool
409 */
410 private function should_use_network_storage( $option, $network_level_or_blog_id = null ) {
411 if ( ! $this->_is_multisite ) {
412 // Not a multisite environment.
413 return false;
414 }
415
416 if ( is_numeric( $network_level_or_blog_id ) ) {
417 // Explicitly asked to use a specified blog storage.
418 return false;
419 }
420
421 if ( is_bool( $network_level_or_blog_id ) ) {
422 // Explicitly specified whether should use the network or blog level storage.
423 return $network_level_or_blog_id;
424 }
425
426 // Determine which storage to use based on the option.
427 return ! $this->is_site_option( $option );
428 }
429
430 #endregion
431 }