| @@ -1,522 +1,562 @@ | ||
| 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.0.3 | |
| 7 | - */ | |
| 8 | - | |
| 9 | - if ( ! defined( 'ABSPATH' ) ) { | |
| 10 | - exit; | |
| 11 | - } | |
| 12 | - | |
| 13 | - /** | |
| 14 | - * Freemius SDK Version. | |
| 15 | - * | |
| 16 | - * @var string | |
| 17 | - */ | |
| 18 | - $this_sdk_version = '2.3.2'; | |
| 19 | - | |
| 20 | - #region SDK Selection Logic -------------------------------------------------------------------- | |
| 21 | - | |
| 22 | - /** | |
| 23 | - * Special logic added on 1.1.6 to make sure that every Freemius powered plugin | |
| 24 | - * will ALWAYS be loaded with the newest SDK from the active Freemius powered plugins. | |
| 25 | - * | |
| 26 | - * Since Freemius SDK is backward compatible, this will make sure that all Freemius powered | |
| 27 | - * plugins will run correctly. | |
| 28 | - * | |
| 29 | - * @since 1.1.6 | |
| 30 | - */ | |
| 31 | - | |
| 32 | - global $fs_active_plugins; | |
| 33 | - | |
| 34 | - if ( ! function_exists( 'fs_find_caller_plugin_file' ) ) { | |
| 35 | - // Require SDK essentials. | |
| 36 | - require_once dirname( __FILE__ ) . '/includes/fs-essential-functions.php'; | |
| 37 | - } | |
| 38 | - | |
| 39 | - /** | |
| 40 | - * This complex logic fixes symlink issues (e.g. with Vargant). The logic assumes | |
| 41 | - * that if it's a file from an SDK running in a theme, the location of the SDK | |
| 42 | - * is in the main theme's folder. | |
| 43 | - * | |
| 44 | - * @author Vova Feldman (@svovaf) | |
| 45 | - * @since 1.2.2.6 | |
| 46 | - */ | |
| 47 | - $file_path = fs_normalize_path( __FILE__ ); | |
| 48 | - $fs_root_path = dirname( $file_path ); | |
| 49 | - /** | |
| 50 | - * Get the themes directory where the active theme is located (not passing the stylesheet will make WordPress | |
| 51 | - * assume that the themes directory is inside `wp-content`. | |
| 52 | - * | |
| 53 | - * @author Leo Fajardo (@leorw) | |
| 54 | - * @since 2.2.3 | |
| 55 | - */ | |
| 56 | - $themes_directory = get_theme_root( get_stylesheet() ); | |
| 57 | - $themes_directory_name = basename( $themes_directory ); | |
| 58 | - $theme_candidate_basename = basename( dirname( $fs_root_path ) ) . '/' . basename( $fs_root_path ); | |
| 59 | - | |
| 60 | - if ( $file_path == fs_normalize_path( realpath( trailingslashit( $themes_directory ) . $theme_candidate_basename . '/' . basename( $file_path ) ) ) | |
| 61 | - ) { | |
| 62 | - $this_sdk_relative_path = '../' . $themes_directory_name . '/' . $theme_candidate_basename; | |
| 63 | - $is_theme = true; | |
| 64 | - } else { | |
| 65 | - $this_sdk_relative_path = plugin_basename( $fs_root_path ); | |
| 66 | - $is_theme = false; | |
| 67 | - } | |
| 68 | - | |
| 69 | - if ( ! isset( $fs_active_plugins ) ) { | |
| 70 | - // Load all Freemius powered active plugins. | |
| 71 | - $fs_active_plugins = get_option( 'fs_active_plugins', new stdClass() ); | |
| 72 | - | |
| 73 | - if ( ! isset( $fs_active_plugins->plugins ) ) { | |
| 74 | - $fs_active_plugins->plugins = array(); | |
| 75 | - } | |
| 76 | - } | |
| 77 | - | |
| 78 | - if ( empty( $fs_active_plugins->abspath ) ) { | |
| 79 | - /** | |
| 80 | - * Store the WP install absolute path reference to identify environment change | |
| 81 | - * while replicating the storage. | |
| 82 | - * | |
| 83 | - * @author Vova Feldman (@svovaf) | |
| 84 | - * @since 1.2.1.7 | |
| 85 | - */ | |
| 86 | - $fs_active_plugins->abspath = ABSPATH; | |
| 87 | - } else { | |
| 88 | - if ( ABSPATH !== $fs_active_plugins->abspath ) { | |
| 89 | - /** | |
| 90 | - * WordPress path has changed, cleanup the SDK references cache. | |
| 91 | - * This resolves issues triggered when spinning a staging environments | |
| 92 | - * while replicating the database. | |
| 93 | - * | |
| 94 | - * @author Vova Feldman (@svovaf) | |
| 95 | - * @since 1.2.1.7 | |
| 96 | - */ | |
| 97 | - $fs_active_plugins->abspath = ABSPATH; | |
| 98 | - $fs_active_plugins->plugins = array(); | |
| 99 | - unset( $fs_active_plugins->newest ); | |
| 100 | - } else { | |
| 101 | - /** | |
| 102 | - * Make sure SDK references are still valid. This resolves | |
| 103 | - * issues when users hard delete modules via FTP. | |
| 104 | - * | |
| 105 | - * @author Vova Feldman (@svovaf) | |
| 106 | - * @since 1.2.1.7 | |
| 107 | - */ | |
| 108 | - $has_changes = false; | |
| 109 | - foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) { | |
| 110 | - if ( ! file_exists( ( isset( $data->type ) && 'theme' === $data->type ? $themes_directory : WP_PLUGIN_DIR ) . '/' . $sdk_path ) ) { | |
| 111 | - unset( $fs_active_plugins->plugins[ $sdk_path ] ); | |
| 112 | - $has_changes = true; | |
| 113 | - } | |
| 114 | - } | |
| 115 | - | |
| 116 | - if ( $has_changes ) { | |
| 117 | - if ( empty( $fs_active_plugins->plugins ) ) { | |
| 118 | - unset( $fs_active_plugins->newest ); | |
| 119 | - } | |
| 120 | - | |
| 121 | - update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 122 | - } | |
| 123 | - } | |
| 124 | - } | |
| 125 | - | |
| 126 | - if ( ! function_exists( 'fs_find_direct_caller_plugin_file' ) ) { | |
| 127 | - require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-1.1.7.1.php'; | |
| 128 | - } | |
| 129 | - | |
| 130 | - if ( ! function_exists( 'fs_get_plugins' ) ) { | |
| 131 | - require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-2.2.1.php'; | |
| 132 | - } | |
| 133 | - | |
| 134 | - // Update current SDK info based on the SDK path. | |
| 135 | - if ( ! isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) || | |
| 136 | - $this_sdk_version != $fs_active_plugins->plugins[ $this_sdk_relative_path ]->version | |
| 137 | - ) { | |
| 138 | - if ( $is_theme ) { | |
| 139 | - $plugin_path = basename( dirname( $this_sdk_relative_path ) ); | |
| 140 | - } else { | |
| 141 | - $plugin_path = plugin_basename( fs_find_direct_caller_plugin_file( $file_path ) ); | |
| 142 | - } | |
| 143 | - | |
| 144 | - $fs_active_plugins->plugins[ $this_sdk_relative_path ] = (object) array( | |
| 145 | - 'version' => $this_sdk_version, | |
| 146 | - 'type' => ( $is_theme ? 'theme' : 'plugin' ), | |
| 147 | - 'timestamp' => time(), | |
| 148 | - 'plugin_path' => $plugin_path, | |
| 149 | - ); | |
| 150 | - } | |
| 151 | - | |
| 152 | - $is_current_sdk_newest = isset( $fs_active_plugins->newest ) && ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path ); | |
| 153 | - | |
| 154 | - if ( ! isset( $fs_active_plugins->newest ) ) { | |
| 155 | - /** | |
| 156 | - * This will be executed only once, for the first time a Freemius powered plugin is activated. | |
| 157 | - */ | |
| 158 | - fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); | |
| 159 | - | |
| 160 | - $is_current_sdk_newest = true; | |
| 161 | - } else if ( version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '<' ) ) { | |
| 162 | - /** | |
| 163 | - * Current SDK is newer than the newest stored SDK. | |
| 164 | - */ | |
| 165 | - fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); | |
| 166 | - | |
| 167 | - if ( class_exists( 'Freemius' ) ) { | |
| 168 | - // Older SDK version was already loaded. | |
| 169 | - | |
| 170 | - if ( ! $fs_active_plugins->newest->in_activation ) { | |
| 171 | - // Re-order plugins to load this plugin first. | |
| 172 | - fs_newest_sdk_plugin_first(); | |
| 173 | - } | |
| 174 | - | |
| 175 | - // Refresh page. | |
| 176 | - fs_redirect( $_SERVER['REQUEST_URI'] ); | |
| 177 | - } | |
| 178 | - } else { | |
| 179 | - if ( ! function_exists( 'get_plugins' ) ) { | |
| 180 | - require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 181 | - } | |
| 182 | - | |
| 183 | - $fs_newest_sdk = $fs_active_plugins->newest; | |
| 184 | - $fs_newest_sdk = $fs_active_plugins->plugins[ $fs_newest_sdk->sdk_path ]; | |
| 185 | - | |
| 186 | - $is_newest_sdk_type_theme = ( isset( $fs_newest_sdk->type ) && 'theme' === $fs_newest_sdk->type ); | |
| 187 | - | |
| 188 | - if ( ! $is_newest_sdk_type_theme ) { | |
| 189 | - $is_newest_sdk_plugin_active = is_plugin_active( $fs_newest_sdk->plugin_path ); | |
| 190 | - } else { | |
| 191 | - $current_theme = wp_get_theme(); | |
| 192 | - $is_newest_sdk_plugin_active = ( $current_theme->stylesheet === $fs_newest_sdk->plugin_path ); | |
| 193 | - | |
| 194 | - $current_theme_parent = $current_theme->parent(); | |
| 195 | - | |
| 196 | - /** | |
| 197 | - * If the current theme is a child of the theme that has the newest SDK, this prevents a redirects loop | |
| 198 | - * from happening by keeping the SDK info stored in the `fs_active_plugins` option. | |
| 199 | - */ | |
| 200 | - if ( ! $is_newest_sdk_plugin_active && $current_theme_parent instanceof WP_Theme ) { | |
| 201 | - $is_newest_sdk_plugin_active = ( $fs_newest_sdk->plugin_path === $current_theme_parent->stylesheet ); | |
| 202 | - } | |
| 203 | - } | |
| 204 | - | |
| 205 | - if ( $is_current_sdk_newest && | |
| 206 | - ! $is_newest_sdk_plugin_active && | |
| 207 | - ! $fs_active_plugins->newest->in_activation | |
| 208 | - ) { | |
| 209 | - // If current SDK is the newest and the plugin is NOT active, it means | |
| 210 | - // that the current plugin in activation mode. | |
| 211 | - $fs_active_plugins->newest->in_activation = true; | |
| 212 | - update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 213 | - } | |
| 214 | - | |
| 215 | - if ( ! $is_theme ) { | |
| 216 | - $sdk_starter_path = fs_normalize_path( WP_PLUGIN_DIR . '/' . $this_sdk_relative_path . '/start.php' ); | |
| 217 | - } else { | |
| 218 | - $sdk_starter_path = fs_normalize_path( | |
| 219 | - $themes_directory | |
| 220 | - . '/' | |
| 221 | - . str_replace( "../{$themes_directory_name}/", '', $this_sdk_relative_path ) | |
| 222 | - . '/start.php' ); | |
| 223 | - } | |
| 224 | - | |
| 225 | - $is_newest_sdk_path_valid = ( $is_newest_sdk_plugin_active || $fs_active_plugins->newest->in_activation ) && file_exists( $sdk_starter_path ); | |
| 226 | - | |
| 227 | - if ( ! $is_newest_sdk_path_valid && ! $is_current_sdk_newest ) { | |
| 228 | - // Plugin with newest SDK is no longer active, or SDK was moved to a different location. | |
| 229 | - unset( $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ] ); | |
| 230 | - } | |
| 231 | - | |
| 232 | - if ( ! ( $is_newest_sdk_plugin_active || $fs_active_plugins->newest->in_activation ) || | |
| 233 | - ! $is_newest_sdk_path_valid || | |
| 234 | - // Is newest SDK downgraded. | |
| 235 | - ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && | |
| 236 | - version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '>' ) ) | |
| 237 | - ) { | |
| 238 | - /** | |
| 239 | - * Plugin with newest SDK is no longer active. | |
| 240 | - * OR | |
| 241 | - * The newest SDK was in the current plugin. BUT, seems like the version of | |
| 242 | - * the SDK was downgraded to a lower SDK. | |
| 243 | - */ | |
| 244 | - // Find the active plugin with the newest SDK version and update the newest reference. | |
| 245 | - fs_fallback_to_newest_active_sdk(); | |
| 246 | - } else { | |
| 247 | - if ( $is_newest_sdk_plugin_active && | |
| 248 | - $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && | |
| 249 | - ( $fs_active_plugins->newest->in_activation || | |
| 250 | - ( class_exists( 'Freemius' ) && ( ! defined( 'WP_FS__SDK_VERSION' ) || version_compare( WP_FS__SDK_VERSION, $this_sdk_version, '<' ) ) ) | |
| 251 | - ) | |
| 252 | - | |
| 253 | - ) { | |
| 254 | - if ( $fs_active_plugins->newest->in_activation && ! $is_newest_sdk_type_theme ) { | |
| 255 | - // Plugin no more in activation. | |
| 256 | - $fs_active_plugins->newest->in_activation = false; | |
| 257 | - update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 258 | - } | |
| 259 | - | |
| 260 | - // Reorder plugins to load plugin with newest SDK first. | |
| 261 | - if ( fs_newest_sdk_plugin_first() ) { | |
| 262 | - // Refresh page after re-order to make sure activated plugin loads newest SDK. | |
| 263 | - if ( class_exists( 'Freemius' ) ) { | |
| 264 | - fs_redirect( $_SERVER['REQUEST_URI'] ); | |
| 265 | - } | |
| 266 | - } | |
| 267 | - } | |
| 268 | - } | |
| 269 | - } | |
| 270 | - | |
| 271 | - if ( class_exists( 'Freemius' ) ) { | |
| 272 | - // SDK was already loaded. | |
| 273 | - return; | |
| 274 | - } | |
| 275 | - | |
| 276 | - if ( version_compare( $this_sdk_version, $fs_active_plugins->newest->version, '<' ) ) { | |
| 277 | - $newest_sdk = $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ]; | |
| 278 | - | |
| 279 | - $plugins_or_theme_dir_path = ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) ? | |
| 280 | - WP_PLUGIN_DIR : | |
| 281 | - $themes_directory; | |
| 282 | - | |
| 283 | - $newest_sdk_starter = fs_normalize_path( | |
| 284 | - $plugins_or_theme_dir_path | |
| 285 | - . '/' | |
| 286 | - . str_replace( "../{$themes_directory_name}/", '', $fs_active_plugins->newest->sdk_path ) | |
| 287 | - . '/start.php' ); | |
| 288 | - | |
| 289 | - if ( file_exists( $newest_sdk_starter ) ) { | |
| 290 | - // Reorder plugins to load plugin with newest SDK first. | |
| 291 | - fs_newest_sdk_plugin_first(); | |
| 292 | - | |
| 293 | - // There's a newer SDK version, load it instead of the current one! | |
| 294 | - require_once $newest_sdk_starter; | |
| 295 | - | |
| 296 | - return; | |
| 297 | - } | |
| 298 | - } | |
| 299 | - | |
| 300 | - #endregion SDK Selection Logic -------------------------------------------------------------------- | |
| 301 | - | |
| 302 | - #region Hooks & Filters Collection -------------------------------------------------------------------- | |
| 303 | - | |
| 304 | - /** | |
| 305 | - * Freemius hooks (actions & filters) tags structure: | |
| 306 | - * | |
| 307 | - * fs_{filter/action_name}_{plugin_slug} | |
| 308 | - * | |
| 309 | - * -------------------------------------------------------- | |
| 310 | - * | |
| 311 | - * Usage with WordPress' add_action() / add_filter(): | |
| 312 | - * | |
| 313 | - * add_action('fs_{filter/action_name}_{plugin_slug}', $callable); | |
| 314 | - * | |
| 315 | - * -------------------------------------------------------- | |
| 316 | - * | |
| 317 | - * Usage with Freemius' instance add_action() / add_filter(): | |
| 318 | - * | |
| 319 | - * // No need to add 'fs_' prefix nor '_{plugin_slug}' suffix. | |
| 320 | - * my_freemius()->add_action('{action_name}', $callable); | |
| 321 | - * | |
| 322 | - * -------------------------------------------------------- | |
| 323 | - * | |
| 324 | - * Freemius filters collection: | |
| 325 | - * | |
| 326 | - * fs_connect_url_{plugin_slug} | |
| 327 | - * fs_trial_promotion_message_{plugin_slug} | |
| 328 | - * fs_is_long_term_user_{plugin_slug} | |
| 329 | - * fs_uninstall_reasons_{plugin_slug} | |
| 330 | - * fs_is_plugin_update_{plugin_slug} | |
| 331 | - * fs_api_domains_{plugin_slug} | |
| 332 | - * fs_email_template_sections_{plugin_slug} | |
| 333 | - * fs_support_forum_submenu_{plugin_slug} | |
| 334 | - * fs_support_forum_url_{plugin_slug} | |
| 335 | - * fs_connect_message_{plugin_slug} | |
| 336 | - * fs_connect_message_on_update_{plugin_slug} | |
| 337 | - * fs_uninstall_confirmation_message_{plugin_slug} | |
| 338 | - * fs_pending_activation_message_{plugin_slug} | |
| 339 | - * fs_is_submenu_visible_{plugin_slug} | |
| 340 | - * fs_plugin_icon_{plugin_slug} | |
| 341 | - * fs_show_trial_{plugin_slug} | |
| 342 | - * | |
| 343 | - * -------------------------------------------------------- | |
| 344 | - * | |
| 345 | - * Freemius actions collection: | |
| 346 | - * | |
| 347 | - * fs_after_license_loaded_{plugin_slug} | |
| 348 | - * fs_after_license_change_{plugin_slug} | |
| 349 | - * fs_after_plans_sync_{plugin_slug} | |
| 350 | - * | |
| 351 | - * fs_after_account_details_{plugin_slug} | |
| 352 | - * fs_after_account_user_sync_{plugin_slug} | |
| 353 | - * fs_after_account_plan_sync_{plugin_slug} | |
| 354 | - * fs_before_account_load_{plugin_slug} | |
| 355 | - * fs_after_account_connection_{plugin_slug} | |
| 356 | - * fs_account_property_edit_{plugin_slug} | |
| 357 | - * fs_account_email_verified_{plugin_slug} | |
| 358 | - * fs_account_page_load_before_departure_{plugin_slug} | |
| 359 | - * fs_before_account_delete_{plugin_slug} | |
| 360 | - * fs_after_account_delete_{plugin_slug} | |
| 361 | - * | |
| 362 | - * fs_sdk_version_update_{plugin_slug} | |
| 363 | - * fs_plugin_version_update_{plugin_slug} | |
| 364 | - * | |
| 365 | - * fs_initiated_{plugin_slug} | |
| 366 | - * fs_after_init_plugin_registered_{plugin_slug} | |
| 367 | - * fs_after_init_plugin_anonymous_{plugin_slug} | |
| 368 | - * fs_after_init_plugin_pending_activations_{plugin_slug} | |
| 369 | - * fs_after_init_addon_registered_{plugin_slug} | |
| 370 | - * fs_after_init_addon_anonymous_{plugin_slug} | |
| 371 | - * fs_after_init_addon_pending_activations_{plugin_slug} | |
| 372 | - * | |
| 373 | - * fs_after_premium_version_activation_{plugin_slug} | |
| 374 | - * fs_after_free_version_reactivation_{plugin_slug} | |
| 375 | - * | |
| 376 | - * fs_after_uninstall_{plugin_slug} | |
| 377 | - * fs_before_admin_menu_init_{plugin_slug} | |
| 378 | - */ | |
| 379 | - | |
| 380 | - #endregion Hooks & Filters Collection -------------------------------------------------------------------- | |
| 381 | - | |
| 382 | - if ( ! class_exists( 'Freemius' ) ) { | |
| 383 | - | |
| 384 | - if ( ! defined( 'WP_FS__SDK_VERSION' ) ) { | |
| 385 | - define( 'WP_FS__SDK_VERSION', $this_sdk_version ); | |
| 386 | - } | |
| 387 | - | |
| 388 | - $plugins_or_theme_dir_path = fs_normalize_path( trailingslashit( $is_theme ? | |
| 389 | - $themes_directory : | |
| 390 | - WP_PLUGIN_DIR ) ); | |
| 391 | - | |
| 392 | - if ( 0 === strpos( $file_path, $plugins_or_theme_dir_path ) ) { | |
| 393 | - // No symlinks | |
| 394 | - } else { | |
| 395 | - /** | |
| 396 | - * This logic finds the SDK symlink and set WP_FS__DIR to use it. | |
| 397 | - * | |
| 398 | - * @author Vova Feldman (@svovaf) | |
| 399 | - * @since 1.2.2.5 | |
| 400 | - */ | |
| 401 | - $sdk_symlink = null; | |
| 402 | - | |
| 403 | - // Try to load SDK's symlink from cache. | |
| 404 | - if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && | |
| 405 | - is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && | |
| 406 | - ! empty( $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink ) | |
| 407 | - ) { | |
| 408 | - $sdk_symlink = $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink; | |
| 409 | - if ( 0 === strpos( $sdk_symlink, $plugins_or_theme_dir_path ) ) { | |
| 410 | - /** | |
| 411 | - * Make the symlink path relative. | |
| 412 | - * | |
| 413 | - * @author Leo Fajardo (@leorw) | |
| 414 | - */ | |
| 415 | - $sdk_symlink = substr( $sdk_symlink, strlen( $plugins_or_theme_dir_path ) ); | |
| 416 | - | |
| 417 | - $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; | |
| 418 | - update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 419 | - } | |
| 420 | - | |
| 421 | - $realpath = realpath( $plugins_or_theme_dir_path . $sdk_symlink ); | |
| 422 | - if ( ! is_string( $realpath ) || ! file_exists( $realpath ) ) { | |
| 423 | - $sdk_symlink = null; | |
| 424 | - } | |
| 425 | - } | |
| 426 | - | |
| 427 | - if ( empty( $sdk_symlink ) ) // Has symlinks, therefore, we need to configure WP_FS__DIR based on the symlink. | |
| 428 | - { | |
| 429 | - $partial_path_right = basename( $file_path ); | |
| 430 | - $partial_path_left = dirname( $file_path ); | |
| 431 | - $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); | |
| 432 | - | |
| 433 | - while ( '/' !== $partial_path_left && | |
| 434 | - ( false === $realpath || $file_path !== fs_normalize_path( $realpath ) ) | |
| 435 | - ) { | |
| 436 | - $partial_path_right = trailingslashit( basename( $partial_path_left ) ) . $partial_path_right; | |
| 437 | - $partial_path_left_prev = $partial_path_left; | |
| 438 | - $partial_path_left = dirname( $partial_path_left_prev ); | |
| 439 | - | |
| 440 | - /** | |
| 441 | - * Avoid infinite loop if for example `$partial_path_left_prev` is `C:/`, in this case, | |
| 442 | - * `dirname( 'C:/' )` will return `C:/`. | |
| 443 | - * | |
| 444 | - * @author Leo Fajardo (@leorw) | |
| 445 | - */ | |
| 446 | - if ( $partial_path_left === $partial_path_left_prev ) { | |
| 447 | - $partial_path_left = ''; | |
| 448 | - break; | |
| 449 | - } | |
| 450 | - | |
| 451 | - $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); | |
| 452 | - } | |
| 453 | - | |
| 454 | - if ( ! empty( $partial_path_left ) && '/' !== $partial_path_left ) { | |
| 455 | - $sdk_symlink = fs_normalize_path( dirname( $partial_path_right ) ); | |
| 456 | - | |
| 457 | - // Cache value. | |
| 458 | - if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && | |
| 459 | - is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) | |
| 460 | - ) { | |
| 461 | - $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; | |
| 462 | - update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 463 | - } | |
| 464 | - } | |
| 465 | - } | |
| 466 | - | |
| 467 | - if ( ! empty( $sdk_symlink ) ) { | |
| 468 | - // Set SDK dir to the symlink path. | |
| 469 | - define( 'WP_FS__DIR', $plugins_or_theme_dir_path . $sdk_symlink ); | |
| 470 | - } | |
| 471 | - } | |
| 472 | - | |
| 473 | - // Load SDK files. | |
| 474 | - require_once dirname( __FILE__ ) . '/require.php'; | |
| 475 | - | |
| 476 | - /** | |
| 477 | - * Quick shortcut to get Freemius for specified plugin. | |
| 478 | - * Used by various templates. | |
| 479 | - * | |
| 480 | - * @param number $module_id | |
| 481 | - * | |
| 482 | - * @return Freemius | |
| 483 | - */ | |
| 484 | - function freemius( $module_id ) { | |
| 485 | - return Freemius::instance( $module_id ); | |
| 486 | - } | |
| 487 | - | |
| 488 | - /** | |
| 489 | - * @param string $slug | |
| 490 | - * @param number $plugin_id | |
| 491 | - * @param string $public_key | |
| 492 | - * @param bool $is_live Is live or test plugin. | |
| 493 | - * @param bool $is_premium Hints freemius if running the premium plugin or not. | |
| 494 | - * | |
| 495 | - * @return Freemius | |
| 496 | - * | |
| 497 | - * @deprecated Please use fs_dynamic_init(). | |
| 498 | - */ | |
| 499 | - function fs_init( $slug, $plugin_id, $public_key, $is_live = true, $is_premium = true ) { | |
| 500 | - $fs = Freemius::instance( $plugin_id, $slug, true ); | |
| 501 | - $fs->init( $plugin_id, $public_key, $is_live, $is_premium ); | |
| 502 | - | |
| 503 | - return $fs; | |
| 504 | - } | |
| 505 | - | |
| 506 | - /** | |
| 507 | - * @param array <string,string> $module Plugin or Theme details. | |
| 508 | - * | |
| 509 | - * @return Freemius | |
| 510 | - * @throws Freemius_Exception | |
| 511 | - */ | |
| 512 | - function fs_dynamic_init( $module ) { | |
| 513 | - $fs = Freemius::instance( $module['id'], $module['slug'], true ); | |
| 514 | - $fs->dynamic_init( $module ); | |
| 515 | - | |
| 516 | - return $fs; | |
| 517 | - } | |
| 518 | - | |
| 519 | - function fs_dump_log() { | |
| 520 | - FS_Logger::dump(); | |
| 521 | - } | |
| 522 | - } | |
| 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.0.3 | |
| 7 | + */ | |
| 8 | + | |
| 9 | + if ( ! defined( 'ABSPATH' ) ) { | |
| 10 | + exit; | |
| 11 | + } | |
| 12 | + | |
| 13 | + /** | |
| 14 | + * Freemius SDK Version. | |
| 15 | + * | |
| 16 | + * @var string | |
| 17 | + */ | |
| 18 | + $this_sdk_version = '2.6.2'; | |
| 19 | + | |
| 20 | + #region SDK Selection Logic -------------------------------------------------------------------- | |
| 21 | + | |
| 22 | + /** | |
| 23 | + * Special logic added on 1.1.6 to make sure that every Freemius powered plugin | |
| 24 | + * will ALWAYS be loaded with the newest SDK from the active Freemius powered plugins. | |
| 25 | + * | |
| 26 | + * Since Freemius SDK is backward compatible, this will make sure that all Freemius powered | |
| 27 | + * plugins will run correctly. | |
| 28 | + * | |
| 29 | + * @since 1.1.6 | |
| 30 | + */ | |
| 31 | + | |
| 32 | + global $fs_active_plugins; | |
| 33 | + | |
| 34 | + if ( ! function_exists( 'fs_find_caller_plugin_file' ) ) { | |
| 35 | + // Require SDK essentials. | |
| 36 | + require_once dirname( __FILE__ ) . '/includes/fs-essential-functions.php'; | |
| 37 | + } | |
| 38 | + | |
| 39 | + /** | |
| 40 | + * This complex logic fixes symlink issues (e.g. with Vargant). The logic assumes | |
| 41 | + * that if it's a file from an SDK running in a theme, the location of the SDK | |
| 42 | + * is in the main theme's folder. | |
| 43 | + * | |
| 44 | + * @author Vova Feldman (@svovaf) | |
| 45 | + * @since 1.2.2.6 | |
| 46 | + */ | |
| 47 | + $file_path = fs_normalize_path( __FILE__ ); | |
| 48 | + $fs_root_path = dirname( $file_path ); | |
| 49 | + | |
| 50 | + // @todo: Remove this code after a few months when WP 6.3 usage is low enough. | |
| 51 | + global $wp_version; | |
| 52 | + | |
| 53 | + if ( | |
| 54 | + ! function_exists( 'wp_get_current_user' ) && | |
| 55 | + /** | |
| 56 | + * `get_stylesheet()` will rely on `wp_get_current_user()` when it is being filtered by `theme-previews.php`. That happens only when the site editor is loaded or when the site editor is sending REST requests. | |
| 57 | + * @see theme-previews.php:wp_get_theme_preview_path() | |
| 58 | + * | |
| 59 | + * @todo This behavior is already fixed in the core (WP 6.3.2+), and this code can be removed after a few months when WP 6.3 usage is low enough. | |
| 60 | + * @since WP 6.3.0 | |
| 61 | + */ | |
| 62 | + version_compare( $wp_version, '6.3', '>=' ) && | |
| 63 | + version_compare( $wp_version, '6.3.1', '<=' ) && | |
| 64 | + ( | |
| 65 | + 'site-editor.php' === basename( $_SERVER['SCRIPT_FILENAME'] ) || | |
| 66 | + ( | |
| 67 | + function_exists( 'wp_is_json_request' ) && | |
| 68 | + wp_is_json_request() && | |
| 69 | + ! empty( $_GET['wp_theme_preview'] ) | |
| 70 | + ) | |
| 71 | + ) | |
| 72 | + ) { | |
| 73 | + // Requiring this file since the call to get_stylesheet() below can trigger a call to wp_get_current_user() when previewing a theme. | |
| 74 | + require_once ABSPATH . 'wp-includes/pluggable.php'; | |
| 75 | + } | |
| 76 | + | |
| 77 | + /** | |
| 78 | + * Get the themes directory where the active theme is located (not passing the stylesheet will make WordPress | |
| 79 | + * assume that the themes directory is inside `wp-content`. | |
| 80 | + * | |
| 81 | + * @author Leo Fajardo (@leorw) | |
| 82 | + * @since 2.2.3 | |
| 83 | + */ | |
| 84 | + $themes_directory = get_theme_root( get_stylesheet() ); | |
| 85 | + $themes_directory_name = basename( $themes_directory ); | |
| 86 | + $theme_candidate_basename = basename( dirname( $fs_root_path ) ) . '/' . basename( $fs_root_path ); | |
| 87 | + | |
| 88 | + if ( $file_path == fs_normalize_path( realpath( trailingslashit( $themes_directory ) . $theme_candidate_basename . '/' . basename( $file_path ) ) ) | |
| 89 | + ) { | |
| 90 | + $this_sdk_relative_path = '../' . $themes_directory_name . '/' . $theme_candidate_basename; | |
| 91 | + $is_theme = true; | |
| 92 | + } else { | |
| 93 | + $this_sdk_relative_path = plugin_basename( $fs_root_path ); | |
| 94 | + $is_theme = false; | |
| 95 | + } | |
| 96 | + | |
| 97 | + if ( ! isset( $fs_active_plugins ) ) { | |
| 98 | + // Load all Freemius powered active plugins. | |
| 99 | + $fs_active_plugins = get_option( 'fs_active_plugins' ); | |
| 100 | + | |
| 101 | + if ( ! is_object( $fs_active_plugins ) ) { | |
| 102 | + $fs_active_plugins = new stdClass(); | |
| 103 | + } | |
| 104 | + | |
| 105 | + if ( ! isset( $fs_active_plugins->plugins ) ) { | |
| 106 | + $fs_active_plugins->plugins = array(); | |
| 107 | + } | |
| 108 | + } | |
| 109 | + | |
| 110 | + if ( empty( $fs_active_plugins->abspath ) ) { | |
| 111 | + /** | |
| 112 | + * Store the WP install absolute path reference to identify environment change | |
| 113 | + * while replicating the storage. | |
| 114 | + * | |
| 115 | + * @author Vova Feldman (@svovaf) | |
| 116 | + * @since 1.2.1.7 | |
| 117 | + */ | |
| 118 | + $fs_active_plugins->abspath = ABSPATH; | |
| 119 | + } else { | |
| 120 | + if ( ABSPATH !== $fs_active_plugins->abspath ) { | |
| 121 | + /** | |
| 122 | + * WordPress path has changed, cleanup the SDK references cache. | |
| 123 | + * This resolves issues triggered when spinning a staging environments | |
| 124 | + * while replicating the database. | |
| 125 | + * | |
| 126 | + * @author Vova Feldman (@svovaf) | |
| 127 | + * @since 1.2.1.7 | |
| 128 | + */ | |
| 129 | + $fs_active_plugins->abspath = ABSPATH; | |
| 130 | + $fs_active_plugins->plugins = array(); | |
| 131 | + unset( $fs_active_plugins->newest ); | |
| 132 | + } else { | |
| 133 | + /** | |
| 134 | + * Make sure SDK references are still valid. This resolves | |
| 135 | + * issues when users hard delete modules via FTP. | |
| 136 | + * | |
| 137 | + * @author Vova Feldman (@svovaf) | |
| 138 | + * @since 1.2.1.7 | |
| 139 | + */ | |
| 140 | + $has_changes = false; | |
| 141 | + foreach ( $fs_active_plugins->plugins as $sdk_path => $data ) { | |
| 142 | + if ( ! file_exists( ( isset( $data->type ) && 'theme' === $data->type ? $themes_directory : WP_PLUGIN_DIR ) . '/' . $sdk_path ) ) { | |
| 143 | + unset( $fs_active_plugins->plugins[ $sdk_path ] ); | |
| 144 | + | |
| 145 | + if ( | |
| 146 | + ! empty( $fs_active_plugins->newest ) && | |
| 147 | + $sdk_path === $fs_active_plugins->newest->sdk_path | |
| 148 | + ) { | |
| 149 | + unset( $fs_active_plugins->newest ); | |
| 150 | + } | |
| 151 | + | |
| 152 | + $has_changes = true; | |
| 153 | + } | |
| 154 | + } | |
| 155 | + | |
| 156 | + if ( $has_changes ) { | |
| 157 | + if ( empty( $fs_active_plugins->plugins ) ) { | |
| 158 | + unset( $fs_active_plugins->newest ); | |
| 159 | + } | |
| 160 | + | |
| 161 | + update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 162 | + } | |
| 163 | + } | |
| 164 | + } | |
| 165 | + | |
| 166 | + if ( ! function_exists( 'fs_find_direct_caller_plugin_file' ) ) { | |
| 167 | + require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-1.1.7.1.php'; | |
| 168 | + } | |
| 169 | + | |
| 170 | + if ( ! function_exists( 'fs_get_plugins' ) ) { | |
| 171 | + require_once dirname( __FILE__ ) . '/includes/supplements/fs-essential-functions-2.2.1.php'; | |
| 172 | + } | |
| 173 | + | |
| 174 | + // Update current SDK info based on the SDK path. | |
| 175 | + if ( ! isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) || | |
| 176 | + $this_sdk_version != $fs_active_plugins->plugins[ $this_sdk_relative_path ]->version | |
| 177 | + ) { | |
| 178 | + if ( $is_theme ) { | |
| 179 | + $plugin_path = basename( dirname( $this_sdk_relative_path ) ); | |
| 180 | + } else { | |
| 181 | + $plugin_path = plugin_basename( fs_find_direct_caller_plugin_file( $file_path ) ); | |
| 182 | + } | |
| 183 | + | |
| 184 | + $fs_active_plugins->plugins[ $this_sdk_relative_path ] = (object) array( | |
| 185 | + 'version' => $this_sdk_version, | |
| 186 | + 'type' => ( $is_theme ? 'theme' : 'plugin' ), | |
| 187 | + 'timestamp' => time(), | |
| 188 | + 'plugin_path' => $plugin_path, | |
| 189 | + ); | |
| 190 | + } | |
| 191 | + | |
| 192 | + $is_current_sdk_newest = isset( $fs_active_plugins->newest ) && ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path ); | |
| 193 | + | |
| 194 | + if ( ! isset( $fs_active_plugins->newest ) ) { | |
| 195 | + /** | |
| 196 | + * This will be executed only once, for the first time a Freemius powered plugin is activated. | |
| 197 | + */ | |
| 198 | + fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); | |
| 199 | + | |
| 200 | + $is_current_sdk_newest = true; | |
| 201 | + } else if ( version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '<' ) ) { | |
| 202 | + /** | |
| 203 | + * Current SDK is newer than the newest stored SDK. | |
| 204 | + */ | |
| 205 | + fs_update_sdk_newest_version( $this_sdk_relative_path, $fs_active_plugins->plugins[ $this_sdk_relative_path ]->plugin_path ); | |
| 206 | + | |
| 207 | + if ( class_exists( 'Freemius' ) ) { | |
| 208 | + // Older SDK version was already loaded. | |
| 209 | + | |
| 210 | + if ( ! $fs_active_plugins->newest->in_activation ) { | |
| 211 | + // Re-order plugins to load this plugin first. | |
| 212 | + fs_newest_sdk_plugin_first(); | |
| 213 | + } | |
| 214 | + | |
| 215 | + // Refresh page. | |
| 216 | + fs_redirect( $_SERVER['REQUEST_URI'] ); | |
| 217 | + } | |
| 218 | + } else { | |
| 219 | + if ( ! function_exists( 'get_plugins' ) ) { | |
| 220 | + require_once ABSPATH . 'wp-admin/includes/plugin.php'; | |
| 221 | + } | |
| 222 | + | |
| 223 | + $fs_newest_sdk = $fs_active_plugins->newest; | |
| 224 | + $fs_newest_sdk = $fs_active_plugins->plugins[ $fs_newest_sdk->sdk_path ]; | |
| 225 | + | |
| 226 | + $is_newest_sdk_type_theme = ( isset( $fs_newest_sdk->type ) && 'theme' === $fs_newest_sdk->type ); | |
| 227 | + | |
| 228 | + if ( ! $is_newest_sdk_type_theme ) { | |
| 229 | + $is_newest_sdk_plugin_active = is_plugin_active( $fs_newest_sdk->plugin_path ); | |
| 230 | + } else { | |
| 231 | + $current_theme = wp_get_theme(); | |
| 232 | + $is_newest_sdk_plugin_active = ( $current_theme->stylesheet === $fs_newest_sdk->plugin_path ); | |
| 233 | + | |
| 234 | + $current_theme_parent = $current_theme->parent(); | |
| 235 | + | |
| 236 | + /** | |
| 237 | + * If the current theme is a child of the theme that has the newest SDK, this prevents a redirects loop | |
| 238 | + * from happening by keeping the SDK info stored in the `fs_active_plugins` option. | |
| 239 | + */ | |
| 240 | + if ( ! $is_newest_sdk_plugin_active && $current_theme_parent instanceof WP_Theme ) { | |
| 241 | + $is_newest_sdk_plugin_active = ( $fs_newest_sdk->plugin_path === $current_theme_parent->stylesheet ); | |
| 242 | + } | |
| 243 | + } | |
| 244 | + | |
| 245 | + if ( $is_current_sdk_newest && | |
| 246 | + ! $is_newest_sdk_plugin_active && | |
| 247 | + ! $fs_active_plugins->newest->in_activation | |
| 248 | + ) { | |
| 249 | + // If current SDK is the newest and the plugin is NOT active, it means | |
| 250 | + // that the current plugin in activation mode. | |
| 251 | + $fs_active_plugins->newest->in_activation = true; | |
| 252 | + update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 253 | + } | |
| 254 | + | |
| 255 | + if ( ! $is_theme ) { | |
| 256 | + $sdk_starter_path = fs_normalize_path( WP_PLUGIN_DIR . '/' . $this_sdk_relative_path . '/start.php' ); | |
| 257 | + } else { | |
| 258 | + $sdk_starter_path = fs_normalize_path( | |
| 259 | + $themes_directory | |
| 260 | + . '/' | |
| 261 | + . str_replace( "../{$themes_directory_name}/", '', $this_sdk_relative_path ) | |
| 262 | + . '/start.php' ); | |
| 263 | + } | |
| 264 | + | |
| 265 | + $is_newest_sdk_path_valid = ( $is_newest_sdk_plugin_active || $fs_active_plugins->newest->in_activation ) && file_exists( $sdk_starter_path ); | |
| 266 | + | |
| 267 | + if ( ! $is_newest_sdk_path_valid && ! $is_current_sdk_newest ) { | |
| 268 | + // Plugin with newest SDK is no longer active, or SDK was moved to a different location. | |
| 269 | + unset( $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ] ); | |
| 270 | + } | |
| 271 | + | |
| 272 | + if ( ! ( $is_newest_sdk_plugin_active || $fs_active_plugins->newest->in_activation ) || | |
| 273 | + ! $is_newest_sdk_path_valid || | |
| 274 | + // Is newest SDK downgraded. | |
| 275 | + ( $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && | |
| 276 | + version_compare( $fs_active_plugins->newest->version, $this_sdk_version, '>' ) ) | |
| 277 | + ) { | |
| 278 | + /** | |
| 279 | + * Plugin with newest SDK is no longer active. | |
| 280 | + * OR | |
| 281 | + * The newest SDK was in the current plugin. BUT, seems like the version of | |
| 282 | + * the SDK was downgraded to a lower SDK. | |
| 283 | + */ | |
| 284 | + // Find the active plugin with the newest SDK version and update the newest reference. | |
| 285 | + fs_fallback_to_newest_active_sdk(); | |
| 286 | + } else { | |
| 287 | + if ( $is_newest_sdk_plugin_active && | |
| 288 | + $this_sdk_relative_path == $fs_active_plugins->newest->sdk_path && | |
| 289 | + ( $fs_active_plugins->newest->in_activation || | |
| 290 | + ( class_exists( 'Freemius' ) && ( ! defined( 'WP_FS__SDK_VERSION' ) || version_compare( WP_FS__SDK_VERSION, $this_sdk_version, '<' ) ) ) | |
| 291 | + ) | |
| 292 | + | |
| 293 | + ) { | |
| 294 | + if ( $fs_active_plugins->newest->in_activation && ! $is_newest_sdk_type_theme ) { | |
| 295 | + // Plugin no more in activation. | |
| 296 | + $fs_active_plugins->newest->in_activation = false; | |
| 297 | + update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 298 | + } | |
| 299 | + | |
| 300 | + // Reorder plugins to load plugin with newest SDK first. | |
| 301 | + if ( fs_newest_sdk_plugin_first() ) { | |
| 302 | + // Refresh page after re-order to make sure activated plugin loads newest SDK. | |
| 303 | + if ( class_exists( 'Freemius' ) ) { | |
| 304 | + fs_redirect( $_SERVER['REQUEST_URI'] ); | |
| 305 | + } | |
| 306 | + } | |
| 307 | + } | |
| 308 | + } | |
| 309 | + } | |
| 310 | + | |
| 311 | + if ( class_exists( 'Freemius' ) ) { | |
| 312 | + // SDK was already loaded. | |
| 313 | + return; | |
| 314 | + } | |
| 315 | + | |
| 316 | + if ( version_compare( $this_sdk_version, $fs_active_plugins->newest->version, '<' ) ) { | |
| 317 | + $newest_sdk = $fs_active_plugins->plugins[ $fs_active_plugins->newest->sdk_path ]; | |
| 318 | + | |
| 319 | + $plugins_or_theme_dir_path = ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) ? | |
| 320 | + WP_PLUGIN_DIR : | |
| 321 | + $themes_directory; | |
| 322 | + | |
| 323 | + $newest_sdk_starter = fs_normalize_path( | |
| 324 | + $plugins_or_theme_dir_path | |
| 325 | + . '/' | |
| 326 | + . str_replace( "../{$themes_directory_name}/", '', $fs_active_plugins->newest->sdk_path ) | |
| 327 | + . '/start.php' ); | |
| 328 | + | |
| 329 | + if ( file_exists( $newest_sdk_starter ) ) { | |
| 330 | + // Reorder plugins to load plugin with newest SDK first. | |
| 331 | + fs_newest_sdk_plugin_first(); | |
| 332 | + | |
| 333 | + // There's a newer SDK version, load it instead of the current one! | |
| 334 | + require_once $newest_sdk_starter; | |
| 335 | + | |
| 336 | + return; | |
| 337 | + } | |
| 338 | + } | |
| 339 | + | |
| 340 | + #endregion SDK Selection Logic -------------------------------------------------------------------- | |
| 341 | + | |
| 342 | + #region Hooks & Filters Collection -------------------------------------------------------------------- | |
| 343 | + | |
| 344 | + /** | |
| 345 | + * Freemius hooks (actions & filters) tags structure: | |
| 346 | + * | |
| 347 | + * fs_{filter/action_name}_{plugin_slug} | |
| 348 | + * | |
| 349 | + * -------------------------------------------------------- | |
| 350 | + * | |
| 351 | + * Usage with WordPress' add_action() / add_filter(): | |
| 352 | + * | |
| 353 | + * add_action('fs_{filter/action_name}_{plugin_slug}', $callable); | |
| 354 | + * | |
| 355 | + * -------------------------------------------------------- | |
| 356 | + * | |
| 357 | + * Usage with Freemius' instance add_action() / add_filter(): | |
| 358 | + * | |
| 359 | + * // No need to add 'fs_' prefix nor '_{plugin_slug}' suffix. | |
| 360 | + * my_freemius()->add_action('{action_name}', $callable); | |
| 361 | + * | |
| 362 | + * -------------------------------------------------------- | |
| 363 | + * | |
| 364 | + * Freemius filters collection: | |
| 365 | + * | |
| 366 | + * fs_connect_url_{plugin_slug} | |
| 367 | + * fs_trial_promotion_message_{plugin_slug} | |
| 368 | + * fs_is_long_term_user_{plugin_slug} | |
| 369 | + * fs_uninstall_reasons_{plugin_slug} | |
| 370 | + * fs_is_plugin_update_{plugin_slug} | |
| 371 | + * fs_api_domains_{plugin_slug} | |
| 372 | + * fs_email_template_sections_{plugin_slug} | |
| 373 | + * fs_support_forum_submenu_{plugin_slug} | |
| 374 | + * fs_support_forum_url_{plugin_slug} | |
| 375 | + * fs_connect_message_{plugin_slug} | |
| 376 | + * fs_connect_message_on_update_{plugin_slug} | |
| 377 | + * fs_uninstall_confirmation_message_{plugin_slug} | |
| 378 | + * fs_pending_activation_message_{plugin_slug} | |
| 379 | + * fs_is_submenu_visible_{plugin_slug} | |
| 380 | + * fs_plugin_icon_{plugin_slug} | |
| 381 | + * fs_show_trial_{plugin_slug} | |
| 382 | + * | |
| 383 | + * -------------------------------------------------------- | |
| 384 | + * | |
| 385 | + * Freemius actions collection: | |
| 386 | + * | |
| 387 | + * fs_after_license_loaded_{plugin_slug} | |
| 388 | + * fs_after_license_change_{plugin_slug} | |
| 389 | + * fs_after_plans_sync_{plugin_slug} | |
| 390 | + * | |
| 391 | + * fs_after_account_details_{plugin_slug} | |
| 392 | + * fs_after_account_user_sync_{plugin_slug} | |
| 393 | + * fs_after_account_plan_sync_{plugin_slug} | |
| 394 | + * fs_before_account_load_{plugin_slug} | |
| 395 | + * fs_after_account_connection_{plugin_slug} | |
| 396 | + * fs_account_property_edit_{plugin_slug} | |
| 397 | + * fs_account_email_verified_{plugin_slug} | |
| 398 | + * fs_account_page_load_before_departure_{plugin_slug} | |
| 399 | + * fs_before_account_delete_{plugin_slug} | |
| 400 | + * fs_after_account_delete_{plugin_slug} | |
| 401 | + * | |
| 402 | + * fs_sdk_version_update_{plugin_slug} | |
| 403 | + * fs_plugin_version_update_{plugin_slug} | |
| 404 | + * | |
| 405 | + * fs_initiated_{plugin_slug} | |
| 406 | + * fs_after_init_plugin_registered_{plugin_slug} | |
| 407 | + * fs_after_init_plugin_anonymous_{plugin_slug} | |
| 408 | + * fs_after_init_plugin_pending_activations_{plugin_slug} | |
| 409 | + * fs_after_init_addon_registered_{plugin_slug} | |
| 410 | + * fs_after_init_addon_anonymous_{plugin_slug} | |
| 411 | + * fs_after_init_addon_pending_activations_{plugin_slug} | |
| 412 | + * | |
| 413 | + * fs_after_premium_version_activation_{plugin_slug} | |
| 414 | + * fs_after_free_version_reactivation_{plugin_slug} | |
| 415 | + * | |
| 416 | + * fs_after_uninstall_{plugin_slug} | |
| 417 | + * fs_before_admin_menu_init_{plugin_slug} | |
| 418 | + */ | |
| 419 | + | |
| 420 | + #endregion Hooks & Filters Collection -------------------------------------------------------------------- | |
| 421 | + | |
| 422 | + if ( ! class_exists( 'Freemius' ) ) { | |
| 423 | + | |
| 424 | + if ( ! defined( 'WP_FS__SDK_VERSION' ) ) { | |
| 425 | + define( 'WP_FS__SDK_VERSION', $this_sdk_version ); | |
| 426 | + } | |
| 427 | + | |
| 428 | + $plugins_or_theme_dir_path = fs_normalize_path( trailingslashit( $is_theme ? | |
| 429 | + $themes_directory : | |
| 430 | + WP_PLUGIN_DIR ) ); | |
| 431 | + | |
| 432 | + if ( 0 === strpos( $file_path, $plugins_or_theme_dir_path ) ) { | |
| 433 | + // No symlinks | |
| 434 | + } else { | |
| 435 | + /** | |
| 436 | + * This logic finds the SDK symlink and set WP_FS__DIR to use it. | |
| 437 | + * | |
| 438 | + * @author Vova Feldman (@svovaf) | |
| 439 | + * @since 1.2.2.5 | |
| 440 | + */ | |
| 441 | + $sdk_symlink = null; | |
| 442 | + | |
| 443 | + // Try to load SDK's symlink from cache. | |
| 444 | + if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && | |
| 445 | + is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && | |
| 446 | + ! empty( $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink ) | |
| 447 | + ) { | |
| 448 | + $sdk_symlink = $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink; | |
| 449 | + if ( 0 === strpos( $sdk_symlink, $plugins_or_theme_dir_path ) ) { | |
| 450 | + /** | |
| 451 | + * Make the symlink path relative. | |
| 452 | + * | |
| 453 | + * @author Leo Fajardo (@leorw) | |
| 454 | + */ | |
| 455 | + $sdk_symlink = substr( $sdk_symlink, strlen( $plugins_or_theme_dir_path ) ); | |
| 456 | + | |
| 457 | + $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; | |
| 458 | + update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 459 | + } | |
| 460 | + | |
| 461 | + $realpath = realpath( $plugins_or_theme_dir_path . $sdk_symlink ); | |
| 462 | + if ( ! is_string( $realpath ) || ! file_exists( $realpath ) ) { | |
| 463 | + $sdk_symlink = null; | |
| 464 | + } | |
| 465 | + } | |
| 466 | + | |
| 467 | + if ( empty( $sdk_symlink ) ) // Has symlinks, therefore, we need to configure WP_FS__DIR based on the symlink. | |
| 468 | + { | |
| 469 | + $partial_path_right = basename( $file_path ); | |
| 470 | + $partial_path_left = dirname( $file_path ); | |
| 471 | + $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); | |
| 472 | + | |
| 473 | + while ( '/' !== $partial_path_left && | |
| 474 | + ( false === $realpath || $file_path !== fs_normalize_path( $realpath ) ) | |
| 475 | + ) { | |
| 476 | + $partial_path_right = trailingslashit( basename( $partial_path_left ) ) . $partial_path_right; | |
| 477 | + $partial_path_left_prev = $partial_path_left; | |
| 478 | + $partial_path_left = dirname( $partial_path_left_prev ); | |
| 479 | + | |
| 480 | + /** | |
| 481 | + * Avoid infinite loop if for example `$partial_path_left_prev` is `C:/`, in this case, | |
| 482 | + * `dirname( 'C:/' )` will return `C:/`. | |
| 483 | + * | |
| 484 | + * @author Leo Fajardo (@leorw) | |
| 485 | + */ | |
| 486 | + if ( $partial_path_left === $partial_path_left_prev ) { | |
| 487 | + $partial_path_left = ''; | |
| 488 | + break; | |
| 489 | + } | |
| 490 | + | |
| 491 | + $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); | |
| 492 | + } | |
| 493 | + | |
| 494 | + if ( ! empty( $partial_path_left ) && '/' !== $partial_path_left ) { | |
| 495 | + $sdk_symlink = fs_normalize_path( dirname( $partial_path_right ) ); | |
| 496 | + | |
| 497 | + // Cache value. | |
| 498 | + if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && | |
| 499 | + is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) | |
| 500 | + ) { | |
| 501 | + $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; | |
| 502 | + update_option( 'fs_active_plugins', $fs_active_plugins ); | |
| 503 | + } | |
| 504 | + } | |
| 505 | + } | |
| 506 | + | |
| 507 | + if ( ! empty( $sdk_symlink ) ) { | |
| 508 | + // Set SDK dir to the symlink path. | |
| 509 | + define( 'WP_FS__DIR', $plugins_or_theme_dir_path . $sdk_symlink ); | |
| 510 | + } | |
| 511 | + } | |
| 512 | + | |
| 513 | + // Load SDK files. | |
| 514 | + require_once dirname( __FILE__ ) . '/require.php'; | |
| 515 | + | |
| 516 | + /** | |
| 517 | + * Quick shortcut to get Freemius for specified plugin. | |
| 518 | + * Used by various templates. | |
| 519 | + * | |
| 520 | + * @param number $module_id | |
| 521 | + * | |
| 522 | + * @return Freemius | |
| 523 | + */ | |
| 524 | + function freemius( $module_id ) { | |
| 525 | + return Freemius::instance( $module_id ); | |
| 526 | + } | |
| 527 | + | |
| 528 | + /** | |
| 529 | + * @param string $slug | |
| 530 | + * @param number $plugin_id | |
| 531 | + * @param string $public_key | |
| 532 | + * @param bool $is_live Is live or test plugin. | |
| 533 | + * @param bool $is_premium Hints freemius if running the premium plugin or not. | |
| 534 | + * | |
| 535 | + * @return Freemius | |
| 536 | + * | |
| 537 | + * @deprecated Please use fs_dynamic_init(). | |
| 538 | + */ | |
| 539 | + function fs_init( $slug, $plugin_id, $public_key, $is_live = true, $is_premium = true ) { | |
| 540 | + $fs = Freemius::instance( $plugin_id, $slug, true ); | |
| 541 | + $fs->init( $plugin_id, $public_key, $is_live, $is_premium ); | |
| 542 | + | |
| 543 | + return $fs; | |
| 544 | + } | |
| 545 | + | |
| 546 | + /** | |
| 547 | + * @param array <string,string|bool|array> $module Plugin or Theme details. | |
| 548 | + * | |
| 549 | + * @return Freemius | |
| 550 | + * @throws Freemius_Exception | |
| 551 | + */ | |
| 552 | + function fs_dynamic_init( $module ) { | |
| 553 | + $fs = Freemius::instance( $module['id'], $module['slug'], true ); | |
| 554 | + $fs->dynamic_init( $module ); | |
| 555 | + | |
| 556 | + return $fs; | |
| 557 | + } | |
| 558 | + | |
| 559 | + function fs_dump_log() { | |
| 560 | + FS_Logger::dump(); | |
| 561 | + } | |
| 562 | + } | |