-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathupdater.php
More file actions
337 lines (286 loc) · 9.92 KB
/
updater.php
File metadata and controls
337 lines (286 loc) · 9.92 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
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
<?php
if ( ! class_exists( 'Memberful_Updater' ) ) :
/**
* Base class for kicking off updater functionality.
*
* @since 1.0.0.
*/
class Memberful_Updater {
/**
* The config values for the updater.
*
* @since 1.0.0.
*
* @var array The values to configure the updater.
*/
var $config = array();
/**
* The URL to get product information.
*
* @since 1.0.0.
*
* @var string The URL to get information for products.
*/
var $feed = 'https://yourwebsite.com/product/feed';
/**
* The one instance of Memberful_Updater.
*
* @since 1.0.0.
*
* @var Memberful_Updater
*/
private static $instance;
/**
* Instantiate or return the one Memberful_Updater instance.
*
* @since 1.0.0.
*
* @return Memberful_Updater
*/
public static function instance() {
if ( is_null( self::$instance ) )
self::$instance = new self();
return self::$instance;
}
/**
* Initiate the actions.
*
* @since 1.0.0.
*
* @return Memberful_Updater
*/
public function __construct() {
include untrailingslashit( dirname( __FILE__ ) ) . '/api-key.php';
// Setup the updater config
add_action( 'after_setup_theme', array( $this, 'updater_config' ) );
// Allow manual update checks to be performed
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'pre_set_site_transient_update_plugins' ) );
add_filter( 'pre_set_site_transient_update_themes', array( $this, 'pre_set_site_transient_update_themes' ) );
// Override the requests for the plugin and theme APIs
add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 );
// Reject update if API key is not available
add_action( 'admin_init', array( $this, 'redirect_if_no_key' ) );
// Pass header value to request
add_filter( 'http_request_args', array( $this, 'http_request_args' ), 20, 2 );
}
/**
* Set the config values.
*
* @since 1.0.0.
*
* @return void
*/
public function updater_config() {
$this->config = apply_filters( 'memberful_updater_config', array() );
}
/**
* Perform manual checks on non-wp.org plugins.
*
* @since 1.0.0.
*
* @param object $update The plugin check update object.
* @return object The modified plugin check update object.
*/
public function pre_set_site_transient_update_plugins( $update ) {
if (
isset( $update->response ) &&
isset( $this->config['file'] ) &&
isset( $this->config['slug'] ) &&
isset( $this->config['current_version'] ) &&
( isset( $this->config['type'] ) && 'plugin' === $this->config['type'] )
) {
unset( $update->response[ $this->config['file'] ] );
// Query the feed for data about the plugin or theme
$request = wp_remote_get( $this->feed );
if ( 200 !== (int) wp_remote_retrieve_response_code( $request ) ) {
return $update;
}
$data = (array) json_decode( wp_remote_retrieve_body( $request ) );
// Make sure the desired plugin or theme is available
if ( ! isset( $data[ $this->config['slug'] ] ) ) {
return $update;
}
$this_data = $data[ $this->config['slug'] ];
// Set the appropriate values in the object
if ( isset( $update->checked ) ) {
$update->checked[ $this->config['file'] ] = $this_data->version;
}
if ( 1 === version_compare( $this_data->version, $this->config['current_version'] ) ) {
$update->response[ $this->config['file'] ] = new stdClass();
$update->response[ $this->config['file'] ]->new_version = $this_data->version;
$update->response[ $this->config['file'] ]->url = $this_data->homepage;
$update->response[ $this->config['file'] ]->slug = $this->config['slug'];
$update->response[ $this->config['file'] ]->plugin = $this->config['file'];
$update->response[ $this->config['file'] ]->package = $this->get_download_link();
}
}
return $update;
}
/**
* Perform manual checks on non-wp.org themes.
*
* @since 1.0.0.
*
* @param object $update The theme check update object.
* @return object The modified theme check update object.
*/
public function pre_set_site_transient_update_themes( $update ) {
if (
isset( $update->response ) &&
isset( $this->config['slug'] ) &&
isset( $this->config['current_version'] ) &&
( isset( $this->config['type'] ) && 'theme' === $this->config['type'] )
) {
unset( $update->response[ $this->config['slug'] ] );
// Query the feed for data about the plugin or theme
$request = wp_remote_get( $this->feed );
if ( 200 !== (int) wp_remote_retrieve_response_code( $request ) ) {
return $update;
}
$data = (array) json_decode( wp_remote_retrieve_body( $request ) );
// Make sure the desired plugin or theme is available
if ( ! isset( $data[ $this->config['slug'] ] ) ) {
return $update;
}
$this_data = $data[ $this->config['slug'] ];
// Set the appropriate values in the object
if ( isset( $update->checked ) ) {
$update->checked[ $this->config['slug'] ] = $this_data->version;
}
if ( 1 === version_compare( $this_data->version, $this->config['current_version'] ) ) {
$update->response[ $this->config['slug'] ] = array(
'theme' => $this->config['slug'],
'new_version' => $this_data->version,
'url' => $this_data->homepage,
'package' => $this->get_download_link(),
);
}
}
return $update;
}
/**
* Override the standard plugins API request when updating a certain plugin.
*
* @since 1.0.0.
*
* @param bool $default False allows the default request. Non-false value cancels the default request.
* @param string $action The plugins API request being made. Represents the info being requested.
* @param object $plugin Plugin Info API object.
* @return bool|WP_Error|object False to do nothing; WP_Error if something goes wrong; object if providing other information.
*/
public function plugins_api( $default, $action, $plugin ) {
if ( ( 'plugin_information' !== $action ) || ! isset( $plugin->slug ) || ( $this->config['slug'] !== $plugin->slug ) ) {
return $default;
}
// Query the feed for data about the plugin or theme
$request = wp_remote_get( $this->feed );
if ( 200 !== (int) wp_remote_retrieve_response_code( $request ) ) {
return $default;
}
$data = (array) json_decode( wp_remote_retrieve_body( $request ) );
// Make sure the desired plugin or theme is available
if ( ! isset( $data[ $this->config['slug'] ] ) ) {
return $default;
}
// Grab the data
$plugin = $data[ $this->config['slug'] ];
// Convert object to array
$plugin->sections = (array) $plugin->sections;
// Append the download link
$plugin->download_link = $this->get_download_link();
return $plugin;
}
/**
* Get the download link for the plugin or theme package.
*
* @since 1.0.0.
*
* @return string The URL for the download link.
*/
public function get_download_link() {
if ( isset( $this->config['type'] ) && isset( $this->config['slug'] ) ) {
return 'https://yourwebsite.com/download/' . $this->config['type'] . '/item/' . $this->config['slug'] . '/';
} else {
return '';
}
}
/**
* If the user has no API key, redirect to authenticate.
*
* @since 1.0.0.
*
* @return void
*/
public function redirect_if_no_key() {
global $pagenow;
// Plugin conditions
$single_plugin_update = ( 'update.php' === $pagenow && isset( $_GET['action'] ) && 'upgrade-plugin' === $_GET['action'] && isset( $this->config['file'] ) && isset( $_GET['plugin'] ) && $this->config['file'] === $_GET['plugin'] );
$multiple_plugin_update = ( 'update-core.php' === $pagenow && isset( $_GET['action'] ) && 'do-plugin-upgrade' === $_GET['action'] && isset( $_POST['checked'] ) && isset( $this->config['file'] ) && in_array( $this->config['file'], $_POST['checked'] ) );
// Theme conditions
$single_theme_update = ( 'update.php' === $pagenow && isset( $_GET['action'] ) && 'upgrade-theme' === $_GET['action'] && isset( $_GET['theme'] ) && $this->config['slug'] === $_GET['theme'] );
$multiple_theme_update = ( 'update-core.php' === $pagenow && isset( $_GET['action'] ) && 'do-theme-upgrade' === $_GET['action'] && isset( $_POST['checked'] ) && isset( $this->config['slug'] ) && in_array( $this->config['slug'], $_POST['checked'] ) );
// Only redirect when in the correct context
if ( false === $single_plugin_update && false === $multiple_plugin_update && false === $single_theme_update && false === $multiple_theme_update ) {
return;
}
// Don't redirect if the API key is set
if ( false !== get_option( 'memberful-api-key', false ) ) {
return;
}
// Generate the redirect based on the type
if ( 'plugin' === $this->config['type'] ) {
$redirect = add_query_arg(
array(
'action' => $_GET['action'],
'plugin' => $this->config['file'],
'page' => 'updater_auth_page',
),
admin_url( 'tools.php' )
);
// Redirect to the auth page
wp_safe_redirect( $redirect );
exit();
} else if ( 'theme' === $this->config['type'] ) {
$redirect = add_query_arg(
array(
'action' => $_GET['action'],
'theme' => $this->config['slug'],
'page' => 'updater_auth_page',
),
admin_url( 'tools.php' )
);
// Redirect to the auth page
wp_safe_redirect( $redirect );
exit();
}
}
/**
* Append API key to request as a header.
*
* @since 1.0.0.
*
* @param array $args The default args.
* @param string $url URL for the request.
* @return array Modified args.
*/
public function http_request_args( $args, $url ) {
if ( $url === $this->get_download_link() ) {
$args['headers']['X-Memberful-API-Key'] = get_option( 'memberful-api-key', '' );
}
return $args;
}
}
endif;
if ( ! function_exists( 'memberful_get_updater' ) ) :
/**
* Return the Memberful_Updater instance.
*
* @since 1.0.0.
*
* @return Memberful_Updater
*/
function memberful_get_updater() {
return Memberful_Updater::instance();
}
endif;
memberful_get_updater();