3 if( ! class_exists( "Yoast_Update_Manager", false ) ) {
5 class Yoast_Update_Manager {
13 * @var Yoast_License_Manager
15 protected $license_manager;
20 protected $error_message = '';
25 protected $update_response = null;
28 * @var string The transient name storing the API response
30 private $response_transient_key = '';
33 * @var string The transient name that stores failed request tries
35 private $request_failed_transient_key = '';
40 * @param string $api_url The url to the EDD shop
41 * @param string $item_name The item name in the EDD shop
42 * @param string $license_key The (valid) license key
43 * @param string $slug The slug. This is either the plugin main file path or the theme slug.
44 * @param string $version The current plugin or theme version
45 * @param string $author (optional) The item author.
47 public function __construct( Yoast_Product $product, $license_manager ) {
48 $this->product = $product;
49 $this->license_manager = $license_manager;
51 // generate transient names
52 $this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
53 $this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
55 // maybe delete transient
56 $this->maybe_delete_transients();
60 * Deletes the various transients
61 * If we're on the update-core.php?force-check=1 page
63 private function maybe_delete_transients() {
66 if( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
67 delete_transient( $this->response_transient_key );
68 delete_transient( $this->request_failed_transient_key );
73 * If the update check returned a WP_Error, show it to the user
75 public function show_update_error() {
77 if ( $this->error_message === '' ) {
83 <p><?php printf( __( '%s failed to check for updates because of the following error: <em>%s</em>', $this->product->get_text_domain() ), $this->product->get_item_name(), $this->error_message ); ?></p>
89 * Calls the API and, if successfull, returns the object delivered by the API.
91 * @uses get_bloginfo()
92 * @uses wp_remote_post()
95 * @return false||object
97 private function call_remote_api() {
99 // only check if the failed transient is not set (or if it's expired)
100 if( get_transient( $this->request_failed_transient_key ) !== false ) {
104 // start request process
107 // set a transient to prevent failed update checks on every page load
108 // this transient will be removed if a request succeeds
109 set_transient( $this->request_failed_transient_key, 'failed', 10800 );
111 // setup api parameters
113 'edd_action' => 'get_version',
114 'license' => $this->license_manager->get_license_key(),
115 'item_name' => $this->product->get_item_name(),
116 'wp_version' => $wp_version,
117 'item_version' => $this->product->get_version(),
119 'slug' => $this->product->get_slug()
122 // setup request parameters
123 $request_params = array(
125 'body' => $api_params
128 require_once dirname( __FILE__ ) . '/class-api-request.php';
129 $request = new Yoast_API_Request( $this->product->get_api_url(), $request_params );
131 if( $request->is_valid() !== true ) {
133 // show error message
134 $this->error_message = $request->get_error_message();
135 add_action( 'admin_notices', array( $this, 'show_update_error' ) );
140 // request succeeded, delete transient indicating a request failed
141 delete_transient( $this->request_failed_transient_key );
144 $response = $request->get_response();
146 // check if response returned that a given site was inactive
147 if( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
149 // deactivate local license
150 $this->license_manager->set_license_status( 'invalid' );
152 // show notice to let the user know we deactivated his/her license
153 $this->error_message = __( "This site has not been activated properly on yoast.com and thus cannot check for future updates. Please activate your site with a valid license key.", $this->product->get_text_domain() );
154 add_action( 'admin_notices', array( $this, 'show_update_error' ) );
157 $response->sections = maybe_unserialize( $response->sections );
160 set_transient( $this->response_transient_key, $response, 10800 );
166 * Gets the remote product data (from the EDD API)
168 * - If it was previously fetched in the current requests, this gets it from the instance property
169 * - Next, it tries the 3-hour transient
170 * - Next, it calls the remote API and stores the result
174 protected function get_remote_data() {
176 // always use property if it's set
177 if( null !== $this->update_response ) {
178 return $this->update_response;
181 // get cached remote data
182 $data = $this->get_cached_remote_data();
184 // if cache is empty or expired, call remote api
185 if( $data === false ) {
186 $data = $this->call_remote_api();
189 $this->update_response = $data;
194 * Gets the remote product data from a 3-hour transient
198 private function get_cached_remote_data() {
200 $data = get_transient( $this->response_transient_key );