GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( a6186c...4efb95 )
by Chris
9s
created

EDD_SL_Plugin_Updater::show_update_notification()   D

Complexity

Conditions 13
Paths 37

Size

Total Lines 90
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 182

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 13
eloc 48
c 1
b 0
f 0
nc 37
nop 2
dl 0
loc 90
rs 4.9922
ccs 0
cts 52
cp 0
crap 182

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
// uncomment this line for testing
4
//set_site_transient( 'update_plugins', null );
5
6
// Exit if accessed directly
7
if ( ! defined( 'ABSPATH' ) ) exit;
8
9
/**
10
 * Allows plugins to use their own update API.
11
 *
12
 * @author Pippin Williamson
13
 * @version 1.6.4
14
 */
15
class EDD_SL_Plugin_Updater {
16
17
	private $api_url     = '';
18
	private $api_data    = array();
19
	private $name        = '';
20
	private $slug        = '';
21
	private $version     = '';
22
	private $wp_override = false;
23
24
	/**
25
	 * Class constructor.
26
	 *
27
	 * @uses plugin_basename()
28
	 * @uses hook()
29
	 *
30
	 * @param string  $_api_url     The URL pointing to the custom API endpoint.
31
	 * @param string  $_plugin_file Path to the plugin file.
32
	 * @param array   $_api_data    Optional data to send with API calls.
33
	 */
34
	public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
35
36
		global $edd_plugin_data;
37
38
		$this->api_url     = trailingslashit( $_api_url );
39
		$this->api_data    = $_api_data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $_api_data can be null. However, the property $api_data is declared as array. Maybe change the type of the property to array|null or add a type check?

Our type inference engine has found an assignment of a scalar value (like a string, an integer or null) to a property which is an array.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.

To type hint that a parameter can be either an array or null, you can set a type hint of array and a default value of null. The PHP interpreter will then accept both an array or null for that parameter.

function aContainsB(array $needle = null, array  $haystack) {
    if (!$needle) {
        return false;
    }

    return array_intersect($haystack, $needle) == $haystack;
}

The function can be called with either null or an array for the parameter $needle but will only accept an array as $haystack.

Loading history...
40
		$this->name        = plugin_basename( $_plugin_file );
41
		$this->slug        = basename( $_plugin_file, '.php' );
42
		$this->version     = $_api_data['version'];
43
		$this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
44
45
		$edd_plugin_data[ $this->slug ] = $this->api_data;
46
47
		// Set up hooks.
48
		$this->init();
49
50
	}
51
52
	/**
53
	 * Set up WordPress filters to hook into WP's update process.
54
	 *
55
	 * @uses add_filter()
56
	 *
57
	 * @return void
58
	 */
59
	public function init() {
60
61
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
62
		add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
63
		remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10, 2 );
64
		add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
65
		add_action( 'admin_init', array( $this, 'show_changelog' ) );
66
67
	}
68
69
	/**
70
	 * Check for Updates at the defined API endpoint and modify the update array.
71
	 *
72
	 * This function dives into the update API just when WordPress creates its update array,
73
	 * then adds a custom API call and injects the custom plugin data retrieved from the API.
74
	 * It is reassembled from parts of the native WordPress plugin update code.
75
	 * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
76
	 *
77
	 * @uses api_request()
78
	 *
79
	 * @param array   $_transient_data Update array build by WordPress.
80
	 * @return array Modified update array with custom plugin data.
81
	 */
82
	public function check_update( $_transient_data ) {
83
84
		global $pagenow;
85
86
		if ( ! is_object( $_transient_data ) ) {
87
			$_transient_data = new stdClass;
88
		}
89
90
		if ( 'plugins.php' == $pagenow && is_multisite() ) {
91
			return $_transient_data;
92
		}
93
94
		if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
95
			return $_transient_data;
96
		}
97
98
		$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
99
100
		if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
101
102
			if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
103
104
				$_transient_data->response[ $this->name ] = $version_info;
105
106
			}
107
108
			$_transient_data->last_checked           = time();
109
			$_transient_data->checked[ $this->name ] = $this->version;
110
111
		}
112
113
		return $_transient_data;
114
	}
115
116
	/**
117
	 * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
118
	 *
119
	 * @param string  $file
120
	 * @param array   $plugin
121
	 */
122
	public function show_update_notification( $file, $plugin ) {
123
124
		if( ! current_user_can( 'update_plugins' ) ) {
125
			return;
126
		}
127
128
		if( ! is_multisite() ) {
129
			return;
130
		}
131
132
		if ( $this->name != $file ) {
133
			return;
134
		}
135
136
		// Remove our filter on the site transient
137
		remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
138
139
		$update_cache = get_site_transient( 'update_plugins' );
140
141
		$update_cache = is_object( $update_cache ) ? $update_cache : new stdClass();
142
143
		if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
144
145
			$cache_key    = md5( 'edd_plugin_' . sanitize_key( $this->name ) . '_version_info' );
146
			$version_info = get_transient( $cache_key );
147
148
			if( false === $version_info ) {
149
150
				$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
151
152
				set_transient( $cache_key, $version_info, 3600 );
153
			}
154
155
			if( ! is_object( $version_info ) ) {
156
				return;
157
			}
158
159
			if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
160
161
				$update_cache->response[ $this->name ] = $version_info;
162
163
			}
164
165
			$update_cache->last_checked = time();
166
			$update_cache->checked[ $this->name ] = $this->version;
167
168
			set_site_transient( 'update_plugins', $update_cache );
169
170
		} else {
171
172
			$version_info = $update_cache->response[ $this->name ];
173
174
		}
175
176
		// Restore our filter
177
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
178
179
		if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
180
181
			// build a plugin list row, with update notification
182
			$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
183
			echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
