GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

fs-essential-functions.php ➔ fs_find_caller_plugin_file()   B
last analyzed

Complexity

Conditions 7
Paths 32

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 32
nop 0
dl 0
loc 41
rs 8.3306
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 26 and the first side effect is on line 39.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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 ) {
0 ignored issues
show
Best Practice introduced by
The function fs_normalize_path() has been defined more than once; this definition is ignored, only the first definition in this file (L26-28) is considered.

This check looks for functions that have already been defined in the same file.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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,
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
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
			$in_activation = ( ! is_plugin_active( $plugin_file ) );
348
		} else {
349
			$theme         = wp_get_theme();
350
			$in_activation = ( $newest_sdk->plugin_path == $theme->stylesheet );
351
		}
352
353
		$fs_active_plugins->newest = (object) array(
354
			'plugin_path'   => $plugin_file,
355
			'sdk_path'      => $sdk_relative_path,
356
			'version'       => $newest_sdk->version,
357
			'in_activation' => $in_activation,
358
			'timestamp'     => time(),
359
		);
360
361
		// Update DB with latest SDK version and path.
362
		update_option( 'fs_active_plugins', $fs_active_plugins );
363
	}
364
365
	/**
366
	 * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first.
367
	 *
368
	 * @author Vova Feldman (@svovaf)
369
	 * @since  1.1.6
370
	 *
371
	 * @return bool Was plugin order changed. Return false if plugin was loaded first anyways.
372
	 *
373
	 * @global $fs_active_plugins
374
	 */
375
	function fs_newest_sdk_plugin_first() {
376
        global $fs_active_plugins;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
377
378
        /**
379
         * @todo Multi-site network activated plugin are always loaded prior to site plugins so if there's a 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).
380
         *
381
         * @link https://github.com/Freemius/wordpress-sdk/issues/26
382
         */
383
384
        $newest_sdk_plugin_path = $fs_active_plugins->newest->plugin_path;
385
386
        $active_plugins        = get_option( 'active_plugins', array() );
387
        $newest_sdk_plugin_key = array_search( $newest_sdk_plugin_path, $active_plugins );
388
        if ( 0 === $newest_sdk_plugin_key ) {
389
            // if it's 0 it's the first plugin already, no need to continue
390
            return false;
391
        } else if ( is_numeric( $newest_sdk_plugin_key ) ) {
392
            // Remove plugin from its current position.
393
            array_splice( $active_plugins, $newest_sdk_plugin_key, 1 );
394
395
            // Set it to be included first.
396
            array_unshift( $active_plugins, $newest_sdk_plugin_path );
397
398
            update_option( 'active_plugins', $active_plugins );
399
400
            return true;
401
        } else if ( is_multisite() && false === $newest_sdk_plugin_key ) {
402
            // Plugin is network active.
403
            $network_active_plugins = get_site_option( 'active_sitewide_plugins', array() );
404
405
            if (isset($network_active_plugins[$newest_sdk_plugin_path])) {
406
                reset($network_active_plugins);
407
                if ( $newest_sdk_plugin_path === key($network_active_plugins) ) {
408
                    // Plugin is already activated first on the network level.
409
                    return false;
410
                } else if ( is_numeric( $newest_sdk_plugin_key ) ) {
411
                    $time = $network_active_plugins[$newest_sdk_plugin_path];
412
413
                    // Remove plugin from its current position.
414
                    unset($network_active_plugins[$newest_sdk_plugin_path]);
415
416
                    // Set it to be included first.
417
                    $network_active_plugins = array($newest_sdk_plugin_path => $time) + $network_active_plugins;
418
419
                    update_site_option( 'active_sitewide_plugins', $network_active_plugins );
420
421
                    return true;
422
                }
423
            }
424
        }
425
426
        return false;
427
    }
428
429
	/**
430
	 * Go over all Freemius SDKs in the system and find and "remember"
431
	 * the newest SDK which is associated with an active plugin.
432
	 *
433
	 * @author Vova Feldman (@svovaf)
434
	 * @since  1.1.6
435
	 *
436
	 * @global $fs_active_plugins
437
	 */
438
	function fs_fallback_to_newest_active_sdk() {
439
		global $fs_active_plugins;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
440
441
		/**
442
		 * @var object $newest_sdk_data
443
		 */
444
		$newest_sdk_data = null;
445
		$newest_sdk_path = null;
446
447
		foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) {
448
			if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' )
449
			) {
450
				// If plugin inactive or SDK starter file doesn't exist, remove SDK reference.
451
				if ( 'plugin' === $data->type ) {
452
					$is_module_active = is_plugin_active( $data->plugin_path );
453
				} else {
454
					$active_theme     = wp_get_theme();
455
					$is_module_active = ( $data->plugin_path === $active_theme->get_template() );
456
				}
457
458
				$is_sdk_exists = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) );
459
460
				if ( ! $is_module_active || ! $is_sdk_exists ) {
461
					unset( $fs_active_plugins->plugins[ $sdk_relative_path ] );
462
463
					// No need to store the data since it will be stored in fs_update_sdk_newest_version()
464
					// or explicitly with update_option().
465
				} else {
466
					$newest_sdk_data = $data;
467
					$newest_sdk_path = $sdk_relative_path;
468
				}
469
			}
470
		}
471
472
		if ( is_null( $newest_sdk_data ) ) {
473
			// Couldn't find any SDK reference.
474
			$fs_active_plugins = new stdClass();
475
			update_option( 'fs_active_plugins', $fs_active_plugins );
476
		} else {
477
			fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path );
478
		}
479
	}