Plugin Directory

source: ultimakit-for-wp/tags/1.2.1/src/freemius/includes/fs-essential-functions.php @ 3110582

Last change on this file since 3110582 was 3110582, checked in by ankitmaru, 4 weeks ago

Minor Fixes & Improvements.

File size: 15.0 KB
Line 
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_get_ip' ) ) {
153                /**
154                 * Get server IP.
155         *
156         * @since 2.5.1 This method returns the server IP.
157         *
158                 * @author Vova Feldman (@svovaf)
159                 * @since  1.1.2
160                 *
161                 * @return string|null
162                 */
163                function fs_get_ip() {
164                        return empty( $_SERVER[ 'SERVER_ADDR' ] ) ?
165                null :
166                $_SERVER[ 'SERVER_ADDR' ];
167                }
168        }
169
170    if ( ! function_exists( 'fs_find_caller_plugin_file' ) ) {
171        /**
172         * Leverage backtrace to find caller plugin main file path.
173         *
174             * @author Vova Feldman (@svovaf)
175         * @since  1.0.6
176         *
177             * @return string
178         */
179        function fs_find_caller_plugin_file() {
180            /**
181             * All the code below will be executed once on activation.
182             * If the user changes the main plugin's file name, the file_exists()
183             * will catch it.
184             */
185            if ( ! function_exists( 'get_plugins' ) ) {
186                require_once ABSPATH . 'wp-admin/includes/plugin.php';
187            }
188
189            $all_plugins       = fs_get_plugins( true );
190            $all_plugins_paths = array();
191
192            // Get active plugin's main files real full names (might be symlinks).
193            foreach ( $all_plugins as $relative_path => $data ) {
194                $all_plugins_paths[] = fs_normalize_path( realpath( WP_PLUGIN_DIR . '/' . $relative_path ) );
195            }
196
197            $plugin_file = null;
198            for ( $i = 1, $bt = debug_backtrace(), $len = count( $bt ); $i < $len; $i ++ ) {
199                if ( empty( $bt[ $i ]['file'] ) ) {
200                    continue;
201                }
202
203                if ( in_array( fs_normalize_path( $bt[ $i ]['file'] ), $all_plugins_paths ) ) {
204                    $plugin_file = $bt[ $i ]['file'];
205                    break;
206                }
207            }
208
209            if ( is_null( $plugin_file ) ) {
210                // Throw an error to the developer in case of some edge case dev environment.
211                wp_die(
212                    'Freemius SDK couldn\'t find the plugin\'s main file. Please contact sdk@freemius.com with the current error.',
213                    'Error',
214                    array( 'back_link' => true )
215                );
216            }
217
218            return $plugin_file;
219        }
220    }
221
222        require_once dirname( __FILE__ ) . '/supplements/fs-essential-functions-1.1.7.1.php';
223
224    if ( ! function_exists( 'fs_update_sdk_newest_version' ) ) {
225        /**
226         * Update SDK newest version reference.
227         *
228         * @author Vova Feldman (@svovaf)
229         * @since  1.1.6
230         *
231         * @param string      $sdk_relative_path
232         * @param string|bool $plugin_file
233         *
234         * @global            $fs_active_plugins
235         */
236        function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false ) {
237            /**
238             * If there is a plugin running an older version of FS (1.2.1 or below), the `fs_update_sdk_newest_version()`
239             * function in the older version will be used instead of this one. But since the older version is using
240             * the `is_plugin_active` function to check if a plugin is active, passing the theme's `plugin_path` to the
241             * `is_plugin_active` function will return false since the path is not a plugin path, so `in_activation` will be
242             * `true` for theme modules and the upgrading of the SDK version to 1.2.2 or newer version will work fine.
243             *
244             * Future versions that will call this function will use the proper logic here instead of just relying on the
245             * `is_plugin_active` function to fail for themes.
246             *
247             * @author Leo Fajardo (@leorw)
248             * @since  1.2.2
249             */
250
251            global $fs_active_plugins;
252
253            $newest_sdk = $fs_active_plugins->plugins[ $sdk_relative_path ];
254
255            if ( ! is_string( $plugin_file ) ) {
256                $plugin_file = plugin_basename( fs_find_caller_plugin_file() );
257            }
258
259            if ( ! isset( $newest_sdk->type ) || 'theme' !== $newest_sdk->type ) {
260                if ( ! function_exists( 'is_plugin_active' ) ) {
261                    require_once ABSPATH . 'wp-admin/includes/plugin.php';
262                }
263
264                $in_activation = ( ! is_plugin_active( $plugin_file ) );
265            } else {
266                $theme         = wp_get_theme();
267                $in_activation = ( $newest_sdk->plugin_path == $theme->stylesheet );
268            }
269
270            $fs_active_plugins->newest = (object) array(
271                'plugin_path'   => $plugin_file,
272                'sdk_path'      => $sdk_relative_path,
273                'version'       => $newest_sdk->version,
274                'in_activation' => $in_activation,
275                'timestamp'     => time(),
276            );
277
278            // Update DB with latest SDK version and path.
279            update_option( 'fs_active_plugins', $fs_active_plugins );
280        }
281    }
282
283    if ( ! function_exists( 'fs_newest_sdk_plugin_first' ) ) {
284        /**
285         * Reorder the plugins load order so the plugin with the newest Freemius SDK is loaded first.
286         *
287         * @author Vova Feldman (@svovaf)
288         * @since  1.1.6
289         *
290         * @return bool Was plugin order changed. Return false if plugin was loaded first anyways.
291         *
292         * @global $fs_active_plugins
293         */
294        function fs_newest_sdk_plugin_first() {
295            global $fs_active_plugins;
296
297            /**
298             * @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).
299             *
300             * @link https://github.com/Freemius/wordpress-sdk/issues/26
301             */
302
303            $newest_sdk_plugin_path = $fs_active_plugins->newest->plugin_path;
304
305            $active_plugins         = get_option( 'active_plugins', array() );
306            $updated_active_plugins = array( $newest_sdk_plugin_path );
307
308            $plugin_found  = false;
309            $is_first_path = true;
310
311            foreach ( $active_plugins as $key => $plugin_path ) {
312                if ( $plugin_path === $newest_sdk_plugin_path ) {
313                    if ( $is_first_path ) {
314                        // if it's the first plugin already, no need to continue
315                        return false;
316                    }
317
318                    $plugin_found = true;
319
320                    // Skip the plugin (it is already added as the 1st item of $updated_active_plugins).
321                    continue;
322                }
323
324                $updated_active_plugins[] = $plugin_path;
325
326                if ( $is_first_path ) {
327                    $is_first_path = false;
328                }
329            }
330
331            if ( $plugin_found ) {
332                update_option( 'active_plugins', $updated_active_plugins );
333
334                return true;
335            }
336
337            if ( is_multisite() ) {
338                // Plugin is network active.
339                $network_active_plugins = get_site_option( 'active_sitewide_plugins', array() );
340
341                if ( isset( $network_active_plugins[ $newest_sdk_plugin_path ] ) ) {
342                    reset( $network_active_plugins );
343                    if ( $newest_sdk_plugin_path === key( $network_active_plugins ) ) {
344                        // Plugin is already activated first on the network level.
345                        return false;
346                    } else {
347                        $time = $network_active_plugins[ $newest_sdk_plugin_path ];
348
349                        // Remove plugin from its current position.
350                        unset( $network_active_plugins[ $newest_sdk_plugin_path ] );
351
352                        // Set it to be included first.
353                        $network_active_plugins = array( $newest_sdk_plugin_path => $time ) + $network_active_plugins;
354
355                        update_site_option( 'active_sitewide_plugins', $network_active_plugins );
356
357                        return true;
358                    }
359                }
360            }
361
362            return false;
363        }
364    }
365
366    if ( ! function_exists( 'fs_fallback_to_newest_active_sdk' ) ) {
367        /**
368         * Go over all Freemius SDKs in the system and find and "remember"
369         * the newest SDK which is associated with an active plugin.
370         *
371         * @author Vova Feldman (@svovaf)
372         * @since  1.1.6
373         *
374         * @global $fs_active_plugins
375         */
376        function fs_fallback_to_newest_active_sdk() {
377            global $fs_active_plugins;
378
379            /**
380             * @var object $newest_sdk_data
381             */
382            $newest_sdk_data = null;
383            $newest_sdk_path = null;
384
385            foreach ( $fs_active_plugins->plugins as $sdk_relative_path => $data ) {
386                if ( is_null( $newest_sdk_data ) || version_compare( $data->version, $newest_sdk_data->version, '>' )
387                ) {
388                    // If plugin inactive or SDK starter file doesn't exist, remove SDK reference.
389                    if ( 'plugin' === $data->type ) {
390                        $is_module_active = is_plugin_active( $data->plugin_path );
391                    } else {
392                        $active_theme     = wp_get_theme();
393                        $is_module_active = ( $data->plugin_path === $active_theme->get_template() );
394                    }
395
396                    $is_sdk_exists = file_exists( fs_normalize_path( WP_PLUGIN_DIR . '/' . $sdk_relative_path . '/start.php' ) );
397
398                    if ( ! $is_module_active || ! $is_sdk_exists ) {
399                        unset( $fs_active_plugins->plugins[ $sdk_relative_path ] );
400
401                        // No need to store the data since it will be stored in fs_update_sdk_newest_version()
402                        // or explicitly with update_option().
403                    } else {
404                        $newest_sdk_data = $data;
405                        $newest_sdk_path = $sdk_relative_path;
406                    }
407                }
408            }
409
410            if ( is_null( $newest_sdk_data ) ) {
411                // Couldn't find any SDK reference.
412                $fs_active_plugins = new stdClass();
413                update_option( 'fs_active_plugins', $fs_active_plugins );
414            } else {
415                fs_update_sdk_newest_version( $newest_sdk_path, $newest_sdk_data->plugin_path );
416            }
417        }
418    }
Note: See TracBrowser for help on using the repository browser.