184
185
			$changelog_link = self_admin_url( 'index.php?edd_sl_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&TB_iframe=true&width=772&height=911' );
186
187
			if ( empty( $version_info->download_link ) ) {
188
				printf(
189
					__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'easy-digital-downloads' ),
190
					esc_html( $version_info->name ),
191
					'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
192
					esc_html( $version_info->new_version ),
193
					'</a>'
194
				);
195
			} else {
196
				printf(
197
					__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'easy-digital-downloads' ),
198
					esc_html( $version_info->name ),
199
					'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
200
					esc_html( $version_info->new_version ),
201
					'</a>',
202
					'<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',
203
					'</a>'
204
				);
205
			}
206
207
			do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
208
209
			echo '</div></td></tr>';
210
		}
211
	}
212
213
214
	/**
215
	 * Updates information on the "View version x.x details" page with custom data.
216
	 *
217
	 * @uses api_request()
218
	 *
219
	 * @param mixed   $_data
220
	 * @param string  $_action
221
	 * @param object  $_args
222
	 * @return object $_data
223
	 */
224
	public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
225
226
227
		if ( $_action != 'plugin_information' ) {
228
229
			return $_data;
230
231
		}
232
233
		if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
234
235
			return $_data;
236
237
		}
238
239
		$to_send = array(
240
			'slug'   => $this->slug,
241
			'is_ssl' => is_ssl(),
242
			'fields' => array(
243
				'banners' => false, // These will be supported soon hopefully
244
				'reviews' => false
245
			)
246
		);
247
248
		$api_response = $this->api_request( 'plugin_information', $to_send );
249
250
		if ( false !== $api_response ) {
251
			$_data = $api_response;
252
		}
253
254
		return $_data;
255
	}
256
257
258
	/**
259
	 * Disable SSL verification in order to prevent download update failures
260
	 *
261
	 * @param array   $args
262
	 * @param string  $url
263
	 * @return object $array
264
	 */
265
	public function http_request_args( $args, $url ) {
266
		// If it is an https request and we are performing a package download, disable ssl verification
267
		if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
268
			$args['sslverify'] = false;
269
		}
270
		return $args;
271
	}
272
273
	/**
274
	 * Calls the API and, if successfull, returns the object delivered by the API.
275
	 *
276
	 * @uses get_bloginfo()
277
	 * @uses wp_remote_post()
278
	 * @uses is_wp_error()
279
	 *
280
	 * @param string  $_action The requested action.
281
	 * @param array   $_data   Parameters for the API action.
282
	 * @return false|object
283
	 */
284
	private function api_request( $_action, $_data ) {
0 ignored issues
show
Unused Code introduced by
The parameter $_action is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
285
286
		global $wp_version;
287
288
		$data = array_merge( $this->api_data, $_data );
289
290
		if ( $data['slug'] != $this->slug ) {
291
			return;
292
		}
293
294
		if( $this->api_url == trailingslashit (home_url() ) ) {
295
			return false; // Don't allow a plugin to ping itself
296
		}
297
298
		$api_params = array(
299
			'edd_action' => 'get_version',
300
			'license'    => ! empty( $data['license'] ) ? $data['license'] : '',
301
			'item_name'  => isset( $data['item_name'] ) ? $data['item_name'] : false,
302
			'item_id'    => isset( $data['item_id'] ) ? $data['item_id'] : false,
303
			'slug'       => $data['slug'],
304
			'author'     => $data['author'],
305
			'url'        => home_url()
306
		);
307
308
		$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
309
310
		if ( ! is_wp_error( $request ) ) {
311
			$request = json_decode( wp_remote_retrieve_body( $request ) );
312
		}
313
314
		if ( $request && isset( $request->sections ) ) {
315
			$request->sections = maybe_unserialize( $request->sections );
316
		} else {
317
			$request = false;
318
		}
319
320
		return $request;
321
	}
322
323
	public function show_changelog() {
324
325
		global $edd_plugin_data;
326
327
		if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
328
			return;
329
		}
330
331
		if( empty( $_REQUEST['plugin'] ) ) {
332
			return;
333
		}
334
335
		if( empty( $_REQUEST['slug'] ) ) {
336
			return;
337
		}
338
339
		if( ! current_user_can( 'update_plugins' ) ) {
340
			wp_die( __( 'You do not have permission to install plugin updates', 'easy-digital-downloads' ), __( 'Error', 'easy-digital-downloads' ), array( 'response' => 403 ) );
341
		}
342
343
		$data         = $edd_plugin_data[ $_REQUEST['slug'] ];
344
		$cache_key    = md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_version_info' );
345
		$version_info = get_transient( $cache_key );
346
347
		if( false === $version_info ) {
348
349
			$api_params = array(
350
				'edd_action' => 'get_version',
351
				'item_name'  => isset( $data['item_name'] ) ? $data['item_name'] : false,
352
				'item_id'    => isset( $data['item_id'] ) ? $data['item_id'] : false,
353
				'slug'       => $_REQUEST['slug'],
354
				'author'     => $data['author'],
355
				'url'        => home_url()
356
			);
357
358
			$request = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
359
360
			if ( ! is_wp_error( $request ) ) {
361
				$version_info = json_decode( wp_remote_retrieve_body( $request ) );
362
			}
363
364
			if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
365
				$version_info->sections = maybe_unserialize( $version_info->sections );
366
			} else {
367
				$version_info = false;
368
			}
369
370
			set_transient( $cache_key, $version_info, 3600 );
371
372
		}
373
374
		if( ! empty( $version_info ) && isset( $version_info->sections['changelog'] ) ) {
375
			echo '<div style="background:#fff;padding:10px;">' . $version_info->sections['changelog'] . '</div>';
376
		}
377
378
		exit;
379
	}
380
381
}
382