PluginProbe
BlockSpare – Gutenberg Blocks, AI Content Generator & Site Builder for News, Magazine & Blogs / 5.0.1
BlockSpare – Gutenberg Blocks, AI Content Generator & Site Builder for News, Magazine & Blogs v5.0.1
5.0.1 4.1.0 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 2.1.2 2.5.0 2.5.3 All 39 releases
← All changes | freemius/includes/fs-essential-functions.php +421 -500 2.1.2 → 5.0.1 View file →
@@ -1,500 +1,421 @@
1 -<?php
2 - /**
3 - * IMPORTANT:
4 - * This file will be loaded based on the order of the plugins/themes load.
5 - * If there's a theme and a plugin using Freemius, the plugin's essential
6 - * file will always load first.
7 - *
8 - * @package Freemius
9 - * @copyright Copyright (c) 2015, Freemius, Inc.
10 - * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
11 - * @since 1.1.5
12 - */
13 -
14 - if ( ! function_exists( 'fs_normalize_path' ) ) {
15 - if ( function_exists( 'wp_normalize_path' ) ) {
16 - /**
17 - * Normalize a filesystem path.
18 - *
19 - * Replaces backslashes with forward slashes for Windows systems, and ensures
20 - * no duplicate slashes exist.
21 - *
22 - * @param string $path Path to normalize.
23 - *
24 - * @return string Normalized path.
25 - */
26 - function fs_normalize_path( $path ) {
27 - return wp_normalize_path( $path );
28 - }
29 - } else {
30 - function fs_normalize_path( $path ) {
31 - $path = str_replace( '\\', '/', $path );
32 - $path = preg_replace( '|/+|', '/', $path );
33 -
34 - return $path;
35 - }
36 - }
37 - }
38 -
39 - require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-2.2.1.php';
40 -
41 - #region Core Redirect (copied from BuddyPress) -----------------------------------------
42 -
43 - if ( ! function_exists( 'fs_redirect' ) ) {
44 - /**
45 - * Redirects to another page, with a workaround for the IIS Set-Cookie bug.
46 - *
47 - * @link http://support.microsoft.com/kb/q176113/
48 - * @since 1.5.1
49 - * @uses apply_filters() Calls 'wp_redirect' hook on $location and $status.
50 - *
51 - * @param string $location The path to redirect to.
52 - * @param bool $exit If true, exit after redirect (Since 1.2.1.5).
53 - * @param int $status Status code to use.
54 - *
55 - * @return bool False if $location is not set
56 - */
57 - function fs_redirect( $location, $exit = true, $status = 302 ) {
58 - global $is_IIS;
59 -
60 - $file = '';
61 - $line = '';
62 - if ( headers_sent($file, $line) ) {
63 - if ( WP_FS__DEBUG_SDK && class_exists( 'FS_Admin_Notices' ) ) {
64 - $notices = FS_Admin_Notices::instance( 'global' );
65 -
66 - $notices->add( "Freemius failed to redirect the page because the headers have been already sent from line <b><code>{$line}</code></b> in file <b><code>{$file}</code></b>. If it's unexpected, it usually happens due to invalid space and/or EOL character(s).", 'Oops...', 'error' );
67 - }
68 -
69 - return false;
70 - }
71 -
72 - if ( defined( 'DOING_AJAX' ) ) {
73 - // Don't redirect on AJAX calls.
74 - return false;
75 - }
76 -
77 - if ( ! $location ) // allows the wp_redirect filter to cancel a redirect
78 - {
79 - return false;
80 - }
81 -
82 - $location = fs_sanitize_redirect( $location );
83 -
84 - if ( $is_IIS ) {
85 - header( "Refresh: 0;url=$location" );
86 - } else {
87 - if ( php_sapi_name() != 'cgi-fcgi' ) {
88 - status_header( $status );
89 - } // This causes problems on IIS and some FastCGI setups
90 - header( "Location: $location" );
91 - }
92 -
93 - if ( $exit ) {
94 - exit();
95 - }
96 -
97 - return true;
98 - }
99 -
100 - if ( ! function_exists( 'fs_sanitize_redirect' ) ) {
101 - /**
102 - * Sanitizes a URL for use in a redirect.
103 - *
104 - * @since 2.3
105 - *
106 - * @param string $location
107 - *
108 - * @return string redirect-sanitized URL
109 - */
110 - function fs_sanitize_redirect( $location ) {
111 - $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location );
112 - $location = fs_kses_no_null( $location );
113 -
114 - // remove %0d and %0a from location
115 - $strip = array( '%0d', '%0a' );
116 - $found = true;
117 - while ( $found ) {
118 - $found = false;
119 - foreach ( (array) $strip as $val ) {
120 - while ( strpos( $location, $val ) !== false ) {
121 - $found = true;
122 - $location = str_replace( $val, '', $location );
123 - }
124 - }
125 - }
126 -
127 - return $location;
128 - }
129 - }
130 -
131 - if ( ! function_exists( 'fs_kses_no_null' ) ) {
132 - /**
133 - * Removes any NULL characters in $string.
134 - *
135 - * @since 1.0.0
136 - *
137 - * @param string $string
138 - *
139 - * @return string
140 - */
141 - function fs_kses_no_null( $string ) {
142 - $string = preg_replace( '/\0+/', '', $string );
143 - $string = preg_replace( '/(\\\\0)+/', '', $string );
144 -
145 - return $string;
146 - }
147 - }
148 - }
149 -
150 - #endregion Core Redirect (copied from BuddyPress) -----------------------------------------
151 -
152 - if ( ! function_exists( '__fs' ) ) {
153 - global $fs_text_overrides;
154 -
155 - if ( ! isset( $fs_text_overrides ) ) {
156 - $fs_text_overrides = array();
157 - }
158 -
159 - /**
160 - * Retrieve a translated text by key.
161 - *
162 - * @deprecated Use `fs_text()` instead since methods starting with `__` trigger warnings in Php 7.
163 - * @todo Remove this method in the future.
164 - *
165 - * @author Vova Feldman (@svovaf)
166 - * @since 1.1.4
167 - *
168 - * @param string $key
169 - * @param string $slug
170 - *
171 - * @return string
172 - *
173 - * @global $fs_text, $fs_text_overrides
174 - */
175 - function __fs( $key, $slug = 'freemius' ) {
176 - _deprecated_function( __FUNCTION__, '2.0.0', 'fs_text()' );
177 -
178 - global $fs_text,
179 - $fs_module_info_text,
180 - $fs_text_overrides;
181 -
182 - if ( isset( $fs_text_overrides[ $slug ] ) ) {
183 - if ( isset( $fs_text_overrides[ $slug ][ $key ] ) ) {
184 - return $fs_text_overrides[ $slug ][ $key ];
185 - }
186 -
187 - $lower_key = strtolower( $key );
188 - if ( isset( $fs_text_overrides[ $slug ][ $lower_key ] ) ) {
189 - return $fs_text_overrides[ $slug ][ $lower_key ];
190 - }
191 - }
192 -
193 - if ( ! isset( $fs_text ) ) {
194 - $dir = defined( 'WP_FS__DIR_INCLUDES' ) ?
195 - WP_FS__DIR_INCLUDES :
196 - dirname( __FILE__ );
197 -
198 - require_once $dir . '/i18n.php';
199 - }
200 -
201 - if ( isset( $fs_text[ $key ] ) ) {
202 - return $fs_text[ $key ];
203 - }
204 -
205 - if ( isset( $fs_module_info_text[ $key ] ) ) {
206 - return $fs_module_info_text[ $key ];
207 - }
208 -
209 - return $key;
210 - }
211 -
212 - /**
213 - * Output a translated text by key.
214 - *
215 - * @deprecated Use `fs_echo()` instead for consistency with `fs_text()`.
216 - *
217 - * @todo Remove this method in the future.
218 - *
219 - * @author Vova Feldman (@svovaf)
220 - * @since 1.1.4
221 - *
222 - * @param string $key
223 - * @param string $slug
224 - */
225 - function _efs( $key, $slug = 'freemius' ) {
226 - fs_echo( $key, $slug );
227 - }
228 - }
229 -
230 - if ( ! function_exists( 'fs_get_ip' ) ) {
231 - /**
232 - * Get client IP.
233 - *
234 - * @author Vova Feldman (@svovaf)
235 - * @since 1.1.2
236 - *
237 - * @return string|null
238 - */
239 - function fs_get_ip() {
240 - $fields = array(
241 - 'HTTP_CF_CONNECTING_IP',
242 - 'HTTP_CLIENT_IP',
243 - 'HTTP_X_FORWARDED_FOR',
244 - 'HTTP_X_FORWARDED',
245 - 'HTTP_FORWARDED_FOR',
246 - 'HTTP_FORWARDED',
247 - 'REMOTE_ADDR',
248 - );
249 -
250 - foreach ( $fields as $ip_field ) {
251 - if ( ! empty( $_SERVER[ $ip_field ] ) ) {
252 - return $_SERVER[ $ip_field ];
253 - }
254 - }
255 -
256 - return null;
257 - }
258 - }
259 -
260 - /**
261 - * Leverage backtrace to find caller plugin main file path.
262 - *
263 - * @author Vova Feldman (@svovaf)
264 - * @since 1.0.6
265 - *
266 - * @return string
267 - */
268 - function fs_find_caller_plugin_file() {
269 - /**
270 - * All the code below will be executed once on activation.
271 - * If the user changes the main plugin's file name, the file_exists()
272 - * will catch it.
273 - */
274 - if ( ! function_exists( 'get_plugins' ) ) {
275 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
276 - }
277 -
278 - $all_plugins = fs_get_plugins( true );
279 - $all_plugins_paths = array();
280 -
281 - // Get active plugin's main files real full names (might be symlinks).
282 - foreach ( $all_plugins as $relative_path => $data ) {
283 - $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) );
284 - }
285 -
286 - $plugin_file = null;
287 - for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) {
288 - if ( empty( $bt[ $i ]['file'] ) ) {
289 - continue;
290 - }
291 -
292 - if ( in_array( fs_normalize_path( $bt[ $i ]['file'] ), $all_plugins_paths ) ) {
293 - $plugin_file = $bt[ $i ]['file'];
294 - break;
295 - }
296 - }
297 -
298 - if ( is_null( $plugin_file ) ) {
299 - // Throw an error to the developer in case of some edge case dev environment.
300 - wp_die(
301 - 'Freemius SDK couldn\'t find the plugin\'s main file. Please contact [email protected] with the current error.',
302 - 'Error',
303 - array( 'back_link' => true )
304 - );
305 - }
306 -
307 - return $plugin_file;
308 - }
309 -
310 - require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-1.1.7.1.php';
311 -
312 - /**
313 - * Update SDK newest version reference.
314 - *
315 - * @author Vova Feldman (@svovaf)
316 - * @since 1.1.6
317 - *
318 - * @param string $sdk_relative_path
319 - * @param string|bool $plugin_file
320 - *
321 - * @global $fs_active_plugins
322 - */
323 - function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false ) {
324 - /**
325 - * If there is a plugin running an older version of FS (1.2.1 or below), the `fs_update_sdk_newest_version()`
326 - * function in the older version will be used instead of this one. But since the older version is using
327 - * the `is_plugin_active` function to check if a plugin is active, passing the theme's `plugin_path` to the
328 - * `is_plugin_active` function will return false since the path is not a plugin path, so `in_activation` will be
329 - * `true` for theme modules and the upgrading of the SDK version to 1.2.2 or newer version will work fine.
330 - *
331 - * Future versions that will call this function will use the proper logic here instead of just relying on the
332 - * `is_plugin_active` function to fail for themes.
333 - *
334 - * @author Leo Fajardo (@leorw)
335 - * @since 1.2.2
336 - */
337 -
338 - global $fs_active_plugins;
339 -
340 - $newest_sdk = $fs_active_plugins->plugins[ $sdk_relative_path ];
341 -
342 - if ( ! is_string( $plugin_file ) ) {
343 - $plugin_file = plugin_basename( fs_find_caller_plugin_file() );
344 - }
345 -
346 - if ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) {
347 - if ( ! function_exists( 'is_plugin_active' ) ) {
348 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
349 - }
350 -
351 - $in_activation = ( ! is_plugin_active( $plugin_file ) );
352 - } else {
353 - $theme = wp_get_theme();
354 - $in_activation = ( $newest_sdk->plugin_path == $theme->stylesheet );
355 - }
356 -
357 - $fs_active_plugins->newest = (object) array(
358 - 'plugin_path' => $plugin_file,
359 - 'sdk_path' => $sdk_relative_path,
360 - 'version' => $newest_sdk->version,
361 - 'in_activation' => $in_activation,
362 - 'timestamp' => time(),
363 - );
364 -
365 - // Update DB with latest SDK version and path.
366 - update_option( 'fs_active_plugins', $fs_active_plugins );
367 - }
368 -
369 - /**
370 - * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first.
371 - *
372 - * @author Vova Feldman (@svovaf)
373 - * @since 1.1.6
374 - *
375 - * @return bool Was plugin order changed. Return false if plugin was loaded first anyways.
376 - *
377 - * @global $fs_active_plugins
378 - */
379 - function fs_newest_sdk_plugin_first() {
380 - global $fs_active_plugins;
381 -
382 - /**
383 - * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a plugin activated in the network mode that has an older version of the SDK of another plugin which is site activated that has new SDK version, the fs-essential-functions.php will be loaded from the older SDK. Same thing about MU plugins (loaded even before network activated plugins).
384 - *
385 - * @link https://github.com/Freemius/wordpress-sdk/issues/26
386 - */
387 -
388 - $newest_sdk_plugin_path = $fs_active_plugins->newest->plugin_path;
389 -
390 - $active_plugins = get_option( 'active_plugins', array() );
391 - $updated_active_plugins = array( $newest_sdk_plugin_path );
392 -
393 - $plugin_found = false;
394 - $is_first_path = true;
395 -
396 - foreach ( $active_plugins as $key => $plugin_path ) {
397 - if ( $plugin_path === $newest_sdk_plugin_path ) {
398 - if ( $is_first_path ) {
399 - // if it's the first plugin already, no need to continue
400 - return false;
401 - }
402 -
403 - $plugin_found = true;
404 -
405 - // Skip the plugin (it is already added as the 1st item of $updated_active_plugins).
406 - continue;
407 - }
408 -
409 - $updated_active_plugins[] = $plugin_path;
410 -
411 - if ( $is_first_path ) {
412 - $is_first_path = false;
413 - }
414 - }
415 -
416 - if ( $plugin_found ) {
417 - update_option( 'active_plugins', $updated_active_plugins );
418 -
419 - return true;
420 - }
421 -
422 - if ( is_multisite() ) {
423 - // Plugin is network active.
424 - $network_active_plugins = get_site_option( 'active_sitewide_plugins', array() );
425 -
426 - if ( isset( $network_active_plugins[ $newest_sdk_plugin_path ] ) ) {
427 - reset( $network_active_plugins );
428 - if ( $newest_sdk_plugin_path === key( $network_active_plugins ) ) {
429 - // Plugin is already activated first on the network level.
430 - return false;
431 - } else {
432 - $time = $network_active_plugins[ $newest_sdk_plugin_path ];
433 -
434 - // Remove plugin from its current position.
435 - unset( $network_active_plugins[ $newest_sdk_plugin_path ] );
436 -
437 - // Set it to be included first.
438 - $network_active_plugins = array( $newest_sdk_plugin_path => $time ) + $network_active_plugins;
439 -
440 - update_site_option( 'active_sitewide_plugins', $network_active_plugins );
441 -
442 - return true;
443 - }
444 - }
445 - }
446 -
447 - return false;
448 - }
449 -
450 - /**
451 - * Go over all Freemius SDKs in the system and find and "remember"
452 - * the newest SDK which is associated with an active plugin.
453 - *
454 - * @author Vova Feldman (@svovaf)
455 - * @since 1.1.6
456 - *
457 - * @global $fs_active_plugins
458 - */
459 - function fs_fallback_to_newest_active_sdk() {
460 - global $fs_active_plugins;
461 -
462 - /**
463 - * @var object $newest_sdk_data
464 - */
465 - $newest_sdk_data = null;
466 - $newest_sdk_path = null;
467 -
468 - foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) {
469 - if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' )
470 - ) {
471 - // If plugin inactive or SDK starter file doesn't exist, remove SDK reference.
472 - if ( 'plugin' === $data->type ) {
473 - $is_module_active = is_plugin_active( $data->plugin_path );
474 - } else {
475 - $active_theme = wp_get_theme();
476 - $is_module_active = ( $data->plugin_path === $active_theme->get_template() );
477 - }
478 -
479 - $is_sdk_exists = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) );
480 -
481 - if ( ! $is_module_active || ! $is_sdk_exists ) {
482 - unset( $fs_active_plugins->plugins[ $sdk_relative_path ] );
483 -
484 - // No need to store the data since it will be stored in fs_update_sdk_newest_version()
485 - // or explicitly with update_option().
486 - } else {
487 - $newest_sdk_data = $data;
488 - $newest_sdk_path = $sdk_relative_path;
489 - }
490 - }
491 - }
492 -
493 - if ( is_null( $newest_sdk_data ) ) {
494 - // Couldn't find any SDK reference.
495 - $fs_active_plugins = new stdClass();
496 - update_option( 'fs_active_plugins', $fs_active_plugins );
497 - } else {
498 - fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path );
499 - }
500 - }
1 +<?php
2 + /**
3 + * IMPORTANT:
4 + * This file will be loaded based on the order of the plugins/themes load.
5 + * If there's a theme and a plugin using Freemius, the plugin's essential
6 + * file will always load first.
7 + *
8 + * @package Freemius
9 + * @copyright Copyright (c) 2015, Freemius, Inc.
10 + * @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3
11 + * @since 1.1.5
12 + */
13 + if ( ! defined( 'ABSPATH' ) ) {
14 + exit;
15 + }
16 +
17 + if ( ! function_exists( 'fs_normalize_path' ) ) {
18 + if ( function_exists( 'wp_normalize_path' ) ) {
19 + /**
20 + * Normalize a filesystem path.
21 + *
22 + * Replaces backslashes with forward slashes for Windows systems, and ensures
23 + * no duplicate slashes exist.
24 + *
25 + * @param string $path Path to normalize.
26 + *
27 + * @return string Normalized path.
28 + */
29 + function fs_normalize_path( $path ) {
30 + return wp_normalize_path( $path );
31 + }
32 + } else {
33 + function fs_normalize_path( $path ) {
34 + $path = str_replace( '\\', '/', $path );
35 + $path = preg_replace( '|/+|', '/', $path );
36 +
37 + return $path;
38 + }
39 + }
40 + }
41 +
42 + require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-2.2.1.php';
43 +
44 + #region Core Redirect (copied from BuddyPress) -----------------------------------------
45 +
46 + if ( ! function_exists( 'fs_redirect' ) ) {
47 + /**
48 + * Redirects to another page, with a workaround for the IIS Set-Cookie bug.
49 + *
50 + * @link http://support.microsoft.com/kb/q176113/
51 + * @since 1.5.1
52 + * @uses apply_filters() Calls 'wp_redirect' hook on $location and $status.
53 + *
54 + * @param string $location The path to redirect to.
55 + * @param bool $exit If true, exit after redirect (Since 1.2.1.5).
56 + * @param int $status Status code to use.
57 + *
58 + * @return bool False if $location is not set
59 + */
60 + function fs_redirect( $location, $exit = true, $status = 302 ) {
61 + global $is_IIS;
62 +
63 + $file = '';
64 + $line = '';
65 + if ( headers_sent($file, $line) ) {
66 + if ( WP_FS__DEBUG_SDK && class_exists( 'FS_Admin_Notices' ) ) {
67 + $notices = FS_Admin_Notices::instance( 'global' );
68 +
69 + $notices->add( "Freemius failed to redirect the page because the headers have been already sent from line <b><code>{$line}</code></b> in file <b><code>{$file}</code></b>. If it's unexpected, it usually happens due to invalid space and/or EOL character(s).", 'Oops...', 'error' );
70 + }
71 +
72 + return false;
73 + }
74 +
75 + if ( defined( 'DOING_AJAX' ) ) {
76 + // Don't redirect on AJAX calls.
77 + return false;
78 + }
79 +
80 + if ( ! $location ) // allows the wp_redirect filter to cancel a redirect
81 + {
82 + return false;
83 + }
84 +
85 + $location = fs_sanitize_redirect( $location );
86 +
87 + if ( $is_IIS ) {
88 + header( "Refresh: 0;url=$location" );
89 + } else {
90 + if ( php_sapi_name() != 'cgi-fcgi' ) {
91 + status_header( $status );
92 + } // This causes problems on IIS and some FastCGI setups
93 + header( "Location: $location" );
94 + }
95 +
96 + if ( $exit ) {
97 + exit();
98 + }
99 +
100 + return true;
101 + }
102 +
103 + if ( ! function_exists( 'fs_sanitize_redirect' ) ) {
104 + /**
105 + * Sanitizes a URL for use in a redirect.
106 + *
107 + * @since 2.3
108 + *
109 + * @param string $location
110 + *
111 + * @return string redirect-sanitized URL
112 + */
113 + function fs_sanitize_redirect( $location ) {
114 + $location = preg_replace( '|[^a-z0-9-~+_.?#=&;,/:%!]|i', '', $location );
115 + $location = fs_kses_no_null( $location );
116 +
117 + // remove %0d and %0a from location
118 + $strip = array( '%0d', '%0a' );
119 + $found = true;
120 + while ( $found ) {
121 + $found = false;
122 + foreach ( (array) $strip as $val ) {
123 + while ( strpos( $location, $val ) !== false ) {
124 + $found = true;
125 + $location = str_replace( $val, '', $location );
126 + }
127 + }
128 + }
129 +
130 + return $location;
131 + }
132 + }
133 +
134 + if ( ! function_exists( 'fs_kses_no_null' ) ) {
135 + /**
136 + * Removes any NULL characters in $string.
137 + *
138 + * @since 1.0.0
139 + *
140 + * @param string $string
141 + *
142 + * @return string
143 + */
144 + function fs_kses_no_null( $string ) {
145 + $string = preg_replace( '/\0+/', '', $string );
146 + $string = preg_replace( '/(\\\\0)+/', '', $string );
147 +
148 + return $string;
149 + }
150 + }
151 + }
152 +
153 + #endregion Core Redirect (copied from BuddyPress) -----------------------------------------
154 +
155 + if ( ! function_exists( 'fs_get_ip' ) ) {
156 + /**
157 + * Get server IP.
158 + *
159 + * @since 2.5.1 This method returns the server IP.
160 + *
161 + * @author Vova Feldman (@svovaf)
162 + * @since 1.1.2
163 + *
164 + * @return string|null
165 + */
166 + function fs_get_ip() {
167 + return empty( $_SERVER[ 'SERVER_ADDR' ] ) ?
168 + null :
169 + $_SERVER[ 'SERVER_ADDR' ];
170 + }
171 + }
172 +
173 + if ( ! function_exists( 'fs_find_caller_plugin_file' ) ) {
174 + /**
175 + * Leverage backtrace to find caller plugin main file path.
176 + *
177 + * @author Vova Feldman (@svovaf)
178 + * @since 1.0.6
179 + *
180 + * @return string
181 + */
182 + function fs_find_caller_plugin_file() {
183 + /**
184 + * All the code below will be executed once on activation.
185 + * If the user changes the main plugin's file name, the file_exists()
186 + * will catch it.
187 + */
188 + if ( ! function_exists( 'get_plugins' ) ) {
189 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
190 + }
191 +
192 + $all_plugins = fs_get_plugins( true );
193 + $all_plugins_paths = array();
194 +
195 + // Get active plugin's main files real full names (might be symlinks).
196 + foreach ( $all_plugins as $relative_path => $data ) {
197 + $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) );
198 + }
199 +
200 + $plugin_file = null;
201 + for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) {
202 + if ( empty( $bt[ $i ]['file'] ) ) {
203 + continue;
204 + }
205 +
206 + if ( in_array( fs_normalize_path( $bt[ $i ]['file'] ), $all_plugins_paths ) ) {
207 + $plugin_file = $bt[ $i ]['file'];
208 + break;
209 + }
210 + }
211 +
212 + if ( is_null( $plugin_file ) ) {
213 + // Throw an error to the developer in case of some edge case dev environment.
214 + wp_die(
215 + 'Freemius SDK couldn\'t find the plugin\'s main file. Please contact [email protected] with the current error.',
216 + 'Error',
217 + array( 'back_link' => true )
218 + );
219 + }
220 +
221 + return $plugin_file;
222 + }
223 + }
224 +
225 + require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-1.1.7.1.php';
226 +
227 + if ( ! function_exists( 'fs_update_sdk_newest_version' ) ) {
228 + /**
229 + * Update SDK newest version reference.
230 + *
231 + * @author Vova Feldman (@svovaf)
232 + * @since 1.1.6
233 + *
234 + * @param string $sdk_relative_path
235 + * @param string|bool $plugin_file
236 + *
237 + * @global $fs_active_plugins
238 + */
239 + function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false ) {
240 + /**
241 + * If there is a plugin running an older version of FS (1.2.1 or below), the `fs_update_sdk_newest_version()`
242 + * function in the older version will be used instead of this one. But since the older version is using
243 + * the `is_plugin_active` function to check if a plugin is active, passing the theme's `plugin_path` to the
244 + * `is_plugin_active` function will return false since the path is not a plugin path, so `in_activation` will be
245 + * `true` for theme modules and the upgrading of the SDK version to 1.2.2 or newer version will work fine.
246 + *
247 + * Future versions that will call this function will use the proper logic here instead of just relying on the
248 + * `is_plugin_active` function to fail for themes.
249 + *
250 + * @author Leo Fajardo (@leorw)
251 + * @since 1.2.2
252 + */
253 +
254 + global $fs_active_plugins;
255 +
256 + $newest_sdk = $fs_active_plugins->plugins[ $sdk_relative_path ];
257 +
258 + if ( ! is_string( $plugin_file ) ) {
259 + $plugin_file = plugin_basename( fs_find_caller_plugin_file() );
260 + }
261 +
262 + if ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) {
263 + if ( ! function_exists( 'is_plugin_active' ) ) {
264 + require_once ABSPATH . 'wp-admin/includes/plugin.php';
265 + }
266 +
267 + $in_activation = ( ! is_plugin_active( $plugin_file ) );
268 + } else {
269 + $theme = wp_get_theme();
270 + $in_activation = ( $newest_sdk->plugin_path == $theme->stylesheet );
271 + }
272 +
273 + $fs_active_plugins->newest = (object) array(
274 + 'plugin_path' => $plugin_file,
275 + 'sdk_path' => $sdk_relative_path,
276 + 'version' => $newest_sdk->version,
277 + 'in_activation' => $in_activation,
278 + 'timestamp' => time(),
279 + );
280 +
281 + // Update DB with latest SDK version and path.
282 + update_option( 'fs_active_plugins', $fs_active_plugins );
283 + }
284 + }
285 +
286 + if ( ! function_exists( 'fs_newest_sdk_plugin_first' ) ) {
287 + /**
288 + * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first.
289 + *
290 + * @author Vova Feldman (@svovaf)
291 + * @since 1.1.6
292 + *
293 + * @return bool Was plugin order changed. Return false if plugin was loaded first anyways.
294 + *
295 + * @global $fs_active_plugins
296 + */
297 + function fs_newest_sdk_plugin_first() {
298 + global $fs_active_plugins;
299 +
300 + /**
301 + * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a plugin activated in the network mode that has an older version of the SDK of another plugin which is site activated that has new SDK version, the fs-essential-functions.php will be loaded from the older SDK. Same thing about MU plugins (loaded even before network activated plugins).
302 + *
303 + * @link https://github.com/Freemius/wordpress-sdk/issues/26
304 + */
305 +
306 + $newest_sdk_plugin_path = $fs_active_plugins->newest->plugin_path;
307 +
308 + $active_plugins = get_option( 'active_plugins', array() );
309 + $updated_active_plugins = array( $newest_sdk_plugin_path );
310 +
311 + $plugin_found = false;
312 + $is_first_path = true;
313 +
314 + foreach ( $active_plugins as $key => $plugin_path ) {
315 + if ( $plugin_path === $newest_sdk_plugin_path ) {
316 + if ( $is_first_path ) {
317 + // if it's the first plugin already, no need to continue
318 + return false;
319 + }
320 +
321 + $plugin_found = true;
322 +
323 + // Skip the plugin (it is already added as the 1st item of $updated_active_plugins).
324 + continue;
325 + }
326 +
327 + $updated_active_plugins[] = $plugin_path;
328 +
329 + if ( $is_first_path ) {
330 + $is_first_path = false;
331 + }
332 + }
333 +
334 + if ( $plugin_found ) {
335 + update_option( 'active_plugins', $updated_active_plugins );
336 +
337 + return true;
338 + }
339 +
340 + if ( is_multisite() ) {
341 + // Plugin is network active.
342 + $network_active_plugins = get_site_option( 'active_sitewide_plugins', array() );
343 +
344 + if ( isset( $network_active_plugins[ $newest_sdk_plugin_path ] ) ) {
345 + reset( $network_active_plugins );
346 + if ( $newest_sdk_plugin_path === key( $network_active_plugins ) ) {
347 + // Plugin is already activated first on the network level.
348 + return false;
349 + } else {
350 + $time = $network_active_plugins[ $newest_sdk_plugin_path ];
351 +
352 + // Remove plugin from its current position.
353 + unset( $network_active_plugins[ $newest_sdk_plugin_path ] );
354 +
355 + // Set it to be included first.
356 + $network_active_plugins = array( $newest_sdk_plugin_path => $time ) + $network_active_plugins;
357 +
358 + update_site_option( 'active_sitewide_plugins', $network_active_plugins );
359 +
360 + return true;
361 + }
362 + }
363 + }
364 +
365 + return false;
366 + }
367 + }
368 +
369 + if ( ! function_exists( 'fs_fallback_to_newest_active_sdk' ) ) {
370 + /**
371 + * Go over all Freemius SDKs in the system and find and "remember"
372 + * the newest SDK which is associated with an active plugin.
373 + *
374 + * @author Vova Feldman (@svovaf)
375 + * @since 1.1.6
376 + *
377 + * @global $fs_active_plugins
378 + */
379 + function fs_fallback_to_newest_active_sdk() {
380 + global $fs_active_plugins;
381 +
382 + /**
383 + * @var object $newest_sdk_data
384 + */
385 + $newest_sdk_data = null;
386 + $newest_sdk_path = null;
387 +
388 + foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) {
389 + if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' )
390 + ) {
391 + // If plugin inactive or SDK starter file doesn't exist, remove SDK reference.
392 + if ( 'plugin' === $data->type ) {
393 + $is_module_active = is_plugin_active( $data->plugin_path );
394 + } else {
395 + $active_theme = wp_get_theme();
396 + $is_module_active = ( $data->plugin_path === $active_theme->get_template() );
397 + }
398 +
399 + $is_sdk_exists = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) );
400 +
401 + if ( ! $is_module_active || ! $is_sdk_exists ) {
402 + unset( $fs_active_plugins->plugins[ $sdk_relative_path ] );
403 +
404 + // No need to store the data since it will be stored in fs_update_sdk_newest_version()
405 + // or explicitly with update_option().
406 + } else {
407 + $newest_sdk_data = $data;
408 + $newest_sdk_path = $sdk_relative_path;
409 + }
410 + }
411 + }
412 +
413 + if ( is_null( $newest_sdk_data ) ) {
414 + // Couldn't find any SDK reference.
415 + $fs_active_plugins = new stdClass();
416 + update_option( 'fs_active_plugins', $fs_active_plugins );
417 + } else {
418 + fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path );
419 + }
420 + }
421 + }