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