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