From 2bef0747e4f9cb0c52899028ea5d91a259041489 Mon Sep 17 00:00:00 2001 From: Laurence Bahiirwa Date: Tue, 10 Sep 2024 16:29:33 +0300 Subject: [PATCH] [static-analysis] Fix rule - Access to an undefined property object . --- includes/class-freemius.php | 31 +++++++++++++------- includes/class-fs-plugin-updater.php | 22 ++++++++++---- includes/fs-essential-functions.php | 3 ++ includes/fs-plugin-info-dialog.php | 22 +++++++++++--- includes/managers/class-fs-cache-manager.php | 9 ++++++ phpstan.neon | 9 ------ start.php | 9 ++++++ templates/plugin-info/features.php | 10 ++++--- 8 files changed, 82 insertions(+), 33 deletions(-) diff --git a/includes/class-freemius.php b/includes/class-freemius.php index abe11a2e..5e54df91 100755 --- a/includes/class-freemius.php +++ b/includes/class-freemius.php @@ -994,10 +994,13 @@ private static function migrate_install_plan_to_plan_id( FS_Storage $storage, $b $module_type = $storage->get_module_type(); $module_slug = $storage->get_module_slug(); + /** + * @var FS_Site[] $installs + */ $installs = self::get_all_sites( $module_type, $blog_id ); $install = isset( $installs[ $module_slug ] ) ? $installs[ $module_slug ] : null; - if ( ! is_object( $install ) ) { + if ( is_null( $install ) ) { return; } @@ -1865,7 +1868,6 @@ private function unregister_uninstall_hook() { */ private function clear_module_main_file_cache( $store_prev_path = true ) { if ( ! isset( $this->_storage->plugin_main_file ) || - ! is_object( $this->_storage->plugin_main_file ) || empty( $this->_storage->plugin_main_file->path ) ) { return; @@ -1882,6 +1884,9 @@ private function clear_module_main_file_cache( $store_prev_path = true ) { */ unset( $this->_storage->plugin_main_file->path ); } else { + /** + * @var stdClass $plugin_main_file + */ $plugin_main_file = clone $this->_storage->plugin_main_file; // Store cached path (2nd layer cache). @@ -17130,12 +17135,14 @@ function opt_in( * @link https://themes.trac.wordpress.org/ticket/46134#comment:9 * @link https://themes.trac.wordpress.org/ticket/46134#comment:12 * @link https://themes.trac.wordpress.org/ticket/46134#comment:14 + * + * @var stdClass $decoded The decoded object is expected to be UserPlugin entity, but since we do not have this Entity in the SDK, we made this a StdClass */ $decoded = is_string( $response['body'] ) ? json_decode( $response['body'] ) : null; - if ( empty( $decoded ) && ! is_object( $decoded ) ) { + if ( ! is_object( $decoded ) ) { return false; } @@ -19595,9 +19602,9 @@ private function _store_site( $store = true, $network_level_or_blog_id = null, F $site = $this->_site; } - if ( ! is_object( $site ) || empty( $site->id ) ) { + // @phpstan-ignore-next-line Variable $site in isset() always exists and is not nullable + if ( !isset( $site ) || !is_object( $site ) || empty( $site->id ) ) { $this->_logger->error( "Empty install ID, can't store site." ); - return; } @@ -20044,7 +20051,11 @@ private function _handle_account_user_sync() { $api = $this->get_api_user_scope(); - // Get user's information. + /** + * Get user's information. + * + * @var FS_User $user + */ $user = $api->get( '/', true ); if ( isset( $user->id ) ) { @@ -20973,7 +20984,7 @@ private function _sync_plugin_license( // Find the current context install. $site = null; - if ( is_array( $result ) ) { + if ( is_object( $result ) && is_array( $result->installs ) ) { foreach ( $result->installs as $install ) { if ( $install->id == $this->_site->id ) { $site = new FS_Site( $install ); @@ -22382,7 +22393,7 @@ private function init_change_owner( $candidate_email, $transfer_type ) { /** * Retrieves all module sites. * - * @return array $all_sites Get all module sites. + * @return array $all_sites */ public static function get_all_modules_sites() { $all_sites = []; @@ -22525,8 +22536,8 @@ private function complete_change_owner() { * @author Leo Fajardo (@leorw) * @since 2.3.2 * - * @param number $user_id - * @param string[]|int[] $install_ids_by_slug_map + * @param number $user_id + * @param array $install_ids_by_slug_map * */ private function complete_ownership_change_by_license( $user_id, $install_ids_by_slug_map ) { diff --git a/includes/class-fs-plugin-updater.php b/includes/class-fs-plugin-updater.php index 9bae5ecb..aae43de1 100755 --- a/includes/class-fs-plugin-updater.php +++ b/includes/class-fs-plugin-updater.php @@ -534,7 +534,8 @@ function pre_set_site_transient_update_plugins_filter( $transient_data ) { return $transient_data; } - if ( defined( 'WP_FS__UNINSTALL_MODE' ) ) { + // @phpstan-ignore-next-line + if ( empty( $transient_data ) || defined( 'WP_FS__UNINSTALL_MODE' ) ) { return $transient_data; } @@ -869,7 +870,7 @@ function delete_update_data() { * @param string $action * @param object $args * - * @return object The plugin information or false on failure. + * @return bool|object The plugin information or false on failure. */ static function _fetch_plugin_info_from_repository( $action, $args ) { $url = $http_url = 'http://api.wordpress.org/plugins/info/1.2/'; @@ -889,7 +890,7 @@ static function _fetch_plugin_info_from_repository( $action, $args ) { $request = wp_remote_get( $url, array( 'timeout' => 15 ) ); if ( is_wp_error( $request ) ) { - return; + return false; } $res = json_decode( wp_remote_retrieve_body( $request ), true ); @@ -900,7 +901,7 @@ static function _fetch_plugin_info_from_repository( $action, $args ) { } if ( ! is_object( $res ) || isset( $res->error ) ) { - return; + return false; } return $res; @@ -1110,7 +1111,11 @@ function plugins_api_filter( $data, $action = '', $args = null ) { if ( ! $plugin_in_repo ) { $data = $args; - // Fetch as much as possible info from local files. + /** + * Fetch as much as possible info from local files. + * + * @var stdClass $data + */ $plugin_local_data = $this->_fs->get_plugin_data(); $data->name = $plugin_local_data['Name']; $data->author = $plugin_local_data['Author']; @@ -1130,7 +1135,12 @@ function plugins_api_filter( $data, $action = '', $args = null ) { $addon_version : $this->_fs->get_plugin_version(); - // Get plugin's newest update. + /** + * Get plugin's newest update. + * + * @var FS_Plugin_Tag $new_version + * @var object $data + */ $new_version = $this->get_latest_download_details( $is_addon ? $addon->id : false, $plugin_version ); if ( ! is_object( $new_version ) || empty( $new_version->version ) ) { diff --git a/includes/fs-essential-functions.php b/includes/fs-essential-functions.php index 189660d6..ffd98e41 100644 --- a/includes/fs-essential-functions.php +++ b/includes/fs-essential-functions.php @@ -250,6 +250,9 @@ function fs_update_sdk_newest_version( $sdk_relative_path, $plugin_file = false global $fs_active_plugins; + /** + * @var stdClass $newest_sdk + */ $newest_sdk = $fs_active_plugins->plugins[ $sdk_relative_path ]; if ( ! is_string( $plugin_file ) ) { diff --git a/includes/fs-plugin-info-dialog.php b/includes/fs-plugin-info-dialog.php index 1d343cfd..04df244f 100755 --- a/includes/fs-plugin-info-dialog.php +++ b/includes/fs-plugin-info-dialog.php @@ -78,9 +78,9 @@ function __construct( Freemius $fs ) { * @author Vova Feldman (@svovaf) * @since 1.0.6 * - * @param array $data - * @param string $action - * @param object|null $args + * @param object|array $data + * @param string $action + * @param object|null $args * * @return array|null */ @@ -188,6 +188,9 @@ function _get_addon_info_filter( $data, $action = '', $args = null ) { $latest = null; + /** + * @var stdClass $data + */ if ( ! $has_paid_plan && $selected_addon->is_wp_org_compliant ) { $repo_data = FS_Plugin_Updater::_fetch_plugin_info_from_repository( 'plugin_information', (object) array( @@ -202,7 +205,6 @@ function _get_addon_info_filter( $data, $action = '', $args = null ) { ) ); if ( ! is_object( $repo_data ) ) { - $data = $repo_data; $data->wp_org_missing = false; } else { // Couldn't find plugin on .org. @@ -535,6 +537,9 @@ private function get_checkout_cta( $api, $plan = false ) { restore_current_blog(); } + /** + * @var stdClass $api + */ return '' . esc_html( ! $plan->has_trial() ? ( @@ -763,6 +768,9 @@ private function get_plugin_actions( $api ) { $download_latest_action = ''; + /** + * @var stdClass $api + */ if ( ! empty( $api->download_link ) && ( $can_download_free_version || $can_download_premium_version ) @@ -1092,6 +1100,7 @@ function install_plugin_information() { /** * @var FS_Plugin_Plan $plan + * @var stdClass $api */ ?> pricing[0] ?> @@ -1310,6 +1319,11 @@ class="fs-annual-discount">

slug ) ?>

    + version ) ) { ?>
  • slug ); ?> diff --git a/includes/managers/class-fs-cache-manager.php b/includes/managers/class-fs-cache-manager.php index 78edd8c8..d1fbb377 100755 --- a/includes/managers/class-fs-cache-manager.php +++ b/includes/managers/class-fs-cache-manager.php @@ -160,6 +160,9 @@ function has_valid( $key, $expiration = null ) { function get( $key, $default = null ) { $this->_logger->entrance( 'key = ' . $key ); + /** + * @var stdClass $cache_entry + */ $cache_entry = $this->_options->get_option( $key, false ); if ( is_object( $cache_entry ) && @@ -184,6 +187,9 @@ function get( $key, $default = null ) { function get_valid( $key, $default = null ) { $this->_logger->entrance( 'key = ' . $key ); + /** + * @var stdClass $cache_entry + */ $cache_entry = $this->_options->get_option( $key, false ); if ( is_object( $cache_entry ) && @@ -271,6 +277,9 @@ function purge( $key ) { function update_expiration( $key, $expiration = WP_FS__TIME_24_HOURS_IN_SEC ) { $this->_logger->entrance( 'key = ' . $key ); + /** + * @var stdClass $cache_entry + */ $cache_entry = $this->_options->get_option( $key, false ); if ( ! is_object( $cache_entry ) || diff --git a/phpstan.neon b/phpstan.neon index 61f6301f..314e3ab1 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -20,12 +20,3 @@ parameters: message: '#Variable \$VARS might not be defined#' paths: - templates/* - - - message: '#Access to an undefined property object#' - paths: - - start.php - - includes/class-freemius.php - - includes/fs-plugin-info-dialog.php - - includes/fs-essential-functions.php - - includes/class-fs-plugin-updater.php - - includes/managers/class-fs-cache-manager.php diff --git a/start.php b/start.php index eab56e26..6e730681 100644 --- a/start.php +++ b/start.php @@ -102,11 +102,17 @@ function_exists( 'wp_is_json_request' ) && $fs_active_plugins = new stdClass(); } + /** + * @var stdClass $fs_active_plugins + */ if ( ! isset( $fs_active_plugins->plugins ) ) { $fs_active_plugins->plugins = array(); } } + /** + * @var stdClass $fs_active_plugins + */ if ( empty( $fs_active_plugins->abspath ) ) { /** * Store the WP install absolute path reference to identify environment change @@ -229,6 +235,9 @@ function_exists( 'wp_is_json_request' ) && $is_newest_sdk_plugin_active = is_plugin_active( $fs_newest_sdk->plugin_path ); } else { $current_theme = wp_get_theme(); + /** + * @var stdClass $fs_newest_sdk + */ $is_newest_sdk_plugin_active = ( $current_theme->stylesheet === $fs_newest_sdk->plugin_path ); $current_theme_parent = $current_theme->parent(); diff --git a/templates/plugin-info/features.php b/templates/plugin-info/features.php index 2702903e..6e91160e 100644 --- a/templates/plugin-info/features.php +++ b/templates/plugin-info/features.php @@ -21,13 +21,15 @@ $features_plan_map = array(); foreach ( $plans as $plan ) { + /** + * @var FS_Plugin_Plan $plan + */ if (!empty($plan->features) && is_array($plan->features)) { foreach ( $plan->features as $feature ) { - $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() ); - - if ( ! empty( $plan->id ) ) { - $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature; + if ( ! isset( $features_plan_map[ $feature->id ] ) ) { + $features_plan_map[ $feature->id ] = array( 'feature' => $feature, 'plans' => array() ); } + $features_plan_map[ $feature->id ]['plans'][ $plan->id ] = $feature; } }