class-update-manager.php
5.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
<?php
if ( ! class_exists( "Yoast_Update_Manager", false ) ) {
class Yoast_Update_Manager {
/**
* @var Yoast_Product
*/
protected $product;
/**
* @var Yoast_License_Manager
*/
protected $license_manager;
/**
* @var string
*/
protected $error_message = '';
/**
* @var object
*/
protected $update_response = null;
/**
* @var string The transient name storing the API response
*/
private $response_transient_key = '';
/**
* @var string The transient name that stores failed request tries
*/
private $request_failed_transient_key = '';
/**
* Constructor
*
* @param Yoast_Product $product The product.
* @param Yoast_License_Manager $license_manager The License Manager.
*/
public function __construct( Yoast_Product $product, $license_manager ) {
$this->product = $product;
$this->license_manager = $license_manager;
// generate transient names
$this->response_transient_key = $this->product->get_transient_prefix() . '-update-response';
$this->request_failed_transient_key = $this->product->get_transient_prefix() . '-update-request-failed';
// maybe delete transient
$this->maybe_delete_transients();
}
/**
* Deletes the various transients
* If we're on the update-core.php?force-check=1 page
*/
private function maybe_delete_transients() {
global $pagenow;
if ( $pagenow === 'update-core.php' && isset( $_GET['force-check'] ) ) {
delete_transient( $this->response_transient_key );
delete_transient( $this->request_failed_transient_key );
}
}
/**
* If the update check returned a WP_Error, show it to the user
*/
public function show_update_error() {
if ( $this->error_message === '' ) {
return;
}
?>
<div class="error">
<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>
</div>
<?php
}
/**
* Calls the API and, if successfull, returns the object delivered by the API.
*
* @uses get_bloginfo()
* @uses wp_remote_post()
* @uses is_wp_error()
*
* @return false||object
*/
private function call_remote_api() {
// only check if the failed transient is not set (or if it's expired)
if ( get_transient( $this->request_failed_transient_key ) !== false ) {
return false;
}
// start request process
global $wp_version;
// set a transient to prevent failed update checks on every page load
// this transient will be removed if a request succeeds
set_transient( $this->request_failed_transient_key, 'failed', 10800 );
// setup api parameters
$api_params = array(
'edd_action' => 'get_version',
'license' => $this->license_manager->get_license_key(),
'item_name' => $this->product->get_item_name(),
'wp_version' => $wp_version,
'item_version' => $this->product->get_version(),
'url' => home_url(),
'slug' => $this->product->get_slug(),
);
// Add product ID from product if it is implemented.
if ( method_exists( $this->product, 'get_product_id' ) ) {
$product_id = $this->product->get_product_id();
if ( $product_id > 0 ) {
$api_params['product_id'] = $this->product->get_product_id();
}
}
// setup request parameters
$request_params = array(
'method' => 'POST',
'body' => $api_params
);
require_once dirname( __FILE__ ) . '/class-api-request.php';
$request = new Yoast_API_Request( $this->product->get_api_url(), $request_params );
if ( $request->is_valid() !== true ) {
// show error message
$this->error_message = $request->get_error_message();
add_action( 'admin_notices', array( $this, 'show_update_error' ) );
return false;
}
// request succeeded, delete transient indicating a request failed
delete_transient( $this->request_failed_transient_key );
// decode response
$response = $request->get_response();
// check if response returned that a given site was inactive
if ( isset( $response->license_check ) && ! empty( $response->license_check ) && $response->license_check != 'valid' ) {
// deactivate local license
$this->license_manager->set_license_status( 'invalid' );
// show notice to let the user know we deactivated his/her license
$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() );
add_action( 'admin_notices', array( $this, 'show_update_error' ) );
}
$response->sections = maybe_unserialize( $response->sections );
// store response
set_transient( $this->response_transient_key, $response, 10800 );
return $response;
}
/**
* Gets the remote product data (from the EDD API)
*
* - If it was previously fetched in the current requests, this gets it from the instance property
* - Next, it tries the 3-hour transient
* - Next, it calls the remote API and stores the result
*
* @return object
*/
protected function get_remote_data() {
// always use property if it's set
if ( null !== $this->update_response ) {
return $this->update_response;
}
// get cached remote data
$data = $this->get_cached_remote_data();
// if cache is empty or expired, call remote api
if ( $data === false ) {
$data = $this->call_remote_api();
}
$this->update_response = $data;
return $data;
}
/**
* Gets the remote product data from a 3-hour transient
*
* @return bool|mixed
*/
private function get_cached_remote_data() {
$data = get_transient( $this->response_transient_key );
if ( $data ) {
return $data;
}
return false;
}
}
}