PluginProbe
BlockSpare – Gutenberg Blocks, AI Content Generator & Site Builder for News, Magazine & Blogs / 5.0.1
BlockSpare – Gutenberg Blocks, AI Content Generator & Site Builder for News, Magazine & Blogs v5.0.1
5.0.1 4.1.0 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 2.1.2 2.5.0 2.5.3 All 39 releases
← All changes | freemius/includes/class-fs-storage.php +108 -80 1.3.4 → 5.0.1 View file →
@@ -14,11 +14,14 @@
14 14 * Class FS_Storage
15 15 *
16 16 * A wrapper class for handling network level and single site level storage.
17 17 *
18 - * @property bool $is_network_activation
19 - * @property int $network_install_blog_id
20 - * @property object $sync_cron
18 + * @property bool $is_network_activation
19 + * @property int $network_install_blog_id
20 + * @property bool|null $is_extensions_tracking_allowed
21 + * @property bool|null $is_diagnostic_tracking_allowed
22 + * @property object $sync_cron
23 + * @property bool|int $install_timestamp
21 24 */
22 25 class FS_Storage {
23 26 /**
24 27 * @var FS_Storage[]
@@ -71,8 +74,18 @@
71 74 * }
72 75 */
73 76 private static $_NETWORK_OPTIONS_MAP;
74 77
78 + const OPTION_LEVEL_UNDEFINED = -1;
79 + // The option should be stored on the network level.
80 + const OPTION_LEVEL_NETWORK = 0;
81 + // The option should be stored on the network level when the plugin is network-activated.
82 + const OPTION_LEVEL_NETWORK_ACTIVATED = 1;
83 + // The option should be stored on the network level when the plugin is network-activated and the opt-in connection was NOT delegated to the sub-site admin.
84 + const OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED = 2;
85 + // The option should be stored on the site level.
86 + const OPTION_LEVEL_SITE = 3;
87 +
75 88 /**
76 89 * @author Leo Fajardo (@leorw)
77 90 *
78 91 * @param string $module_type
@@ -141,12 +154,19 @@
141 154 *
142 155 * @param string $key
143 156 * @param mixed $value
144 157 * @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::$_BINARY_MAP).
158 + * @param int $option_level Since 2.5.1
145 159 * @param bool $flush
146 160 */
147 - function store( $key, $value, $network_level_or_blog_id = null, $flush = true ) {
148 - if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
161 + function store(
162 + $key,
163 + $value,
164 + $network_level_or_blog_id = null,
165 + $option_level = self::OPTION_LEVEL_UNDEFINED,
166 + $flush = true
167 + ) {
168 + if ( $this->should_use_network_storage( $key, $network_level_or_blog_id, $option_level ) ) {
149 169 $this->_network_storage->store( $key, $value, $flush );
150 170 } else {
151 171 $storage = $this->get_site_storage( $network_level_or_blog_id );
152 172 $storage->store( $key, $value, $flush );
@@ -198,13 +218,19 @@
198 218 *
199 219 * @param string $key
200 220 * @param mixed $default
201 221 * @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::$_BINARY_MAP).
222 + * @param int $option_level Since 2.5.1
202 223 *
203 224 * @return mixed
204 225 */
205 - function get( $key, $default = false, $network_level_or_blog_id = null ) {
206 - if ( $this->should_use_network_storage( $key, $network_level_or_blog_id ) ) {
226 + function get(
227 + $key,
228 + $default = false,
229 + $network_level_or_blog_id = null,
230 + $option_level = self::OPTION_LEVEL_UNDEFINED
231 + ) {
232 + if ( $this->should_use_network_storage( $key, $network_level_or_blog_id, $option_level ) ) {
207 233 return $this->_network_storage->get( $key, $default );
208 234 } else {
209 235 $storage = $this->get_site_storage( $network_level_or_blog_id );
210 236
@@ -288,21 +314,8 @@
288 314 if ( isset( $this->_storage->{$option} ) && ! isset( $this->_network_storage->{$option} ) ) {
289 315 // Migrate option to the network storage.
290 316 $this->_network_storage->store( $option, $this->_storage->{$option}, false );
291 317
292 - /**
293 - * Remove the option from site level storage.
294 - *
295 - * IMPORTANT:
296 - * The line below is intentionally commented since we want to preserve the option
297 - * on the site storage level for "downgrade compatibility". Basically, if the user
298 - * will downgrade to an older version of the plugin with the prev storage structure,
299 - * it will continue working.
300 - *
301 - * @todo After a few releases we can remove this.
302 - */
303 -// $this->_storage->remove($option, false);
304 -
305 318 $updated = true;
306 319 }
307 320 }
308 321
@@ -335,65 +348,64 @@
335 348 */
336 349 private static function load_network_options_map() {
337 350 self::$_NETWORK_OPTIONS_MAP = array(
338 351 // Network level options.
339 - 'affiliate_application_data' => 0,
340 - 'beta_data' => 0,
341 - 'connectivity_test' => 0,
342 - 'handle_gdpr_admin_notice' => 0,
343 - 'has_trial_plan' => 0,
344 - 'install_sync_timestamp' => 0,
345 - 'install_sync_cron' => 0,
346 - 'is_anonymous_ms' => 0,
347 - 'is_network_activated' => 0,
348 - 'is_on' => 0,
349 - 'is_plugin_new_install' => 0,
350 - 'network_install_blog_id' => 0,
351 - 'pending_sites_info' => 0,
352 - 'plugin_last_version' => 0,
353 - 'plugin_main_file' => 0,
354 - 'plugin_version' => 0,
355 - 'sdk_downgrade_mode' => 0,
356 - 'sdk_last_version' => 0,
357 - 'sdk_upgrade_mode' => 0,
358 - 'sdk_version' => 0,
359 - 'sticky_optin_added_ms' => 0,
360 - 'subscriptions' => 0,
361 - 'sync_timestamp' => 0,
362 - 'sync_cron' => 0,
363 - 'was_plugin_loaded' => 0,
364 - 'network_user_id' => 0,
365 - 'plugin_upgrade_mode' => 0,
366 - 'plugin_downgrade_mode' => 0,
367 - 'is_network_connected' => 0,
352 + 'affiliate_application_data' => self::OPTION_LEVEL_NETWORK,
353 + 'beta_data' => self::OPTION_LEVEL_NETWORK,
354 + 'connectivity_test' => self::OPTION_LEVEL_NETWORK,
355 + 'handle_gdpr_admin_notice' => self::OPTION_LEVEL_NETWORK,
356 + 'has_trial_plan' => self::OPTION_LEVEL_NETWORK,
357 + 'install_sync_timestamp' => self::OPTION_LEVEL_NETWORK,
358 + 'install_sync_cron' => self::OPTION_LEVEL_NETWORK,
359 + 'is_anonymous_ms' => self::OPTION_LEVEL_NETWORK,
360 + 'is_network_activated' => self::OPTION_LEVEL_NETWORK,
361 + 'is_on' => self::OPTION_LEVEL_NETWORK,
362 + 'is_plugin_new_install' => self::OPTION_LEVEL_NETWORK,
363 + 'last_load_timestamp' => self::OPTION_LEVEL_NETWORK,
364 + 'network_install_blog_id' => self::OPTION_LEVEL_NETWORK,
365 + 'pending_sites_info' => self::OPTION_LEVEL_NETWORK,
366 + 'plugin_last_version' => self::OPTION_LEVEL_NETWORK,
367 + 'plugin_main_file' => self::OPTION_LEVEL_NETWORK,
368 + 'plugin_version' => self::OPTION_LEVEL_NETWORK,
369 + 'sdk_downgrade_mode' => self::OPTION_LEVEL_NETWORK,
370 + 'sdk_last_version' => self::OPTION_LEVEL_NETWORK,
371 + 'sdk_upgrade_mode' => self::OPTION_LEVEL_NETWORK,
372 + 'sdk_version' => self::OPTION_LEVEL_NETWORK,
373 + 'sticky_optin_added_ms' => self::OPTION_LEVEL_NETWORK,
374 + 'subscriptions' => self::OPTION_LEVEL_NETWORK,
375 + 'sync_timestamp' => self::OPTION_LEVEL_NETWORK,
376 + 'sync_cron' => self::OPTION_LEVEL_NETWORK,
377 + 'was_plugin_loaded' => self::OPTION_LEVEL_NETWORK,
378 + 'network_user_id' => self::OPTION_LEVEL_NETWORK,
379 + 'plugin_upgrade_mode' => self::OPTION_LEVEL_NETWORK,
380 + 'plugin_downgrade_mode' => self::OPTION_LEVEL_NETWORK,
381 + 'is_network_connected' => self::OPTION_LEVEL_NETWORK,
368 382 /**
369 - * Special flag that is used when a super-admin upgrades to the new version of the SDK that
370 - * supports network level integration, when the connection decision wasn't made for all of the
371 - * sites in the network.
383 + * Special flag that is used when a super-admin upgrades to the new version of the SDK that supports network level integration, when the connection decision wasn't made for all the sites in the network.
372 384 */
373 - 'is_network_activation' => 0,
374 - 'license_migration' => 0,
385 + 'is_network_activation' => self::OPTION_LEVEL_NETWORK,
386 + 'license_migration' => self::OPTION_LEVEL_NETWORK,
375 387
376 388 // When network activated, then network level.
377 - 'install_timestamp' => 1,
378 - 'prev_is_premium' => 1,
379 - 'require_license_activation' => 1,
389 + 'install_timestamp' => self::OPTION_LEVEL_NETWORK_ACTIVATED,
390 + 'prev_is_premium' => self::OPTION_LEVEL_NETWORK_ACTIVATED,
391 + 'require_license_activation' => self::OPTION_LEVEL_NETWORK_ACTIVATED,
380 392
381 393 // If not network activated OR delegated, then site level.
382 - 'activation_timestamp' => 2,
383 - 'expired_license_notice_shown' => 2,
384 - 'is_whitelabeled' => 2,
385 - 'last_license_key' => 2,
386 - 'last_license_user_id' => 2,
387 - 'prev_user_id' => 2,
388 - 'sticky_optin_added' => 2,
389 - 'uninstall_reason' => 2,
390 - 'is_pending_activation' => 2,
391 - 'pending_license_key' => 2,
392 - 'is_extensions_tracking_allowed' => 2,
394 + 'activation_timestamp' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
395 + 'expired_license_notice_shown' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
396 + 'is_whitelabeled' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
397 + 'last_license_key' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
398 + 'last_license_user_id' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
399 + 'prev_user_id' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
400 + 'sticky_optin_added' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
401 + 'uninstall_reason' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
402 + 'is_pending_activation' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
403 + 'pending_license_key' => self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED,
393 404
394 405 // Site level options.
395 - 'is_anonymous' => 3,
406 + 'is_anonymous' => self::OPTION_LEVEL_SITE,
407 + 'clone_id' => self::OPTION_LEVEL_SITE,
396 408 );
397 409 }
398 410
399 411 /**
@@ -402,27 +414,35 @@
402 414 * @author Vova Feldman (@svovaf)
403 415 * @since 2.0.0
404 416 *
405 417 * @param string $key
418 + * @param int $option_level Since 2.5.1
406 419 *
407 - * @return bool|mixed
420 + * @return bool
408 421 */
409 - private function is_multisite_option( $key ) {
422 + private function is_multisite_option( $key, $option_level = self::OPTION_LEVEL_UNDEFINED ) {
410 423 if ( ! isset( self::$_NETWORK_OPTIONS_MAP ) ) {
411 424 self::load_network_options_map();
412 425 }
413 426
414 - if ( ! isset( self::$_NETWORK_OPTIONS_MAP[ $key ] ) ) {
427 + if (
428 + self::OPTION_LEVEL_UNDEFINED === $option_level &&
429 + isset( self::$_NETWORK_OPTIONS_MAP[ $key ] )
430 + ) {
431 + $option_level = self::$_NETWORK_OPTIONS_MAP[ $key ];
432 + }
433 +
434 + if ( self::OPTION_LEVEL_UNDEFINED === $option_level ) {
415 435 // Option not found -> use site level storage.
416 436 return false;
417 437 }
418 438
419 - if ( 0 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
439 + if ( self::OPTION_LEVEL_NETWORK === $option_level ) {
420 440 // Option found and set to always use the network level storage on a multisite.
421 441 return true;
422 442 }
423 443
424 - if ( 3 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
444 + if ( self::OPTION_LEVEL_SITE === $option_level ) {
425 445 // Option found and set to always use the site level storage on a multisite.
426 446 return false;
427 447 }
428 448
@@ -429,14 +449,17 @@
429 449 if ( ! $this->_is_network_active ) {
430 450 return false;
431 451 }
432 452
433 - if ( 1 === self::$_NETWORK_OPTIONS_MAP[ $key ] ) {
453 + if ( self::OPTION_LEVEL_NETWORK_ACTIVATED === $option_level ) {
434 454 // Network activated.
435 455 return true;
436 456 }
437 457
438 - if ( 2 === self::$_NETWORK_OPTIONS_MAP[ $key ] && ! $this->_is_delegated_connection ) {
458 + if (
459 + self::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED === $option_level &&
460 + ! $this->_is_delegated_connection
461 + ) {
439 462 // Network activated and not delegated.
440 463 return true;
441 464 }
442 465
@@ -447,12 +470,17 @@
447 470 * @author Leo Fajardo
448 471 *
449 472 * @param string $key
450 473 * @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::$_BINARY_MAP).
474 + * @param int $option_level Since 2.5.1
451 475 *
452 476 * @return bool
453 477 */
454 - private function should_use_network_storage( $key, $network_level_or_blog_id = null ) {
478 + private function should_use_network_storage(
479 + $key,
480 + $network_level_or_blog_id = null,
481 + $option_level = self::OPTION_LEVEL_UNDEFINED
482 + ) {
455 483 if ( ! $this->_is_multisite ) {
456 484 // Not a multisite environment.
457 485 return false;
458 486 }
@@ -462,14 +490,14 @@
462 490 return false;
463 491 }
464 492
465 493 if ( is_bool( $network_level_or_blog_id ) ) {
466 - // Explicitly specified whether should use the network or blog level storage.
494 + // Explicitly specified whether it should use the network or blog level storage.
467 495 return $network_level_or_blog_id;
468 496 }
469 497
470 498 // Determine which storage to use based on the option.
471 - return $this->is_multisite_option( $key );
499 + return $this->is_multisite_option( $key, $option_level );
472 500 }
473 501
474 502 /**
475 503 * @author Vova Feldman (@svovaf)
@@ -528,5 +556,5 @@
528 556 $this->_storage->{$k};
529 557 }
530 558
531 559 #endregion
532 - }
560 + }