Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,532 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.0.7
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class FS_Admin_Notice_Manager {
/**
* @since 1.2.2
*
* @var string
*/
protected $_module_unique_affix;
/**
* @var string
*/
protected $_id;
/**
* @var string
*/
protected $_title;
/**
* @var array[string]array
*/
private $_notices = array();
/**
* @var FS_Key_Value_Storage
*/
private $_sticky_storage;
/**
* @var FS_Logger
*/
protected $_logger;
/**
* @since 2.0.0
* @var int The ID of the blog that is associated with the current site level admin notices.
*/
private $_blog_id = 0;
/**
* @since 2.0.0
* @var bool
*/
private $_is_network_notices;
/**
* @var FS_Admin_Notice_Manager[]
*/
private static $_instances = array();
/**
* @param string $id
* @param string $title
* @param string $module_unique_affix
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on
* network and blog admin pages.
* @param bool $network_level_or_blog_id Since 2.0.0
*
* @return \FS_Admin_Notice_Manager
*/
static function instance(
$id,
$title = '',
$module_unique_affix = '',
$is_network_and_blog_admins = false,
$network_level_or_blog_id = false
) {
if ( $is_network_and_blog_admins ) {
$network_level_or_blog_id = true;
}
$key = strtolower( $id );
if ( is_multisite() ) {
if ( true === $network_level_or_blog_id ) {
$key .= ':ms';
} else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) {
$key .= ":{$network_level_or_blog_id}";
} else {
$network_level_or_blog_id = get_current_blog_id();
$key .= ":{$network_level_or_blog_id}";
}
}
if ( ! isset( self::$_instances[ $key ] ) ) {
self::$_instances[ $key ] = new FS_Admin_Notice_Manager(
$id,
$title,
$module_unique_affix,
$is_network_and_blog_admins,
$network_level_or_blog_id
);
}
return self::$_instances[ $key ];
}
/**
* @param string $id
* @param string $title
* @param string $module_unique_affix
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network and
* blog admin pages.
* @param bool|int $network_level_or_blog_id
*/
protected function __construct(
$id,
$title = '',
$module_unique_affix = '',
$is_network_and_blog_admins = false,
$network_level_or_blog_id = false
) {
$this->_id = $id;
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $this->_id . '_data', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
$this->_title = ! empty( $title ) ? $title : '';
$this->_module_unique_affix = $module_unique_affix;
$this->_sticky_storage = FS_Key_Value_Storage::instance( 'admin_notices', $this->_id, $network_level_or_blog_id );
if ( is_multisite() ) {
$this->_is_network_notices = ( true === $network_level_or_blog_id );
if ( is_numeric( $network_level_or_blog_id ) ) {
$this->_blog_id = $network_level_or_blog_id;
}
} else {
$this->_is_network_notices = false;
}
$is_network_admin = fs_is_network_admin();
$is_blog_admin = fs_is_blog_admin();
if ( ( $this->_is_network_notices && $is_network_admin ) ||
( ! $this->_is_network_notices && $is_blog_admin ) ||
( $is_network_and_blog_admins && ( $is_network_admin || $is_blog_admin ) )
) {
if ( 0 < count( $this->_sticky_storage ) ) {
$ajax_action_suffix = str_replace( ':', '-', $this->_id );
// If there are sticky notices for the current slug, add a callback
// to the AJAX action that handles message dismiss.
add_action( "wp_ajax_fs_dismiss_notice_action_{$ajax_action_suffix}", array(
&$this,
'dismiss_notice_ajax_callback'
) );
foreach ( $this->_sticky_storage as $msg ) {
// Add admin notice.
$this->add(
$msg['message'],
$msg['title'],
$msg['type'],
true,
$msg['id'],
false,
isset( $msg['wp_user_id'] ) ? $msg['wp_user_id'] : null,
! empty( $msg['plugin'] ) ? $msg['plugin'] : null,
$is_network_and_blog_admins,
isset( $msg['dismissible'] ) ?
$msg['dismissible'] :
null
);
}
}
}
}
/**
* Remove sticky message by ID.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
*/
function dismiss_notice_ajax_callback() {
check_admin_referer( 'fs_dismiss_notice_action' );
if ( ! is_numeric( $_POST['message_id'] ) ) {
$this->_sticky_storage->remove( $_POST['message_id'] );
}
wp_die();
}
/**
* Rendered sticky message dismiss JavaScript.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*/
static function _add_sticky_dismiss_javascript() {
$params = array();
fs_require_once_template( 'sticky-admin-notice-js.php', $params );
}
private static $_added_sticky_javascript = false;
/**
* Hook to the admin_footer to add sticky message dismiss JavaScript handler.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*/
private static function has_sticky_messages() {
if ( ! self::$_added_sticky_javascript ) {
add_action( 'admin_footer', array( 'FS_Admin_Notice_Manager', '_add_sticky_dismiss_javascript' ) );
}
}
/**
* Handle admin_notices by printing the admin messages stacked in the queue.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.4
*
*/
function _admin_notices_hook() {
if ( function_exists( 'current_user_can' ) &&
! current_user_can( 'manage_options' )
) {
// Only show messages to admins.
return;
}
foreach ( $this->_notices as $id => $msg ) {
if ( isset( $msg['wp_user_id'] ) && is_numeric( $msg['wp_user_id'] ) ) {
if ( get_current_user_id() != $msg['wp_user_id'] ) {
continue;
}
}
/**
* Added a filter to control the visibility of admin notices.
*
* Usage example:
*
* /**
* * @param bool $show
* * @param array $msg {
* * @var string $message The actual message.
* * @var string $title An optional message title.
* * @var string $type The type of the message ('success', 'update', 'warning', 'promotion').
* * @var string $id The unique identifier of the message.
* * @var string $manager_id The unique identifier of the notices manager. For plugins it would be the plugin's slug, for themes - `<slug>-theme`.
* * @var string $plugin The product's title.
* * @var string $wp_user_id An optional WP user ID that this admin notice is for.
* * }
* *
* * @return bool
* *\/
* function my_custom_show_admin_notice( $show, $msg ) {
* if ('trial_promotion' != $msg['id']) {
* return false;
* }
*
* return $show;
* }
*
* my_fs()->add_filter( 'show_admin_notice', 'my_custom_show_admin_notice', 10, 2 );
*
* @author Vova Feldman
* @since 2.2.0
*/
$show_notice = call_user_func_array( 'fs_apply_filter', array(
$this->_module_unique_affix,
'show_admin_notice',
$this->show_admin_notices(),
$msg
) );
if ( true !== $show_notice ) {
continue;
}
fs_require_template( 'admin-notice.php', $msg );
if ( $msg['sticky'] ) {
self::has_sticky_messages();
}
}
}
/**
* Enqueue common stylesheet to style admin notice.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*/
function _enqueue_styles() {
fs_enqueue_local_style( 'fs_common', '/admin/common.css' );
}
/**
* Check if the current page is the Gutenberg block editor.
*
* @author Vova Feldman (@svovaf)
* @since 2.2.3
*
* @return bool
*/
function is_gutenberg_page() {
if ( function_exists( 'is_gutenberg_page' ) &&
is_gutenberg_page()
) {
// The Gutenberg plugin is on.
return true;
}
$current_screen = get_current_screen();
if ( method_exists( $current_screen, 'is_block_editor' ) &&
$current_screen->is_block_editor()
) {
// Gutenberg page on 5+.
return true;
}
return false;
}
/**
* Check if admin notices should be shown on page. E.g., we don't want to show notices in the Visual Editor.
*
* @author Xiaheng Chen (@xhchen)
* @since 2.4.2
*
* @return bool
*/
function show_admin_notices() {
global $pagenow;
if ( 'about.php' === $pagenow ) {
// Don't show admin notices on the About page.
return false;
}
if ( $this->is_gutenberg_page() ) {
// Don't show admin notices in Gutenberg (visual editor).
return false;
}
return true;
}
/**
* Add admin message to admin messages queue, and hook to admin_notices / all_admin_notices if not yet hooked.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.4
*
* @param string $message
* @param string $title
* @param string $type
* @param bool $is_sticky
* @param string $id Message ID
* @param bool $store_if_sticky
* @param number|null $wp_user_id
* @param string|null $plugin_title
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
* and blog admin pages.
* @param bool|null $is_dismissible
* @param array $data
*
* @uses add_action()
*/
function add(
$message,
$title = '',
$type = 'success',
$is_sticky = false,
$id = '',
$store_if_sticky = true,
$wp_user_id = null,
$plugin_title = null,
$is_network_and_blog_admins = false,
$is_dismissible = null,
$data = array()
) {
$notices_type = $this->get_notices_type();
if ( empty( $this->_notices ) ) {
if ( ! $is_network_and_blog_admins ) {
add_action( $notices_type, array( &$this, "_admin_notices_hook" ) );
} else {
add_action( 'network_admin_notices', array( &$this, "_admin_notices_hook" ) );
add_action( 'admin_notices', array( &$this, "_admin_notices_hook" ) );
}
add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_styles' ) );
}
if ( '' === $id ) {
$id = md5( $title . ' ' . $message . ' ' . $type );
}
$message_object = array(
'message' => $message,
'title' => $title,
'type' => $type,
'sticky' => $is_sticky,
'id' => $id,
'manager_id' => $this->_id,
'plugin' => ( ! is_null( $plugin_title ) ? $plugin_title : $this->_title ),
'wp_user_id' => $wp_user_id,
'dismissible' => $is_dismissible,
'data' => $data
);
if ( $is_sticky && $store_if_sticky ) {
$this->_sticky_storage->{$id} = $message_object;
}
$this->_notices[ $id ] = $message_object;
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param string|string[] $ids
* @param bool $store
*/
function remove_sticky( $ids, $store = true ) {
if ( ! is_array( $ids ) ) {
$ids = array( $ids );
}
foreach ( $ids as $id ) {
// Remove from sticky storage.
$this->_sticky_storage->remove( $id, $store );
if ( isset( $this->_notices[ $id ] ) ) {
unset( $this->_notices[ $id ] );
}
}
}
/**
* Check if sticky message exists by id.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.9
*
* @param $id
*
* @return bool
*/
function has_sticky( $id ) {
return isset( $this->_sticky_storage[ $id ] );
}
/**
* Adds sticky admin notification.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param string $message
* @param string $id Message ID
* @param string $title
* @param string $type
* @param number|null $wp_user_id
* @param string|null $plugin_title
* @param bool $is_network_and_blog_admins Whether or not the message should be shown both on network
* and blog admin pages.
* @param bool $is_dimissible
* @param array $data
*/
function add_sticky( $message, $id, $title = '', $type = 'success', $wp_user_id = null, $plugin_title = null, $is_network_and_blog_admins = false, $is_dimissible = true, $data = array() ) {
if ( ! empty( $this->_module_unique_affix ) ) {
$message = fs_apply_filter( $this->_module_unique_affix, "sticky_message_{$id}", $message );
$title = fs_apply_filter( $this->_module_unique_affix, "sticky_title_{$id}", $title );
}
$this->add( $message, $title, $type, true, $id, true, $wp_user_id, $plugin_title, $is_network_and_blog_admins, $is_dimissible, $data );
}
/**
* Retrieves the data of an sticky notice.
*
* @author Leo Fajardo (@leorw)
* @since 2.4.3
*
* @param string $id Message ID.
*
* @return array|null
*/
function get_sticky( $id ) {
return isset( $this->_sticky_storage->{$id} ) ?
$this->_sticky_storage->{$id} :
null;
}
/**
* Clear all sticky messages.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.8
*
* @param bool $is_temporary @since 2.5.1
*/
function clear_all_sticky( $is_temporary = false ) {
if ( $is_temporary ) {
$this->_notices = array();
} else {
$this->_sticky_storage->clear_all();
}
}
#--------------------------------------------------------------------------------
#region Helper Method
#--------------------------------------------------------------------------------
/**
* @author Vova Feldman (@svovaf)
* @since 2.0.0
*
* @return string
*/
private function get_notices_type() {
return $this->_is_network_notices ?
'network_admin_notices' :
'admin_notices';
}
#endregion
}

