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