%PDF- %PDF-
Direktori : /home/t/r/a/tradesc/www/relax/wp-content/plugins/wp-rocket/inc/Engine/Plugin/ |
Current File : /home/t/r/a/tradesc/www/relax/wp-content/plugins/wp-rocket/inc/Engine/Plugin/UpdaterSubscriber.php |
<?php namespace WP_Rocket\Engine\Plugin; use Plugin_Upgrader; use Plugin_Upgrader_Skin; use WP_Error; use WP_Rocket\Event_Management\{Event_Manager, Event_Manager_Aware_Subscriber_Interface}; /** * Manages the plugin updates. */ class UpdaterSubscriber implements Event_Manager_Aware_Subscriber_Interface { use UpdaterApiTools; /** * Full path to the plugin. * * @var string */ private $plugin_file; /** * Current version of the plugin. * * @var string */ private $plugin_version; /** * URL to the plugin provider. * * @var string */ private $vendor_url; /** * URL to contact to get update info. * * @var string */ private $api_url; /** * A list of plugin’s icon URLs. * * @var array { * @type string $2x URL to the High-DPI size (png or jpg). Optional. * @type string $1x URL to the normal icon size (png or jpg). Mandatory. * @type string $svg URL to the svg version of the icon. Optional. * } * @see https://developer.wordpress.org/plugins/wordpress-org/plugin-assets/#plugin-icons */ private $icons; /** * An ID to use when a API request fails. * * @var string */ protected $request_error_id = 'rocket_update_failed'; /** * Name of the transient that caches the update data. * * @var string */ protected $cache_transient_name = 'wp_rocket_update_data'; /** * The WordPress Event Manager * * @var Event_Manager */ protected $event_manager; /** * RenewalNotice instance * * @var RenewalNotice */ private $renewal_notice; /** * Constructor * * @param RenewalNotice $renewal_notice RenewalNotice instance. * * @param array $args { Required arguments to populate the class properties. * @type string $plugin_file Full path to the plugin. * @type string $plugin_version Current version of the plugin. * @type string $vendor_url URL to the plugin provider. * @type string $api_url URL to contact to get update info. * } */ public function __construct( RenewalNotice $renewal_notice, $args ) { foreach ( [ 'plugin_file', 'plugin_version', 'vendor_url', 'api_url', 'icons' ] as $setting ) { if ( isset( $args[ $setting ] ) ) { $this->$setting = $args[ $setting ]; } } $this->renewal_notice = $renewal_notice; } /** * {@inheritdoc} * * @param Event_Manager $event_manager The WordPress Event Manager. */ public function set_event_manager( Event_Manager $event_manager ) { $this->event_manager = $event_manager; } /** * {@inheritdoc} */ public static function get_subscribed_events() { return [ 'http_request_args' => [ 'exclude_rocket_from_wp_updates', 5, 2 ], 'pre_set_site_transient_update_plugins' => 'maybe_add_rocket_update_data', 'deleted_site_transient' => 'maybe_delete_rocket_update_data_cache', 'wp_rocket_loaded' => 'maybe_force_check', 'auto_update_plugin' => [ 'disable_auto_updates', 10, 2 ], 'admin_post_rocket_rollback' => 'rollback', 'upgrader_pre_install' => [ 'upgrade_pre_install_option', 10, 2 ], 'upgrader_post_install' => [ 'upgrade_post_install_option', 10, 2 ], 'after_plugin_row_wp-rocket/wp-rocket.php' => 'display_renewal_notice', 'admin_print_styles-plugins.php' => 'add_expired_styles', ]; } /** * When WP checks plugin versions against the latest versions hosted on WordPress.org, remove WPR from the list. * * @see wp_update_plugins() * * @param array $request An array of HTTP request arguments. * @param string $url The request URL. * @return array Updated array of HTTP request arguments. */ public function exclude_rocket_from_wp_updates( $request, $url ) { if ( ! is_string( $url ) ) { return $request; } if ( ! preg_match( '@^https?://api.wordpress.org/plugins/update-check(/|\?|$)@', $url ) || empty( $request['body']['plugins'] ) ) { // Not a plugin update request. Stop immediately. return $request; } /** * Depending on the API version, the data can have several forms: * - Can be serialized or JSON encoded, * - Can be an object of arrays or an object of objects. */ $is_serialized = is_serialized( $request['body']['plugins'] ); $basename = plugin_basename( $this->plugin_file ); $edited = false; if ( $is_serialized ) { $plugins = maybe_unserialize( $request['body']['plugins'] ); } else { $plugins = json_decode( $request['body']['plugins'] ); } if ( ! empty( $plugins->plugins ) ) { if ( is_object( $plugins->plugins ) ) { if ( isset( $plugins->plugins->$basename ) ) { unset( $plugins->plugins->$basename ); $edited = true; } } elseif ( is_array( $plugins->plugins ) ) { if ( isset( $plugins->plugins[ $basename ] ) ) { unset( $plugins->plugins[ $basename ] ); $edited = true; } } } if ( ! empty( $plugins->active ) ) { $active_is_object = is_object( $plugins->active ); if ( $active_is_object || is_array( $plugins->active ) ) { foreach ( $plugins->active as $key => $plugin_basename ) { if ( $plugin_basename !== $basename ) { continue; } if ( $active_is_object ) { unset( $plugins->active->$key ); } else { unset( $plugins->active[ $key ] ); } $edited = true; break; } } } if ( $edited ) { if ( $is_serialized ) { $request['body']['plugins'] = maybe_serialize( $plugins ); } else { $request['body']['plugins'] = wp_json_encode( $plugins ); } } return $request; } /** * Add WPR update data to the "WP update" transient. * * @param \stdClass $transient_value New value of site transient. * @return \stdClass */ public function maybe_add_rocket_update_data( $transient_value ) { if ( defined( 'WP_INSTALLING' ) ) { return $transient_value; } // Get the remote version data. $remote_data = $this->get_cached_latest_version_data(); if ( is_wp_error( $remote_data ) ) { return $transient_value; } // Make sure the transient value is well formed. if ( ! is_object( $transient_value ) ) { $transient_value = new \stdClass(); } if ( empty( $transient_value->response ) ) { $transient_value->response = []; } if ( empty( $transient_value->checked ) ) { $transient_value->checked = []; } // If a newer version is available, add the update. if ( version_compare( $this->plugin_version, $remote_data->new_version, '<' ) ) { $transient_value->response[ $remote_data->plugin ] = $remote_data; } $transient_value->checked[ $remote_data->plugin ] = $this->plugin_version; return $transient_value; } /** * Delete WPR update data cache when the "WP update" transient is deleted. * * @param string $transient_name Deleted transient name. */ public function maybe_delete_rocket_update_data_cache( $transient_name ) { if ( 'update_plugins' === $transient_name ) { $this->delete_rocket_update_data_cache(); } } /** * If the `rocket_force_update` query arg is set, force WP to refresh the list of plugins to update. */ public function maybe_force_check() { if ( is_string( filter_input( INPUT_GET, 'rocket_force_update' ) ) ) { delete_site_transient( 'update_plugins' ); } } /** * Disable auto-updates for WP Rocket * * @param bool|null $update Whether to update. The value of null is internally used to detect whether nothing has hooked into this filter. * @param object $item The update offer. * @return bool|null */ public function disable_auto_updates( $update, $item ) { if ( isset( $item->plugin ) && ( 'wp-rocket/wp-rocket.php' === $item->plugin ) ) { return false; } return $update; } /** * Get the latest WPR update data from our server. * * @return \stdClass|\WP_Error { * A \WP_Error object on failure. An object on success: * * @type string $slug The plugin slug. * @type string $plugin The plugin base name. * @type string $new_version The plugin new version. * @type string $url URL to the plugin provider. * @type string $package URL to the zip file of the new version. * @type array $icons { * A list of plugin’s icon URLs. * * @type string $2x URL to the High-DPI size (png or jpg). Optional. * @type string $1x URL to the normal icon size (png or jpg). Mandatory. * @type string $svg URL to the svg version of the icon. Optional. * } * } */ public function get_latest_version_data() { $request = wp_remote_get( $this->api_url, [ 'timeout' => 30, ] ); if ( is_wp_error( $request ) ) { return $this->get_request_error( [ 'error_code' => $request->get_error_code(), 'response' => $request->get_error_message(), ] ); } $res = trim( wp_remote_retrieve_body( $request ) ); $code = wp_remote_retrieve_response_code( $request ); if ( 200 !== $code ) { /** * If the response doesn’t have a status 200: it is an error, or there is no new update. */ return $this->get_request_error( [ 'http_code' => $code, 'response' => $res, ] ); } /** * This will match: * - `2.3.4.5-beta1||1.2.3.4-beta2||||||||||||||||||||||||||||||||`: expired license. * - `2.3.4.5-beta1|https://wp-rocket.me/i-should-write-a-funny-thing-here/wp-rocket_1.2.3.4-beta2.zip|1.2.3.4-beta2`: valid license. */ if ( ! preg_match( '@^(?<stable_version>\d+(?:\.\d+){1,3}[^|]*)\|(?<package>(?:http.+\.zip)?)\|(?<user_version>\d+(?:\.\d+){1,3}[^|]*)(?:\|+)?$@', $res, $match ) ) { /** * If the response doesn’t have the right format, it is an error. */ return $this->get_request_error( $res ); } $obj = new \stdClass(); $obj->slug = $this->get_plugin_slug( $this->plugin_file ); $obj->plugin = plugin_basename( $this->plugin_file ); $obj->new_version = $match['user_version']; $obj->url = $this->vendor_url; $obj->package = $match['package']; $obj->stable_version = $match['stable_version']; /** * Filters the WP tested version value * * @since 3.10.7 * * @param string $wp_tested_version WP tested version value. */ $obj->tested = apply_filters( 'rocket_wp_tested_version', WP_ROCKET_WP_VERSION_TESTED ); if ( $this->icons && ! empty( $this->icons['1x'] ) ) { $obj->icons = $this->icons; } return $obj; } /** * Get the cached version of the latest WPR update data. * * @return \stdClass|\WP_Error { * A \WP_Error object on failure. An object on success: * * @type string $slug The plugin slug. * @type string $plugin The plugin base name. * @type string $new_version The plugin new version. * @type string $url URL to the plugin provider. * @type string $package URL to the zip file of the new version. * @type array $icons { * A list of plugin’s icon URLs. * * @type string $2x URL to the High-DPI size (png or jpg). Optional. * @type string $1x URL to the normal icon size (png or jpg). Mandatory. * @type string $svg URL to the svg version of the icon. Optional. * } * } */ public function get_cached_latest_version_data() { static $response; if ( isset( $response ) ) { // "force update" won’t bypass the static cache: only one http request by page load. return $response; } $force_update = is_string( filter_input( INPUT_GET, 'rocket_force_update' ) ); if ( ! $force_update ) { // No "force update": try to get the result from a transient. $response = get_site_transient( $this->cache_transient_name ); if ( $response && is_object( $response ) ) { // Got something in cache. return $response; } } // Get fresh data. $response = $this->get_latest_version_data(); $cache_duration = 12 * HOUR_IN_SECONDS; if ( is_wp_error( $response ) ) { $error_data = $response->get_error_data(); if ( ! empty( $error_data['error_code'] ) ) { // `wp_remote_get()` returned an internal error ('error_code' contains a WP_Error code ). $cache_duration = HOUR_IN_SECONDS; } elseif ( ! empty( $error_data['http_code'] ) && $error_data['http_code'] >= 400 ) { // We got a 4xx or 5xx HTTP error. $cache_duration = 2 * HOUR_IN_SECONDS; } } set_site_transient( $this->cache_transient_name, $response, $cache_duration ); return $response; } /** * Delete WP Rocket update data cache. */ public function delete_rocket_update_data_cache() { delete_site_transient( $this->cache_transient_name ); } /** * Do the rollback * * @since 2.4 */ public function rollback() { if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'rocket_rollback' ) ) { wp_nonce_ays( '' ); } if ( ! current_user_can( 'rocket_manage_options' ) ) { wp_nonce_ays( '' ); } /** * Fires before doing the rollback */ do_action( 'rocket_before_rollback' ); $plugin_transient = get_site_transient( 'update_plugins' ); $plugin_folder = plugin_basename( dirname( WP_ROCKET_FILE ) ); $plugin = $plugin_folder . '/' . basename( WP_ROCKET_FILE ); $plugin_transient->response[ $plugin ] = (object) [ 'slug' => $plugin_folder, 'new_version' => WP_ROCKET_LASTVERSION, 'url' => 'https://wp-rocket.me', 'package' => sprintf( 'https://wp-rocket.me/%s/wp-rocket_%s.zip', get_rocket_option( 'consumer_key' ), WP_ROCKET_LASTVERSION ), ]; $this->event_manager->remove_callback( 'pre_set_site_transient_update_plugins', [ $this, 'maybe_add_rocket_update_data' ] ); set_site_transient( 'update_plugins', $plugin_transient ); require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; // translators: %s is the plugin name. $title = sprintf( __( '%s Update Rollback', 'rocket' ), WP_ROCKET_PLUGIN_NAME ); $nonce = 'upgrade-plugin_' . $plugin; $url = 'update.php?action=upgrade-plugin&plugin=' . rawurlencode( $plugin ); $upgrader_skin = new Plugin_Upgrader_Skin( compact( 'title', 'nonce', 'url', 'plugin' ) ); $upgrader = new Plugin_Upgrader( $upgrader_skin ); add_filter( 'update_plugin_complete_actions', [ $this, 'rollback_add_return_link' ] ); rocket_put_content( WP_CONTENT_DIR . '/advanced-cache.php', '' ); $upgrader->upgrade( $plugin ); wp_die( '', // translators: %s is the plugin name. esc_html( sprintf( __( '%s Update Rollback', 'rocket' ), WP_ROCKET_PLUGIN_NAME ) ), [ 'response' => 200, ] ); } /** * After a rollback has been done, replace the "return to" link by a link pointing to WP Rocket's tools page. * A link to the plugins page is kept in case the plugin is not reactivated correctly. * * @since 3.2.4 * * @param array $update_actions Array of plugin action links. * @return array The array of links where the "return to" link has been replaced. */ public function rollback_add_return_link( $update_actions ) { if ( ! isset( $update_actions['plugins_page'] ) ) { return $update_actions; } $update_actions['plugins_page'] = sprintf( /* translators: 1 and 3 are link openings, 2 is a link closing. */ __( '%1$sReturn to WP Rocket%2$s or %3$sgo to Plugins page%2$s', 'rocket' ), '<a href="' . esc_url( admin_url( 'options-general.php?page=' . WP_ROCKET_PLUGIN_SLUG ) . '#tools' ) . '" target="_parent">', '</a>', '<a href="' . esc_url( admin_url( 'plugins.php' ) ) . '" target="_parent">' ); return $update_actions; } /** * Set plugin option before upgrade. * * @param mixed $return The result of the upgrade process. * @param array $plugin The plugin data. * * @return mixed|WP_Error */ public function upgrade_pre_install_option( $return, $plugin = [] ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.returnFound if ( is_wp_error( $return ) || ! $plugin ) { return $return; } $plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : ''; if ( empty( $plugin ) || 'wp-rocket/wp-rocket.php' !== $plugin ) { return $return; } set_transient( 'wp_rocket_updating', true, MINUTE_IN_SECONDS ); return $return; } /** * Update plugin option after upgrade. * * @param mixed $return The result of the upgrade process. * @param array $plugin The plugin data. * * @return mixed|string|WP_Error */ public function upgrade_post_install_option( $return, $plugin = [] ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.returnFound if ( is_wp_error( $return ) || ! $plugin ) { return $return; } $plugin = isset( $plugin['plugin'] ) ? $plugin['plugin'] : ''; if ( empty( $plugin ) || 'wp-rocket/wp-rocket.php' !== $plugin ) { return $return; } delete_transient( 'wp_rocket_updating' ); return $return; } /** * Displays Renewal notice on the plugins page * * @return void */ public function display_renewal_notice() { $latest_version_data = $this->get_cached_latest_version_data(); if ( is_wp_error( $latest_version_data ) ) { return; } if ( ! isset( $latest_version_data->stable_version ) ) { return; } $this->renewal_notice->renewal_notice( $latest_version_data->stable_version ); } /** * Adds styles for expired banner * * @return void */ public function add_expired_styles() { $latest_version_data = $this->get_cached_latest_version_data(); if ( is_wp_error( $latest_version_data ) ) { return; } if ( ! isset( $latest_version_data->stable_version ) ) { return; } $this->renewal_notice->add_expired_styles( $latest_version_data->stable_version ); } }