View File

@@ -0,0 +1,326 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.1.6
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class FS_Cache_Manager {
/**
* @var FS_Option_Manager
*/
private $_options;
/**
* @var FS_Logger
*/
private $_logger;
/**
* @var FS_Cache_Manager[]
*/
private static $_MANAGERS = array();
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.3
*
* @param string $id
*/
private function __construct( $id ) {
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_cach_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
$this->_logger->entrance();
$this->_logger->log( 'id = ' . $id );
$this->_options = FS_Option_Manager::get_manager( $id, true, true, false );
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param $id
*
* @return FS_Cache_Manager
*/
static function get_manager( $id ) {
$id = strtolower( $id );
if ( ! isset( self::$_MANAGERS[ $id ] ) ) {
self::$_MANAGERS[ $id ] = new FS_Cache_Manager( $id );
}
return self::$_MANAGERS[ $id ];
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @return bool
*/
function is_empty() {
$this->_logger->entrance();
return $this->_options->is_empty();
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*/
function clear() {
$this->_logger->entrance();
$this->_options->clear( true );
}
/**
* Delete cache manager from DB.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.9
*/
function delete() {
$this->_options->delete();
}
/**
* Check if there's a cached item.
*
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param string $key
*
* @return bool
*/
function has( $key ) {
$cache_entry = $this->_options->get_option( $key, false );
return ( is_object( $cache_entry ) &&
isset( $cache_entry->timestamp ) &&
is_numeric( $cache_entry->timestamp )
);
}
/**
* Check if there's a valid cached item.
*
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param string $key
* @param null|int $expiration Since 1.2.2.7
*
* @return bool
*/
function has_valid( $key, $expiration = null ) {
$cache_entry = $this->_options->get_option( $key, false );
$is_valid = ( is_object( $cache_entry ) &&
isset( $cache_entry->timestamp ) &&
is_numeric( $cache_entry->timestamp ) &&
$cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
);
if ( $is_valid &&
is_numeric( $expiration ) &&
isset( $cache_entry->created ) &&
is_numeric( $cache_entry->created ) &&
$cache_entry->created + $expiration < WP_FS__SCRIPT_START_TIME
) {
/**
* Even if the cache is still valid, since we are checking for validity
* with an explicit expiration period, if the period has past, return
* `false` as if the cache is invalid.
*
* @since 1.2.2.7
*/
$is_valid = false;
}
return $is_valid;
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param string $key
* @param mixed $default
*
* @return mixed
*/
function get( $key, $default = null ) {
$this->_logger->entrance( 'key = ' . $key );
$cache_entry = $this->_options->get_option( $key, false );
if ( is_object( $cache_entry ) &&
isset( $cache_entry->timestamp ) &&
is_numeric( $cache_entry->timestamp )
) {
return $cache_entry->result;
}
return is_object( $default ) ? clone $default : $default;
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param string $key
* @param mixed $default
*
* @return mixed
*/
function get_valid( $key, $default = null ) {
$this->_logger->entrance( 'key = ' . $key );
$cache_entry = $this->_options->get_option( $key, false );
if ( is_object( $cache_entry ) &&
isset( $cache_entry->timestamp ) &&
is_numeric( $cache_entry->timestamp ) &&
$cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
) {
return $cache_entry->result;
}
return is_object( $default ) ? clone $default : $default;
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param string $key
* @param mixed $value
* @param int $expiration
* @param int $created Since 2.0.0 Cache creation date.
*/
function set( $key, $value, $expiration = WP_FS__TIME_24_HOURS_IN_SEC, $created = WP_FS__SCRIPT_START_TIME ) {
$this->_logger->entrance( 'key = ' . $key );
$cache_entry = new stdClass();
$cache_entry->result = $value;
$cache_entry->created = $created;
$cache_entry->timestamp = $created + $expiration;
$this->_options->set_option( $key, $cache_entry, true );
}
/**
* Get cached record expiration, or false if not cached or expired.
*
* @author Vova Feldman (@svovaf)
* @since 1.1.7.3
*
* @param string $key
*
* @return bool|int
*/
function get_record_expiration( $key ) {
$this->_logger->entrance( 'key = ' . $key );
$cache_entry = $this->_options->get_option( $key, false );
if ( is_object( $cache_entry ) &&
isset( $cache_entry->timestamp ) &&
is_numeric( $cache_entry->timestamp ) &&
$cache_entry->timestamp > WP_FS__SCRIPT_START_TIME
) {
return $cache_entry->timestamp;
}
return false;
}
/**
* Purge cached item.
*
* @author Vova Feldman (@svovaf)
* @since 1.1.6
*
* @param string $key
*/
function purge( $key ) {
$this->_logger->entrance( 'key = ' . $key );
$this->_options->unset_option( $key, true );
}
/**
* Extend cached item caching period.
*
* @author Vova Feldman (@svovaf)
* @since 2.0.0
*
* @param string $key
* @param int $expiration
*
* @return bool
*/
function update_expiration( $key, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) {
$this->_logger->entrance( 'key = ' . $key );
$cache_entry = $this->_options->get_option( $key, false );
if ( ! is_object( $cache_entry ) ||
! isset( $cache_entry->timestamp ) ||
! is_numeric( $cache_entry->timestamp )
) {
return false;
}
$this->set( $key, $cache_entry->result, $expiration, $cache_entry->created );
return true;
}
/**
* Set cached item as expired.
*
* @author Vova Feldman (@svovaf)
* @since 1.2.2.7
*
* @param string $key
*/
function expire( $key ) {
$this->_logger->entrance( 'key = ' . $key );
$cache_entry = $this->_options->get_option( $key, false );
if ( is_object( $cache_entry ) &&
isset( $cache_entry->timestamp ) &&
is_numeric( $cache_entry->timestamp )
) {
// Set to expired.
$cache_entry->timestamp = WP_FS__SCRIPT_START_TIME;
$this->_options->set_option( $key, $cache_entry, true );
}
}
#--------------------------------------------------------------------------------
#region Migration
#--------------------------------------------------------------------------------
/**
* Migrate options from site level.
*
* @author Vova Feldman (@svovaf)
* @since 2.0.0
*/
function migrate_to_network() {
$this->_options->migrate_to_network();
}
#endregion
}

View File

@@ -0,0 +1,190 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 2.1.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class FS_GDPR_Manager {
/**
* @var FS_Option_Manager
*/
private $_storage;
/**
* @var array {
* @type bool $required Are GDPR rules apply on the current context admin.
* @type bool $show_opt_in_notice Should the marketing and offers opt-in message be shown to the admin or not. If not set, defaults to `true`.
* @type int $notice_shown_at Last time the special GDPR opt-in message was shown to the current admin.
* }
*/
private $_data;
/**
* @var int
*/
private $_wp_user_id;
/**
* @var string
*/
private $_option_name;
/**
* @var FS_Admin_Notices
*/
private $_notices;
#--------------------------------------------------------------------------------
#region Singleton
#--------------------------------------------------------------------------------
/**
* @var FS_GDPR_Manager
*/
private static $_instance;
/**
* @return FS_GDPR_Manager
*/
public static function instance() {
if ( ! isset( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
#endregion
private function __construct() {
$this->_storage = FS_Option_Manager::get_manager( WP_FS__GDPR_OPTION_NAME, true, true );
$this->_wp_user_id = Freemius::get_current_wp_user_id();
$this->_option_name = "u{$this->_wp_user_id}";
$this->_data = $this->_storage->get_option( $this->_option_name, array() );
$this->_notices = FS_Admin_Notices::instance( 'all_admins', '', '', true );
if ( ! is_array( $this->_data ) ) {
$this->_data = array();
}
}
/**
* Update a GDPR option for the current admin and store it.
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*
* @param string $name
* @param mixed $value
*/
private function update_option( $name, $value ) {
$this->_data[ $name ] = $value;
$this->_storage->set_option( $this->_option_name, $this->_data, true );
}
/**
* @author Leo Fajardo (@leorw)
* @since 2.1.0
*
* @param bool $is_required
*/
public function store_is_required( $is_required ) {
$this->update_option( 'required', $is_required );
}
/**
* Checks if the GDPR opt-in sticky notice is currently shown.
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*
* @return bool
*/
public function is_opt_in_notice_shown() {
return $this->_notices->has_sticky( "gdpr_optin_actions_{$this->_wp_user_id}", true );
}
/**
* Remove the GDPR opt-in sticky notice.
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*/
public function remove_opt_in_notice() {
$this->_notices->remove_sticky( "gdpr_optin_actions_{$this->_wp_user_id}", true );
$this->disable_opt_in_notice();
}
/**
* Prevents the opt-in message from being added/shown.
*
* @author Leo Fajardo (@leorw)
* @since 2.1.0
*/
public function disable_opt_in_notice() {
$this->update_option( 'show_opt_in_notice', false );
}
/**
* Checks if a GDPR opt-in message needs to be shown to the current admin.
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*
* @return bool
*/
public function should_show_opt_in_notice() {
return (
! isset( $this->_data['show_opt_in_notice'] ) ||
true === $this->_data['show_opt_in_notice']
);
}
/**
* Get the last time the GDPR opt-in notice was shown.
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*
* @return false|int
*/
public function last_time_notice_was_shown() {
return isset( $this->_data['notice_shown_at'] ) ?
$this->_data['notice_shown_at'] :
false;
}
/**
* Update the timestamp of the last time the GDPR opt-in message was shown to now.
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*/
public function notice_was_just_shown() {
$this->update_option( 'notice_shown_at', WP_FS__SCRIPT_START_TIME );
}
/**
* @param string $message
* @param string|null $plugin_title
*
* @author Vova Feldman (@svovaf)
* @since 2.1.0
*/
public function add_opt_in_sticky_notice( $message, $plugin_title = null ) {
$this->_notices->add_sticky(
$message,
"gdpr_optin_actions_{$this->_wp_user_id}",
'',
'promotion',
true,
$this->_wp_user_id,
$plugin_title,
true
);
}
}

View File

@@ -0,0 +1,402 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.0.7
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class FS_Key_Value_Storage
*
* @property int $install_timestamp
* @property int $activation_timestamp
* @property int $sync_timestamp
* @property object $sync_cron
* @property int $install_sync_timestamp
* @property array $connectivity_test
* @property array $is_on
* @property object $trial_plan
* @property bool $has_trial_plan
* @property bool $trial_promotion_shown
* @property string $sdk_version
* @property string $sdk_last_version
* @property bool $sdk_upgrade_mode
* @property bool $sdk_downgrade_mode
* @property bool $plugin_upgrade_mode
* @property bool $plugin_downgrade_mode
* @property string $plugin_version
* @property string $plugin_last_version
* @property bool $is_plugin_new_install
* @property bool $was_plugin_loaded
* @property object $plugin_main_file
* @property bool $prev_is_premium
* @property array $is_anonymous
* @property bool $is_pending_activation
* @property bool $sticky_optin_added
* @property object $uninstall_reason
* @property object $subscription
*/
class FS_Key_Value_Storage implements ArrayAccess, Iterator, Countable {
/**
* @var string
*/
protected $_id;
/**
* @since 1.2.2
*
* @var string
*/
protected $_secondary_id;
/**
* @since 2.0.0
* @var int The ID of the blog that is associated with the current site level options.
*/
private $_blog_id = 0;
/**
* @since 2.0.0
* @var bool
*/
private $_is_multisite_storage;
/**
* @var array
*/
protected $_data;
/**
* @var FS_Key_Value_Storage[]
*/
private static $_instances = array();
/**
* @var FS_Logger
*/
protected $_logger;
/**
* @param string $id
* @param string $secondary_id
* @param bool $network_level_or_blog_id
*
* @return FS_Key_Value_Storage
*/
static function instance( $id, $secondary_id, $network_level_or_blog_id = false ) {
$key = $id . ':' . $secondary_id;
if ( is_multisite() ) {
if ( true === $network_level_or_blog_id ) {
$key .= ':ms';
} else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) {
$key .= ":{$network_level_or_blog_id}";
} else {
$network_level_or_blog_id = get_current_blog_id();
$key .= ":{$network_level_or_blog_id}";
}
}
if ( ! isset( self::$_instances[ $key ] ) ) {
self::$_instances[ $key ] = new FS_Key_Value_Storage( $id, $secondary_id, $network_level_or_blog_id );
}
return self::$_instances[ $key ];
}
protected function __construct( $id, $secondary_id, $network_level_or_blog_id = false ) {
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $secondary_id . '_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
$this->_id = $id;
$this->_secondary_id = $secondary_id;
if ( is_multisite() ) {
$this->_is_multisite_storage = ( true === $network_level_or_blog_id );
if ( is_numeric( $network_level_or_blog_id ) ) {
$this->_blog_id = $network_level_or_blog_id;
}
} else {
$this->_is_multisite_storage = false;
}
$this->load();
}
protected function get_option_manager() {
return FS_Option_Manager::get_manager(
WP_FS__ACCOUNTS_OPTION_NAME,
true,
$this->_is_multisite_storage ?
true :
( $this->_blog_id > 0 ? $this->_blog_id : false )
);
}
protected function get_all_data() {
return $this->get_option_manager()->get_option( $this->_id, array() );
}
/**
* Load plugin data from local DB.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*/
function load() {
$all_plugins_data = $this->get_all_data();
$this->_data = isset( $all_plugins_data[ $this->_secondary_id ] ) ?
$all_plugins_data[ $this->_secondary_id ] :
array();
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param string $key
* @param mixed $value
* @param bool $flush
*/
function store( $key, $value, $flush = true ) {
if ( $this->_logger->is_on() ) {
$this->_logger->entrance( $key . ' = ' . var_export( $value, true ) );
}
if ( array_key_exists( $key, $this->_data ) && $value === $this->_data[ $key ] ) {
// No need to store data if the value wasn't changed.
return;
}
$all_data = $this->get_all_data();
$this->_data[ $key ] = $value;
$all_data[ $this->_secondary_id ] = $this->_data;
$options_manager = $this->get_option_manager();
$options_manager->set_option( $this->_id, $all_data, $flush );
}
/**
* @author Vova Feldman (@svovaf)
* @since 2.0.0
*/
function save() {
$this->get_option_manager()->store();
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param bool $store
* @param string[] $exceptions Set of keys to keep and not clear.
*/
function clear_all( $store = true, $exceptions = array() ) {
$new_data = array();
foreach ( $exceptions as $key ) {
if ( isset( $this->_data[ $key ] ) ) {
$new_data[ $key ] = $this->_data[ $key ];
}
}
$this->_data = $new_data;
if ( $store ) {
$all_data = $this->get_all_data();
$all_data[ $this->_secondary_id ] = $this->_data;
$options_manager = $this->get_option_manager();
$options_manager->set_option( $this->_id, $all_data, true );
}
}
/**
* Delete key-value storage.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.9
*/
function delete() {
$this->_data = array();
$all_data = $this->get_all_data();
unset( $all_data[ $this->_secondary_id ] );
$options_manager = $this->get_option_manager();
$options_manager->set_option( $this->_id, $all_data, true );
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param string $key
* @param bool $store
*/
function remove( $key, $store = true ) {
if ( ! array_key_exists( $key, $this->_data ) ) {
return;
}
unset( $this->_data[ $key ] );
if ( $store ) {
$all_data = $this->get_all_data();
$all_data[ $this->_secondary_id ] = $this->_data;
$options_manager = $this->get_option_manager();
$options_manager->set_option( $this->_id, $all_data, true );
}
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param string $key
* @param mixed $default
*
* @return bool|\FS_Plugin
*/
function get( $key, $default = false ) {
return array_key_exists( $key, $this->_data ) ?
$this->_data[ $key ] :
$default;
}
/**
* @author Vova Feldman (@svovaf)
* @since 2.0.0
*
* @return string
*/
function get_secondary_id() {
return $this->_secondary_id;
}
/* ArrayAccess + Magic Access (better for refactoring)
-----------------------------------------------------------------------------------*/
function __set( $k, $v ) {
$this->store( $k, $v );
}
function __isset( $k ) {
return array_key_exists( $k, $this->_data );
}
function __unset( $k ) {
$this->remove( $k );
}
function __get( $k ) {
return $this->get( $k, null );
}
#[ReturnTypeWillChange]
function offsetSet( $k, $v ) {
if ( is_null( $k ) ) {
throw new Exception( 'Can\'t append value to request params.' );
} else {
$this->{$k} = $v;
}
}
#[ReturnTypeWillChange]
function offsetExists( $k ) {
return array_key_exists( $k, $this->_data );
}
#[ReturnTypeWillChange]
function offsetUnset( $k ) {
unset( $this->$k );
}
#[ReturnTypeWillChange]
function offsetGet( $k ) {
return $this->get( $k, null );
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the current element
*
* @link http://php.net/manual/en/iterator.current.php
* @return mixed Can return any type.
*/
#[ReturnTypeWillChange]
public function current() {
return current( $this->_data );
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Move forward to next element
*
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
*/
#[ReturnTypeWillChange]
public function next() {
next( $this->_data );
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Return the key of the current element
*
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
*/
#[ReturnTypeWillChange]
public function key() {
return key( $this->_data );
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Checks if current position is valid
*
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
*/
#[ReturnTypeWillChange]
public function valid() {
$key = key( $this->_data );
return ( $key !== null && $key !== false );
}
/**
* (PHP 5 &gt;= 5.0.0)<br/>
* Rewind the Iterator to the first element
*
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
*/
#[ReturnTypeWillChange]
public function rewind() {
reset( $this->_data );
}
/**
* (PHP 5 &gt;= 5.1.0)<br/>
* Count elements of an object
*
* @link http://php.net/manual/en/countable.count.php
* @return int The custom count as an integer.
* </p>
* <p>
* The return value is cast to an integer.
*/
#[ReturnTypeWillChange]
public function count() {
return count( $this->_data );
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.0.6
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class FS_License_Manager /*extends FS_Abstract_Manager*/
{
//
//
// /**
// * @var FS_License_Manager[]
// */
// private static $_instances = array();
//
// static function instance( Freemius $fs ) {
// $slug = strtolower( $fs->get_slug() );
//
// if ( ! isset( self::$_instances[ $slug ] ) ) {
// self::$_instances[ $slug ] = new FS_License_Manager( $slug, $fs );
// }
//
// return self::$_instances[ $slug ];
// }
//
//// private function __construct($slug) {
//// parent::__construct($slug);
//// }
//
// function entry_id() {
// return 'licenses';
// }
//
// function sync( $id ) {
//
// }
//
// /**
// * @author Vova Feldman (@svovaf)
// * @since 1.0.5
// * @uses FS_Api
// *
// * @param number|bool $plugin_id
// *
// * @return FS_Plugin_License[]|stdClass Licenses or API error.
// */
// function api_get_user_plugin_licenses( $plugin_id = false ) {
// $api = $this->_fs->get_api_user_scope();
//
// if ( ! is_numeric( $plugin_id ) ) {
// $plugin_id = $this->_fs->get_id();
// }
//
// $result = $api->call( "/plugins/{$plugin_id}/licenses.json" );
//
// if ( ! isset( $result->error ) ) {
// for ( $i = 0, $len = count( $result->licenses ); $i < $len; $i ++ ) {
// $result->licenses[ $i ] = new FS_Plugin_License( $result->licenses[ $i ] );
// }
//
// $result = $result->licenses;
// }
//
// return $result;
// }
//
// function api_get_many() {
//
// }
//
// function api_activate( $id ) {
//
// }
//
// function api_deactivate( $id ) {
//
// }
/**
* @param FS_Plugin_License[] $licenses
*
* @return bool
*/
static function has_premium_license( $licenses ) {
if ( is_array( $licenses ) ) {
foreach ( $licenses as $license ) {
/**
* @var FS_Plugin_License $license
*/
if ( ! $license->is_utilized() && $license->is_features_enabled() ) {
return true;
}
}
}
return false;
}
}

View File

@@ -0,0 +1,476 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.0.3
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* 2-layer lazy options manager.
* layer 2: Memory
* layer 1: Database (options table). All options stored as one option record in the DB to reduce number of DB queries.
*
* If load() is not explicitly called, starts as empty manager. Same thing about saving the data - you have to explicitly call store().
*
* Class Freemius_Option_Manager
*/
class FS_Option_Manager {
/**
* @var string
*/
private $_id;
/**
* @var array|object
*/
private $_options;
/**
* @var FS_Logger
*/
private $_logger;
/**
* @since 2.0.0
* @var int The ID of the blog that is associated with the current site level options.
*/
private $_blog_id = 0;
/**
* @since 2.0.0
* @var bool
*/
private $_is_network_storage;
/**
* @var bool|null
*/
private $_autoload;
/**
* @var array[string]FS_Option_Manager {
* @key string
* @value FS_Option_Manager
* }
*/
private static $_MANAGERS = array();
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @param string $id
* @param bool $load
* @param bool|int $network_level_or_blog_id Since 2.0.0
* @param bool|null $autoload
*/
private function __construct(
$id,
$load = false,
$network_level_or_blog_id = false,
$autoload = null
) {
$id = strtolower( $id );
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_opt_mngr_' . $id, WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
$this->_logger->entrance();
$this->_logger->log( 'id = ' . $id );
$this->_id = $id;
$this->_autoload = $autoload;
if ( is_multisite() ) {
$this->_is_network_storage = ( true === $network_level_or_blog_id );
if ( is_numeric( $network_level_or_blog_id ) ) {
$this->_blog_id = $network_level_or_blog_id;
}
} else {
$this->_is_network_storage = false;
}
if ( $load ) {
$this->load();
}
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @param string $id
* @param bool $load
* @param bool|int $network_level_or_blog_id Since 2.0.0
* @param bool|null $autoload
*
* @return \FS_Option_Manager
*/
static function get_manager(
$id,
$load = false,
$network_level_or_blog_id = false,
$autoload = null
) {
$key = strtolower( $id );
if ( is_multisite() ) {
if ( true === $network_level_or_blog_id ) {
$key .= ':ms';
} else if ( is_numeric( $network_level_or_blog_id ) && $network_level_or_blog_id > 0 ) {
$key .= ":{$network_level_or_blog_id}";
} else {
$network_level_or_blog_id = get_current_blog_id();
$key .= ":{$network_level_or_blog_id}";
}
}
if ( ! isset( self::$_MANAGERS[ $key ] ) ) {
self::$_MANAGERS[ $key ] = new FS_Option_Manager(
$id,
$load,
$network_level_or_blog_id,
$autoload
);
} // If load required but not yet loaded, load.
else if ( $load && ! self::$_MANAGERS[ $key ]->is_loaded() ) {
self::$_MANAGERS[ $key ]->load();
}
return self::$_MANAGERS[ $key ];
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @param bool $flush
*/
function load( $flush = false ) {
$this->_logger->entrance();
if ( ! $flush && isset( $this->_options ) ) {
return;
}
if ( isset( $this->_options ) ) {
// Clear prev options.
$this->clear();
}
$option_name = $this->get_option_manager_name();
if ( $this->_is_network_storage ) {
$this->_options = get_site_option( $option_name );
} else if ( $this->_blog_id > 0 ) {
$this->_options = get_blog_option( $this->_blog_id, $option_name );
} else {
$this->_options = get_option( $option_name );
}
if ( is_string( $this->_options ) ) {
$this->_options = json_decode( $this->_options );
}
// $this->_logger->info('get_option = ' . var_export($this->_options, true));
if ( false === $this->_options ) {
$this->clear();
}
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @return bool
*/
function is_loaded() {
return isset( $this->_options );
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @return bool
*/
function is_empty() {
return ( $this->is_loaded() && false === $this->_options );
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*
* @param bool $flush
*/
function clear( $flush = false ) {
$this->_logger->entrance();
$this->_options = array();
if ( $flush ) {
$this->store();
}
}
/**
* Delete options manager from DB.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.9
*/
function delete() {
$option_name = $this->get_option_manager_name();
if ( $this->_is_network_storage ) {
delete_site_option( $option_name );
} else if ( $this->_blog_id > 0 ) {
delete_blog_option( $this->_blog_id, $option_name );
} else {
delete_option( $option_name );
}
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*
* @param string $option
* @param bool $flush
*
* @return bool
*/
function has_option( $option, $flush = false ) {
if ( ! $this->is_loaded() || $flush ) {
$this->load( $flush );
}
return array_key_exists( $option, $this->_options );
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @param string $option
* @param mixed $default
* @param bool $flush
*
* @return mixed
*/
function get_option( $option, $default = null, $flush = false ) {
$this->_logger->entrance( 'option = ' . $option );
if ( ! $this->is_loaded() || $flush ) {
$this->load( $flush );
}
if ( is_array( $this->_options ) ) {
$value = isset( $this->_options[ $option ] ) ?
$this->_options[ $option ] :
$default;
} else if ( is_object( $this->_options ) ) {
$value = isset( $this->_options->{$option} ) ?
$this->_options->{$option} :
$default;
} else {
$value = $default;
}
/**
* If it's an object, return a clone of the object, otherwise,
* external changes of the object will actually change the value
* of the object in the option manager which may lead to an unexpected
* behaviour and data integrity when a store() call is triggered.
*
* Example:
* $object1 = $options->get_option( 'object1' );
* $object1->x = 123;
*
* $object2 = $options->get_option( 'object2' );
* $object2->y = 'dummy';
*
* $options->set_option( 'object2', $object2, true );
*
* If we don't return a clone of option 'object1', setting 'object2'
* will also store the updated value of 'object1' which is quite not
* an expected behaviour.
*
* @author Vova Feldman
*/
return is_object( $value ) ? clone $value : $value;
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @param string $option
* @param mixed $value
* @param bool $flush
*/
function set_option( $option, $value, $flush = false ) {
$this->_logger->entrance( 'option = ' . $option );
if ( ! $this->is_loaded() ) {
$this->clear();
}
/**
* If it's an object, store a clone of the object, otherwise,
* external changes of the object will actually change the value
* of the object in the options manager which may lead to an unexpected
* behaviour and data integrity when a store() call is triggered.
*
* Example:
* $object1 = new stdClass();
* $object1->x = 123;
*
* $options->set_option( 'object1', $object1 );
*
* $object1->x = 456;
*
* $options->set_option( 'object2', $object2, true );
*
* If we don't set the option as a clone of option 'object1', setting 'object2'
* will also store the updated value of 'object1' ($object1->x = 456 instead of
* $object1->x = 123) which is quite not an expected behaviour.
*
* @author Vova Feldman
*/
$copy = is_object( $value ) ? clone $value : $value;
if ( is_array( $this->_options ) ) {
$this->_options[ $option ] = $copy;
} else if ( is_object( $this->_options ) ) {
$this->_options->{$option} = $copy;
}
if ( $flush ) {
$this->store();
}
}
/**
* Unset option.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @param string $option
* @param bool $flush
*/
function unset_option( $option, $flush = false ) {
$this->_logger->entrance( 'option = ' . $option );
if ( is_array( $this->_options ) ) {
if ( ! isset( $this->_options[ $option ] ) ) {
return;
}
unset( $this->_options[ $option ] );
} else if ( is_object( $this->_options ) ) {
if ( ! isset( $this->_options->{$option} ) ) {
return;
}
unset( $this->_options->{$option} );
}
if ( $flush ) {
$this->store();
}
}
/**
* Dump options to database.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*/
function store() {
$this->_logger->entrance();
$option_name = $this->get_option_manager_name();
if ( $this->_logger->is_on() ) {
$this->_logger->info( $option_name . ' = ' . var_export( $this->_options, true ) );
}
// Update DB.
if ( $this->_is_network_storage ) {
update_site_option( $option_name, $this->_options );
} else if ( $this->_blog_id > 0 ) {
update_blog_option( $this->_blog_id, $option_name, $this->_options );
} else {
update_option( $option_name, $this->_options, $this->_autoload );
}
}
/**
* Get options keys.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.3
*
* @return string[]
*/
function get_options_keys() {
if ( is_array( $this->_options ) ) {
return array_keys( $this->_options );
} else if ( is_object( $this->_options ) ) {
return array_keys( get_object_vars( $this->_options ) );
}
return array();
}
#--------------------------------------------------------------------------------
#region Migration
#--------------------------------------------------------------------------------
/**
* Migrate options from site level.
*
* @author Vova Feldman (@svovaf)
* @since 2.0.0
*/
function migrate_to_network() {
$site_options = FS_Option_Manager::get_manager($this->_id, true, false);
$options = is_object( $site_options->_options ) ?
get_object_vars( $site_options->_options ) :
$site_options->_options;
if ( ! empty( $options ) ) {
foreach ( $options as $key => $val ) {
$this->set_option( $key, $val, false );
}
$this->store();
}
}
#endregion
#--------------------------------------------------------------------------------
#region Helper Methods
#--------------------------------------------------------------------------------
/**
* @return string
*/
private function get_option_manager_name() {
return $this->_id;
}
#endregion
}

View File

@@ -0,0 +1,707 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2022, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 2.5.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* This class is responsible for managing the user permissions.
*
* @author Vova Feldman (@svovaf)
* @since 2.5.1
*/
class FS_Permission_Manager {
/**
* @var Freemius
*/
private $_fs;
/**
* @var FS_Storage
*/
private $_storage;
/**
* @var array<number,self>
*/
private static $_instances = array();
const PERMISSION_USER = 'user';
const PERMISSION_SITE = 'site';
const PERMISSION_EVENTS = 'events';
const PERMISSION_ESSENTIALS = 'essentials';
const PERMISSION_DIAGNOSTIC = 'diagnostic';
const PERMISSION_EXTENSIONS = 'extensions';
const PERMISSION_NEWSLETTER = 'newsletter';
/**
* @param Freemius $fs
*
* @return self
*/
static function instance( Freemius $fs ) {
$id = $fs->get_id();
if ( ! isset( self::$_instances[ $id ] ) ) {
self::$_instances[ $id ] = new self( $fs );
}
return self::$_instances[ $id ];
}
/**
* @param Freemius $fs
*/
protected function __construct( Freemius $fs ) {
$this->_fs = $fs;
$this->_storage = FS_Storage::instance( $fs->get_module_type(), $fs->get_slug() );
}
/**
* @return string[]
*/
static function get_all_permission_ids() {
return array(
self::PERMISSION_USER,
self::PERMISSION_SITE,
self::PERMISSION_EVENTS,
self::PERMISSION_ESSENTIALS,
self::PERMISSION_DIAGNOSTIC,
self::PERMISSION_EXTENSIONS,
self::PERMISSION_NEWSLETTER,
);
}
/**
* @return string[]
*/
static function get_api_managed_permission_ids() {
return array(
self::PERMISSION_USER,
self::PERMISSION_SITE,
self::PERMISSION_EXTENSIONS,
);
}
/**
* @param string $permission
*
* @return bool
*/
static function is_supported_permission( $permission ) {
return in_array( $permission, self::get_all_permission_ids() );
}
/**
* @since 2.5.3
*
* @return bool
*/
function is_premium_context() {
return ( $this->_fs->is_premium() || $this->_fs->can_use_premium_code() );
}
/**
* @param bool $is_license_activation
* @param array[] $extra_permissions
*
* @return array[]
*/
function get_permissions( $is_license_activation, array $extra_permissions = array() ) {
return $is_license_activation ?
$this->get_license_activation_permissions( $extra_permissions ) :
$this->get_opt_in_permissions( $extra_permissions );
}
#--------------------------------------------------------------------------------
#region Opt-In Permissions
#--------------------------------------------------------------------------------
/**
* @param array[] $extra_permissions
*
* @return array[]
*/
function get_opt_in_permissions(
array $extra_permissions = array(),
$load_default_from_storage = false,
$is_optional = false
) {
$permissions = array_merge(
$this->get_opt_in_required_permissions( $load_default_from_storage ),
$this->get_opt_in_optional_permissions( $load_default_from_storage, $is_optional ),
$extra_permissions
);
return $this->get_sorted_permissions_by_priority( $permissions );
}
/**
* @param bool $load_default_from_storage
*
* @return array[]
*/
function get_opt_in_required_permissions( $load_default_from_storage = false ) {
return array( $this->get_user_permission( $load_default_from_storage ) );
}
/**
* @param bool $load_default_from_storage
* @param bool $is_optional
*
* @return array[]
*/
function get_opt_in_optional_permissions(
$load_default_from_storage = false,
$is_optional = false
) {
return array_merge(
$this->get_opt_in_diagnostic_permissions( $load_default_from_storage, $is_optional ),
array( $this->get_extensions_permission(
false,
false,
$load_default_from_storage
) )
);
}
/**
* @param bool $load_default_from_storage
* @param bool $is_optional
*
* @return array[]
*/
function get_opt_in_diagnostic_permissions(
$load_default_from_storage = false,
$is_optional = false
) {
// Alias.
$fs = $this->_fs;
$permissions = array();
$permissions[] = $this->get_permission(
self::PERMISSION_SITE,
'admin-links',
$fs->get_text_inline( 'View Basic Website Info', 'permissions-site' ),
$fs->get_text_inline( 'Homepage URL & title, WP & PHP versions, and site language', 'permissions-site_desc' ),
sprintf(
/* translators: %s: 'Plugin' or 'Theme' */
$fs->get_text_inline( 'To provide additional functionality that\'s relevant to your website, avoid WordPress or PHP version incompatibilities that can break your website, and recognize which languages & regions the %s should be translated and tailored to.', 'permissions-site_tooltip' ),
$fs->get_module_label( true )
),
10,
$is_optional,
true,
$load_default_from_storage
);
$permissions[] = $this->get_permission(
self::PERMISSION_EVENTS,
'admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
sprintf( $fs->get_text_inline( 'View Basic %s Info', 'permissions-events' ), $fs->get_module_label() ),
sprintf(
/* translators: %s: 'Plugin' or 'Theme' */
$fs->get_text_inline( 'Current %s & SDK versions, and if active or uninstalled', 'permissions-events_desc' ),
$fs->get_module_label( true )
),
'',
20,
$is_optional,
true,
$load_default_from_storage
);
return $permissions;
}
#endregion
#--------------------------------------------------------------------------------
#region License Activation Permissions
#--------------------------------------------------------------------------------
/**
* @param array[] $extra_permissions
*
* @return array[]
*/
function get_license_activation_permissions(
array $extra_permissions = array(),
$include_optional_label = true
) {
$permissions = array_merge(
$this->get_license_required_permissions(),
$this->get_license_optional_permissions( $include_optional_label ),
$extra_permissions
);
return $this->get_sorted_permissions_by_priority( $permissions );
}
/**
* @param bool $load_default_from_storage
*
* @return array[]
*/
function get_license_required_permissions( $load_default_from_storage = false ) {
// Alias.
$fs = $this->_fs;
$permissions = array();
$permissions[] = $this->get_permission(
self::PERMISSION_ESSENTIALS,
'admin-links',
$fs->get_text_inline( 'View License Essentials', 'permissions-essentials' ),
$fs->get_text_inline(
sprintf(
/* translators: %s: 'Plugin' or 'Theme' */
'Homepage URL, %s version, SDK version',
$fs->get_module_label()
),
'permissions-essentials_desc'
),
sprintf(
/* translators: %s: 'Plugin' or 'Theme' */
$fs->get_text_inline( 'To let you manage & control where the license is activated and ensure %s security & feature updates are only delivered to websites you authorize.', 'permissions-essentials_tooltip' ),
$fs->get_module_label( true )
),
10,
false,
true,
$load_default_from_storage
);
$permissions[] = $this->get_permission(
self::PERMISSION_EVENTS,
'admin-' . ( $fs->is_plugin() ? 'plugins' : 'appearance' ),
sprintf( $fs->get_text_inline( 'View %s State', 'permissions-events' ), $fs->get_module_label() ),
sprintf(
/* translators: %s: 'Plugin' or 'Theme' */
$fs->get_text_inline( 'Is active, deactivated, or uninstalled', 'permissions-events_desc-paid' ),
$fs->get_module_label( true )
),
sprintf( $fs->get_text_inline( 'So you can reuse the license when the %s is no longer active.', 'permissions-events_tooltip' ), $fs->get_module_label( true ) ),
20,
false,
true,
$load_default_from_storage
);
return $permissions;
}
/**
* @return array[]
*/
function get_license_optional_permissions(
$include_optional_label = false,
$load_default_from_storage = false
) {
return array(
$this->get_diagnostic_permission( $include_optional_label, $load_default_from_storage ),
$this->get_extensions_permission( true, $include_optional_label, $load_default_from_storage ),
);
}
/**
* @param bool $include_optional_label
* @param bool $load_default_from_storage
*
* @return array
*/
function get_diagnostic_permission(
$include_optional_label = false,
$load_default_from_storage = false
) {
return $this->get_permission(
self::PERMISSION_DIAGNOSTIC,
'wordpress-alt',
$this->_fs->get_text_inline( 'View Diagnostic Info', 'permissions-diagnostic' ) . ( $include_optional_label ? ' (' . $this->_fs->get_text_inline( 'optional' ) . ')' : '' ),
$this->_fs->get_text_inline( 'WordPress & PHP versions, site language & title', 'permissions-diagnostic_desc' ),
sprintf(
/* translators: %s: 'Plugin' or 'Theme' */
$this->_fs->get_text_inline( 'To avoid breaking your website due to WordPress or PHP version incompatibilities, and recognize which languages & regions the %s should be translated and tailored to.', 'permissions-diagnostic_tooltip' ),
$this->_fs->get_module_label( true )
),
25,
true,
true,
$load_default_from_storage
);
}
#endregion
#--------------------------------------------------------------------------------
#region Common Permissions
#--------------------------------------------------------------------------------
/**
* @param bool $is_license_activation
* @param bool $include_optional_label
* @param bool $load_default_from_storage
*
* @return array
*/
function get_extensions_permission(
$is_license_activation,
$include_optional_label = false,
$load_default_from_storage = false
) {
$is_on_by_default = ! $is_license_activation;
return $this->get_permission(
self::PERMISSION_EXTENSIONS,
'block-default',
$this->_fs->get_text_inline( 'View Plugins & Themes List', 'permissions-extensions' ) . ( $is_license_activation ? ( $include_optional_label ? ' (' . $this->_fs->get_text_inline( 'optional' ) . ')' : '' ) : '' ),
$this->_fs->get_text_inline( 'Names, slugs, versions, and if active or not', 'permissions-extensions_desc' ),
$this->_fs->get_text_inline( 'To ensure compatibility and avoid conflicts with your installed plugins and themes.', 'permissions-events_tooltip' ),
25,
true,
$is_on_by_default,
$load_default_from_storage
);
}
/**
* @param bool $load_default_from_storage
*
* @return array
*/
function get_user_permission( $load_default_from_storage = false ) {
return $this->get_permission(
self::PERMISSION_USER,
'admin-users',
$this->_fs->get_text_inline( 'View Basic Profile Info', 'permissions-profile' ),
$this->_fs->get_text_inline( 'Your WordPress user\'s: first & last name, and email address', 'permissions-profile_desc' ),
$this->_fs->get_text_inline( 'Never miss important updates, get security warnings before they become public knowledge, and receive notifications about special offers and awesome new features.', 'permissions-profile_tooltip' ),
5,
false,
true,
$load_default_from_storage
);
}
#endregion
#--------------------------------------------------------------------------------
#region Optional Permissions
#--------------------------------------------------------------------------------
/**
* @return array[]
*/
function get_newsletter_permission() {
return $this->get_permission(
self::PERMISSION_NEWSLETTER,
'email-alt',
$this->_fs->get_text_inline( 'Newsletter', 'permissions-newsletter' ),
$this->_fs->get_text_inline( 'Updates, announcements, marketing, no spam', 'permissions-newsletter_desc' ),
'',
15
);
}
#endregion
#--------------------------------------------------------------------------------
#region Permissions Storage
#--------------------------------------------------------------------------------
/**
* @param int|null $blog_id
*
* @return bool
*/
function is_extensions_tracking_allowed( $blog_id = null ) {
return $this->is_permission_allowed( self::PERMISSION_EXTENSIONS, ! $this->_fs->is_premium(), $blog_id );
}
/**
* @param int|null $blog_id
*
* @return bool
*/
function is_essentials_tracking_allowed( $blog_id = null ) {
return $this->is_permission_allowed( self::PERMISSION_ESSENTIALS, true, $blog_id );
}
/**
* @param bool $default
*
* @return bool
*/
function is_diagnostic_tracking_allowed( $default = true ) {
return $this->is_premium_context() ?
$this->is_permission_allowed( self::PERMISSION_DIAGNOSTIC, $default ) :
$this->is_permission_allowed( self::PERMISSION_SITE, $default );
}
/**
* @param int|null $blog_id
*
* @return bool
*/
function is_homepage_url_tracking_allowed( $blog_id = null ) {
return $this->is_permission_allowed( $this->get_site_permission_name(), true, $blog_id );
}
/**
* @param int|null $blog_id
*
* @return bool
*/
function update_site_tracking( $is_enabled, $blog_id = null, $only_if_not_set = false ) {
$permissions = $this->get_site_tracking_permission_names();
$result = true;
foreach ( $permissions as $permission ) {
if ( ! $only_if_not_set || ! $this->is_permission_set( $permission, $blog_id ) ) {
$result = ( $result && $this->update_permission_tracking_flag( $permission, $is_enabled, $blog_id ) );
}
}
return $result;
}
/**
* @param string $permission
* @param bool $default
* @param int|null $blog_id
*
* @return bool
*/
function is_permission_allowed( $permission, $default = false, $blog_id = null ) {
if ( ! self::is_supported_permission( $permission ) ) {
return $default;
}
return $this->is_permission( $permission, true, $blog_id );
}
/**
* @param string $permission
* @param bool $is_allowed
* @param int|null $blog_id
*
* @return bool
*/
function is_permission( $permission, $is_allowed, $blog_id = null ) {
if ( ! self::is_supported_permission( $permission ) ) {
return false;
}
$tag = "is_{$permission}_tracking_allowed";
return ( $is_allowed === $this->_fs->apply_filters(
$tag,
$this->_storage->get(
$tag,
$this->get_permission_default( $permission ),
$blog_id,
FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED
)
) );
}
/**
* @param string $permission
* @param int|null $blog_id
*
* @return bool
*/
function is_permission_set( $permission, $blog_id = null ) {
$tag = "is_{$permission}_tracking_allowed";
$permission = $this->_storage->get(
$tag,
null,
$blog_id,
FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED
);
return is_bool( $permission );
}
/**
* @param string[] $permissions
* @param bool $is_allowed
*
* @return bool `true` if all given permissions are in sync with `$is_allowed`.
*/
function are_permissions( $permissions, $is_allowed, $blog_id = null ) {
foreach ( $permissions as $permission ) {
if ( ! $this->is_permission( $permission, $is_allowed, $blog_id ) ) {
return false;
}
}
return true;
}
/**
* @param string $permission
* @param bool $is_enabled
* @param int|null $blog_id
*
* @return bool `false` if permission not supported or `$is_enabled` is not a boolean.
*/
function update_permission_tracking_flag( $permission, $is_enabled, $blog_id = null ) {
if ( is_bool( $is_enabled ) && self::is_supported_permission( $permission ) ) {
$this->_storage->store(
"is_{$permission}_tracking_allowed",
$is_enabled,
$blog_id,
FS_Storage::OPTION_LEVEL_NETWORK_ACTIVATED_NOT_DELEGATED
);
return true;
}
return false;
}
/**
* @param array<string,bool> $permissions
*/
function update_permissions_tracking_flag( $permissions ) {
foreach ( $permissions as $permission => $is_enabled ) {
$this->update_permission_tracking_flag( $permission, $is_enabled );
}
}
#endregion
/**
* @param string $permission
*
* @return bool
*/
function get_permission_default( $permission ) {
if (
$this->_fs->is_premium() &&
self::PERMISSION_EXTENSIONS === $permission
) {
return false;
}
// All permissions except for the extensions in paid version are on by default when the user opts in to usage tracking.
return true;
}
/**
* @return string
*/
function get_site_permission_name() {
return $this->is_premium_context() ?
self::PERMISSION_ESSENTIALS :
self::PERMISSION_SITE;
}
/**
* @return string[]
*/
function get_site_tracking_permission_names() {
return $this->is_premium_context() ?
array(
FS_Permission_Manager::PERMISSION_ESSENTIALS,
FS_Permission_Manager::PERMISSION_EVENTS,
) :
array( FS_Permission_Manager::PERMISSION_SITE );
}
#--------------------------------------------------------------------------------
#region Rendering
#--------------------------------------------------------------------------------
/**
* @param array $permission
*/
function render_permission( array $permission ) {
fs_require_template( 'connect/permission.php', $permission );
}
/**
* @param array $permissions_group
*/
function render_permissions_group( array $permissions_group ) {
$permissions_group[ 'fs' ] = $this->_fs;
fs_require_template( 'connect/permissions-group.php', $permissions_group );
}
function require_permissions_js() {
fs_require_once_template( 'js/permissions.php', $params );
}
#endregion
#--------------------------------------------------------------------------------
#region Helper Methods
#--------------------------------------------------------------------------------
/**
* @param string $id
* @param string $dashicon
* @param string $label
* @param string $desc
* @param string $tooltip
* @param int $priority
* @param bool $is_optional
* @param bool $is_on_by_default
* @param bool $load_from_storage
*
* @return array
*/
private function get_permission(
$id,
$dashicon,
$label,
$desc,
$tooltip = '',
$priority = 10,
$is_optional = false,
$is_on_by_default = true,
$load_from_storage = false
) {
$is_on = $load_from_storage ?
$this->is_permission_allowed( $id, $is_on_by_default ) :
$is_on_by_default;
return array(
'id' => $id,
'icon-class' => $this->_fs->apply_filters( "permission_{$id}_icon", "dashicons dashicons-{$dashicon}" ),
'label' => $this->_fs->apply_filters( "permission_{$id}_label", $label ),
'tooltip' => $this->_fs->apply_filters( "permission_{$id}_tooltip", $tooltip ),
'desc' => $this->_fs->apply_filters( "permission_{$id}_desc", $desc ),
'priority' => $this->_fs->apply_filters( "permission_{$id}_priority", $priority ),
'optional' => $is_optional,
'default' => $this->_fs->apply_filters( "permission_{$id}_default", $is_on ),
);
}
/**
* @param array $permissions
*
* @return array[]
*/
private function get_sorted_permissions_by_priority( array $permissions ) {
// Allow filtering of the permissions list.
$permissions = $this->_fs->apply_filters( 'permission_list', $permissions );
// Sort by priority.
uasort( $permissions, 'fs_sort_by_priority' );
return $permissions;
}
#endregion
}

View File

@@ -0,0 +1,162 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.0.6
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class FS_Plan_Manager {
/**
* @var FS_Plan_Manager
*/
private static $_instance;
/**
* @return FS_Plan_Manager
*/
static function instance() {
if ( ! isset( self::$_instance ) ) {
self::$_instance = new FS_Plan_Manager();
}
return self::$_instance;
}
private function __construct() {
}
/**
* @param FS_Plugin_License[] $licenses
*
* @return bool
*/
function has_premium_license( $licenses ) {
if ( is_array( $licenses ) ) {
/**
* @var FS_Plugin_License[] $licenses
*/
foreach ( $licenses as $license ) {
if ( ! $license->is_utilized() && $license->is_features_enabled() ) {
return true;
}
}
}
return false;
}
/**
* Check if plugin has any paid plans.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param FS_Plugin_Plan[] $plans
*
* @return bool
*/
function has_paid_plan( $plans ) {
if ( ! is_array( $plans ) || 0 === count( $plans ) ) {
return false;
}
/**
* @var FS_Plugin_Plan[] $plans
*/
for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) {
if ( ! $plans[ $i ]->is_free() ) {
return true;
}
}
return false;
}
/**
* Check if plugin has any free plan, or is it premium only.
*
* Note: If no plans configured, assume plugin is free.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.7
*
* @param FS_Plugin_Plan[] $plans
*
* @return bool
*/
function has_free_plan( $plans ) {
if ( ! is_array( $plans ) || 0 === count( $plans ) ) {
return true;
}
/**
* @var FS_Plugin_Plan[] $plans
*/
for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) {
if ( $plans[ $i ]->is_free() ) {
return true;
}
}
return false;
}
/**
* Find all plans that have trial.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.9
*
* @param FS_Plugin_Plan[] $plans
*
* @return FS_Plugin_Plan[]
*/
function get_trial_plans( $plans ) {
$trial_plans = array();
if ( is_array( $plans ) && 0 < count( $plans ) ) {
/**
* @var FS_Plugin_Plan[] $plans
*/
for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) {
if ( $plans[ $i ]->has_trial() ) {
$trial_plans[] = $plans[ $i ];
}
}
}
return $trial_plans;
}
/**
* Check if plugin has any trial plan.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.9
*
* @param FS_Plugin_Plan[] $plans
*
* @return bool
*/
function has_trial_plan( $plans ) {
if ( ! is_array( $plans ) || 0 === count( $plans ) ) {
return true;
}
/**
* @var FS_Plugin_Plan[] $plans
*/
for ( $i = 0, $len = count( $plans ); $i < $len; $i ++ ) {
if ( $plans[ $i ]->has_trial() ) {
return true;
}
}
return false;
}
}

View File

@@ -0,0 +1,233 @@
<?php
/**
* @package Freemius
* @copyright Copyright (c) 2015, Freemius, Inc.
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
* @since 1.0.6
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class FS_Plugin_Manager {
/**
* @since 1.2.2
*
* @var string|number
*/
protected $_module_id;
/**
* @since 1.2.2
*
* @var FS_Plugin
*/
protected $_module;
/**
* @var FS_Plugin_Manager[]
*/
private static $_instances = array();
/**
* @var FS_Logger
*/
protected $_logger;
/**
* Option names
*
* @author Leo Fajardo (@leorw)
* @since 1.2.2
*/
const OPTION_NAME_PLUGINS = 'plugins';
const OPTION_NAME_THEMES = 'themes';
/**
* @param string|number $module_id
*
* @return FS_Plugin_Manager
*/
static function instance( $module_id ) {
$key = 'm_' . $module_id;
if ( ! isset( self::$_instances[ $key ] ) ) {
self::$_instances[ $key ] = new FS_Plugin_Manager( $module_id );
}
return self::$_instances[ $key ];
}
/**
* @param string|number $module_id
*/
protected function __construct( $module_id ) {
$this->_logger = FS_Logger::get_logger( WP_FS__SLUG . '_' . $module_id . '_' . 'plugins', WP_FS__DEBUG_SDK, WP_FS__ECHO_DEBUG_SDK );
$this->_module_id = $module_id;
$this->load();
}
protected function get_option_manager() {
return FS_Option_Manager::get_manager( WP_FS__ACCOUNTS_OPTION_NAME, true, true );
}
/**
* @author Leo Fajardo (@leorw)
* @since 1.2.2
*
* @param string|bool $module_type "plugin", "theme", or "false" for all modules.
*
* @return array
*/
protected function get_all_modules( $module_type = false ) {
$option_manager = $this->get_option_manager();
if ( false !== $module_type ) {
return fs_get_entities( $option_manager->get_option( $module_type . 's', array() ), FS_Plugin::get_class_name() );
}
return array(
self::OPTION_NAME_PLUGINS => fs_get_entities( $option_manager->get_option( self::OPTION_NAME_PLUGINS, array() ), FS_Plugin::get_class_name() ),
self::OPTION_NAME_THEMES => fs_get_entities( $option_manager->get_option( self::OPTION_NAME_THEMES, array() ), FS_Plugin::get_class_name() ),
);
}
/**
* Load plugin data from local DB.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*/
function load() {
$all_modules = $this->get_all_modules();
if ( ! is_numeric( $this->_module_id ) ) {
unset( $all_modules[ self::OPTION_NAME_THEMES ] );
}
foreach ( $all_modules as $modules ) {
/**
* @since 1.2.2
*
* @var $modules FS_Plugin[]
*/
foreach ( $modules as $module ) {
$found_module = false;
/**
* If module ID is not numeric, it must be a plugin's slug.
*
* @author Leo Fajardo (@leorw)
* @since 1.2.2
*/
if ( ! is_numeric( $this->_module_id ) ) {
if ( $this->_module_id === $module->slug ) {
$this->_module_id = $module->id;
$found_module = true;
}
} else if ( $this->_module_id == $module->id ) {
$found_module = true;
}
if ( $found_module ) {
$this->_module = $module;
break;
}
}
}
}
/**
* Store plugin on local DB.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*
* @param bool|FS_Plugin $module
* @param bool $flush
*
* @return bool|\FS_Plugin
*/
function store( $module = false, $flush = true ) {
if ( false !== $module ) {
$this->_module = $module;
}
$all_modules = $this->get_all_modules( $this->_module->type );
$all_modules[ $this->_module->slug ] = $this->_module;
$options_manager = $this->get_option_manager();
$options_manager->set_option( $this->_module->type . 's', $all_modules, $flush );
return $this->_module;
}
/**
* Update local plugin data if different.
*
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*
* @param \FS_Plugin $plugin
* @param bool $store
*
* @return bool True if plugin was updated.
*/
function update( FS_Plugin $plugin, $store = true ) {
if ( ! ($this->_module instanceof FS_Plugin ) ||
$this->_module->slug != $plugin->slug ||
$this->_module->public_key != $plugin->public_key ||
$this->_module->secret_key != $plugin->secret_key ||
$this->_module->parent_plugin_id != $plugin->parent_plugin_id ||
$this->_module->title != $plugin->title
) {
$this->store( $plugin, $store );
return true;
}
return false;
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*
* @param FS_Plugin $plugin
* @param bool $store
*/
function set( FS_Plugin $plugin, $store = false ) {
$this->_module = $plugin;
if ( $store ) {
$this->store();
}
}
/**
* @author Vova Feldman (@svovaf)
* @since 1.0.6
*
* @return bool|\FS_Plugin
*/
function get() {
if ( isset( $this->_module ) ) {
return $this->_module;
}
if ( empty( $this->_module_id ) ) {
return false;
}
/**
* Return an FS_Plugin entity that has its `id` and `is_live` properties set (`is_live` is initialized in the FS_Plugin constructor) to avoid triggering an error that is relevant to these properties when the FS_Plugin entity is used before the `parse_settings()` method is called. This can happen when creating a regular WordPress site by cloning a subsite of a multisite network and the data that is stored in the network-level storage is not cloned.
*
* @author Leo Fajardo (@leorw)
* @since 2.5.0
*/
$plugin = new FS_Plugin();
$plugin->id = $this->_module_id;
return $plugin;
}
}

View File

@@ -0,0 +1,3 @@
<?php
// Silence is golden.
// Hide file structure from users on unprotected servers.