PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.37
Code Manager v1.0.37
1.0.47 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.3 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.4 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9
code-manager / freemius / start.php
code-manager / freemius Last commit date
assets 1 year ago includes 1 year ago languages 1 year ago templates 1 year ago LICENSE.txt 1 year ago config.php 1 year ago index.php 1 year ago require.php 1 year ago start.php 1 year ago
start.php
563 lines
1 <?php
2 /**
3 * @package Freemius
4 * @copyright Copyright (c) 2015, Freemius, Inc.
5 * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
6 * @since 1.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.8.0';
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 }
563