diff --git a/includes/class-freemius.php b/includes/class-freemius.php index f91387def..0b6be3220 100755 --- a/includes/class-freemius.php +++ b/includes/class-freemius.php @@ -555,6 +555,18 @@ function _data_migration( $sdk_prev_version, $sdk_version ) { return; } + if ( version_compare( $sdk_prev_version, '1.2.3', '<' ) && + version_compare( $sdk_version, '1.2.3', '>=' ) + ) { + /** + * Starting from version 1.2.3, paths are stored as relative paths and not absolute paths; so when + * upgrading to 1.2.3, make paths relative. + * + * @author Leo Fajardo (@leorw) + */ + $this->make_paths_relative(); + } + if ( version_compare( $sdk_prev_version, '1.1.5', '<' ) && version_compare( $sdk_version, '1.1.5', '>=' ) ) { @@ -578,6 +590,46 @@ function _data_migration( $sdk_prev_version, $sdk_version ) { } } + /** + * Makes paths relative. + * + * @author Leo Fajardo + * @since 1.2.3 + */ + private function make_paths_relative() { + $id_slug_type_path_map = self::$_accounts->get_option( 'id_slug_type_path_map', array() ); + + if ( isset( $id_slug_type_path_map[ $this->_module_id ]['path'] ) ) { + $id_slug_type_path_map[ $this->_module_id ]['path'] = $this->get_relative_path( $id_slug_type_path_map[ $this->_module_id ]['path'] ); + + self::$_accounts->set_option( 'id_slug_type_path_map', $id_slug_type_path_map, true ); + } + + if ( isset( $this->_storage->plugin_main_file ) ) { + $plugin_main_file = $this->_storage->plugin_main_file; + + if ( isset( $plugin_main_file->path ) ) { + $this->_storage->plugin_main_file->path = $this->get_relative_path( $this->_storage->plugin_main_file->path ); + } else if ( isset( $plugin_main_file->prev_path ) ) { + $this->_storage->plugin_main_file->prev_path = $this->get_relative_path( $this->_storage->plugin_main_file->prev_path ); + } + } + + // Remove invalid path that is still associated with the current slug if there's any. + $file_slug_map = self::$_accounts->get_option( 'file_slug_map', array() ); + foreach ( $file_slug_map as $plugin_basename => $slug ) { + if ( $slug === $this->_slug && + $plugin_basename !== $this->_plugin_basename && + ! file_exists( $this->get_absolute_path( $plugin_basename ) ) + ) { + unset( $file_slug_map[ $plugin_basename ] ); + self::$_accounts->set_option( 'file_slug_map', $file_slug_map, true ); + + break; + } + } + } + /** * @author Vova Feldman (@svovaf) * @since 1.2.2.7 @@ -874,8 +926,11 @@ private function _find_caller_plugin_file( $is_init = false ) { // Try to load the cached value of the file path. if ( isset( $this->_storage->plugin_main_file ) ) { $plugin_main_file = $this->_storage->plugin_main_file; - if ( isset( $plugin_main_file->path ) && file_exists( $plugin_main_file->path ) ) { - return $plugin_main_file->path; + if ( isset( $plugin_main_file->path ) ) { + $absolute_path = $this->get_absolute_path( $plugin_main_file->path ); + if ( file_exists( $absolute_path ) ) { + return $absolute_path; + } } } @@ -894,8 +949,9 @@ private function _find_caller_plugin_file( $is_init = false ) { if ( isset( $this->_storage->plugin_main_file ) && isset( $this->_storage->plugin_main_file->prev_path ) ) { - if ( file_exists( $this->_storage->plugin_main_file->prev_path ) ) { - return $this->_storage->plugin_main_file->prev_path; + $absolute_path = $this->get_absolute_path( $this->_storage->plugin_main_file->prev_path ); + if ( file_exists( $absolute_path ) ) { + return $absolute_path; } } @@ -918,9 +974,62 @@ private function _find_caller_plugin_file( $is_init = false ) { 'path' => $id_slug_type_path_map[ $this->_module_id ]['path'], ); - return $id_slug_type_path_map[ $this->_module_id ]['path']; + return $this->get_absolute_path( $id_slug_type_path_map[ $this->_module_id ]['path'] ); } + /** + * @author Leo Fajardo (@leorw) + * @since 1.2.3 + * + * @param string $path + * + * @return string + */ + private function get_relative_path( $path ) { + $module_root_dir = $this->get_module_root_dir_path(); + if ( 0 === strpos( $path, $module_root_dir ) ) { + $path = substr( $path, strlen( $module_root_dir ) ); + } + + return $path; + } + + /** + * @author Leo Fajardo (@leorw) + * @since 1.2.3 + * + * @param string $path + * @param string|bool $module_type + * + * @return string + */ + private function get_absolute_path( $path, $module_type = false ) { + $module_root_dir = $this->get_module_root_dir_path( $module_type ); + if ( 0 !== strpos( $path, $module_root_dir ) ) { + $path = fs_normalize_path( $module_root_dir . $path ); + } + + return $path; + } + + /** + * @author Leo Fajardo (@leorw) + * @since 1.2.3 + * + * @param string|bool $module_type + * + * @return string + */ + private function get_module_root_dir_path( $module_type = false ) { + $is_plugin = empty( $module_type ) ? + $this->is_plugin() : + ( WP_FS__MODULE_TYPE_PLUGIN === $module_type ); + + return fs_normalize_path( trailingslashit( $is_plugin ? + WP_PLUGIN_DIR : + get_theme_root() ) ); + } + /** * @author Leo Fajardo (@leorw) * @@ -950,7 +1059,10 @@ private function store_id_slug_type_path_map( $module_id, $slug ) { * @author Vova Feldman (@svovaf) * @since 1.2.3 */ - ! file_exists( $id_slug_type_path_map[ $module_id ]['path'] ) + ! file_exists( $this->get_absolute_path( + $id_slug_type_path_map[ $module_id ]['path'], + $id_slug_type_path_map[ $module_id ]['type'] + ) ) ) { $caller_main_file_and_type = $this->get_caller_main_file_and_type(); @@ -1041,8 +1153,18 @@ private function get_caller_main_file_and_type() { */ if ( $caller_file_path == fs_normalize_path( realpath( trailingslashit( $themes_dir ) . basename( dirname( $caller_file_path ) ) . '/' . basename( $caller_file_path ) ) ) ) { - $module_type = WP_FS__MODULE_TYPE_THEME; - $caller_file_candidate = $caller_file_path; + $module_type = WP_FS__MODULE_TYPE_THEME; + + /** + * Relative path of the theme, e.g.: + * `my-theme/functions.php` + * + * @author Leo Fajardo (@leorw) + */ + $caller_file_candidate = basename( dirname( $caller_file_path ) ) . + '/' . + basename( $caller_file_path ); + continue; } } @@ -1060,7 +1182,7 @@ private function get_caller_main_file_and_type() { if ( isset( $caller_map[ $caller_file_hash ] ) ) { $module_type = WP_FS__MODULE_TYPE_PLUGIN; - $caller_file_candidate = $caller_map[ $caller_file_hash ]; + $caller_file_candidate = plugin_basename( $caller_map[ $caller_file_hash ] ); } } diff --git a/start.php b/start.php index d76a32717..28b95abd0 100644 --- a/start.php +++ b/start.php @@ -364,11 +364,11 @@ define( 'WP_FS__SDK_VERSION', $this_sdk_version ); } - $plugins_or_theme_dir_path = trailingslashit( $is_theme ? + $plugins_or_theme_dir_path = fs_normalize_path( trailingslashit( $is_theme ? get_theme_root() : - WP_PLUGIN_DIR ); + WP_PLUGIN_DIR ) ); - if ( 0 === strpos( $file_path, fs_normalize_path( $plugins_or_theme_dir_path ) ) ) { + if ( 0 === strpos( $file_path, $plugins_or_theme_dir_path ) ) { // No symlinks } else { /** @@ -384,13 +384,24 @@ is_object( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && ! empty( $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink ) ) { - $sdk_symlink = $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink; - $realpath = realpath( $sdk_symlink ); - - if ( ! is_string( $realpath ) || ! file_exists( $realpath ) ) { - $sdk_symlink = null; - } - } + $sdk_symlink = $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink; + if ( 0 === strpos( $sdk_symlink, $plugins_or_theme_dir_path ) ) { + /** + * Make the symlink path relative. + * + * @author Leo Fajardo (@leorw) + */ + $sdk_symlink = substr( $sdk_symlink, strlen( $plugins_or_theme_dir_path ) ); + + $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; + update_option( 'fs_active_plugins', $fs_active_plugins ); + } + + $realpath = realpath( $plugins_or_theme_dir_path . $sdk_symlink ); + if ( ! is_string( $realpath ) || ! file_exists( $realpath ) ) { + $sdk_symlink = null; + } + } if ( empty( $sdk_symlink ) ) // Has symlinks, therefore, we need to configure WP_FS__DIR based on the symlink. { @@ -401,13 +412,26 @@ while ( '/' !== $partial_path_left && ( false === $realpath || $file_path !== fs_normalize_path( $realpath ) ) ) { - $partial_path_right = trailingslashit( basename( $partial_path_left ) ) . $partial_path_right; - $partial_path_left = dirname( $partial_path_left ); - $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); + $partial_path_right = trailingslashit( basename( $partial_path_left ) ) . $partial_path_right; + $partial_path_left_prev = $partial_path_left; + $partial_path_left = dirname( $partial_path_left_prev ); + + /** + * Avoid infinite loop if for example `$partial_path_left_prev` is `C:/`, in this case, + * `dirname( 'C:/' )` will return `C:/`. + * + * @author Leo Fajardo (@leorw) + */ + if ( $partial_path_left === $partial_path_left_prev ) { + $partial_path_left = ''; + break; + } + + $realpath = realpath( $plugins_or_theme_dir_path . $partial_path_right ); } - if ( '/' !== $partial_path_left ) { - $sdk_symlink = fs_normalize_path( $plugins_or_theme_dir_path . dirname( $partial_path_right ) ); + if ( ! empty( $partial_path_left ) && '/' !== $partial_path_left ) { + $sdk_symlink = fs_normalize_path( dirname( $partial_path_right ) ); // Cache value. if ( isset( $fs_active_plugins->plugins[ $this_sdk_relative_path ] ) && @@ -416,13 +440,12 @@ $fs_active_plugins->plugins[ $this_sdk_relative_path ]->sdk_symlink = $sdk_symlink; update_option( 'fs_active_plugins', $fs_active_plugins ); } - } } if ( ! empty( $sdk_symlink ) ) { // Set SDK dir to the symlink path. - define( 'WP_FS__DIR', $sdk_symlink ); + define( 'WP_FS__DIR', $plugins_or_theme_dir_path . $sdk_symlink ); } }