Completed
Push — develop ( c10a82...a5ec11 )
by Zack
07:29
created

EDD_SL_Plugin_Updater::show_changelog()   D

Complexity

Conditions 16
Paths 201

Size

Total Lines 69

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 201
nop 0
dl 0
loc 69
rs 4.7208
c 0
b 0
f 0

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
namespace GV;
3
4
use stdClass;
5
6
/**
7
 * DO NOT MODIFY CODE BELOW.
8
 *
9
 * Note: The translation slug is auto-converted from EDD => GV when the plugin is built with `grunt translate`
10
 */
11
12
// Exit if accessed directly
13
if ( ! defined( 'ABSPATH' ) ) exit;
14
15
/**
16
 * Allows plugins to use their own update API.
17
 *
18
 * @author Easy Digital Downloads
19
 * @version 1.7.1
20
 */
21
class EDD_SL_Plugin_Updater {
22
23
	private $api_url     = '';
24
	private $api_data    = array();
25
	private $name        = '';
26
	private $slug        = '';
27
	private $version     = '';
28
	private $wp_override = false;
29
	private $cache_key   = '';
30
31
	private $health_check_timeout = 5;
32
33
	/**
34
	 * Class constructor.
35
	 *
36
	 * @uses plugin_basename()
37
	 * @uses hook()
38
	 *
39
	 * @param string  $_api_url     The URL pointing to the custom API endpoint.
40
	 * @param string  $_plugin_file Path to the plugin file.
41
	 * @param array   $_api_data    Optional data to send with API calls.
42
	 */
43
	public function __construct( $_api_url, $_plugin_file, $_api_data = null ) {
44
45
		global $edd_plugin_data;
46
47
		$this->api_url     = trailingslashit( $_api_url );
48
		$this->api_data    = $_api_data;
49
		$this->name        = plugin_basename( $_plugin_file );
50
		$this->slug        = basename( $_plugin_file, '.php' );
51
		$this->version     = $_api_data['version'];
52
		$this->wp_override = isset( $_api_data['wp_override'] ) ? (bool) $_api_data['wp_override'] : false;
53
		$this->beta        = ! empty( $this->api_data['beta'] ) ? true : false;
0 ignored issues
show
Bug introduced by
The property beta does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
54
		$this->cache_key   = 'edd_sl_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) );
55
56
		$edd_plugin_data[ $this->slug ] = $this->api_data;
57
58
		/**
59
		 * Fires after the $edd_plugin_data is setup.
60
		 *
61
		 * @since x.x.x
62
		 *
63
		 * @param array $edd_plugin_data Array of EDD SL plugin data.
64
		 */
65
		do_action( 'post_edd_sl_plugin_updater_setup', $edd_plugin_data );
66
67
		// Set up hooks.
68
		$this->init();
69
70
	}
71
72
	/**
73
	 * Set up WordPress filters to hook into WP's update process.
74
	 *
75
	 * @uses add_filter()
76
	 *
77
	 * @return void
78
	 */
79
	public function init() {
80
81
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
82
		add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
83
		remove_action( 'after_plugin_row_' . $this->name, 'wp_plugin_update_row', 10 );
84
		add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
85
		add_action( 'admin_init', array( $this, 'show_changelog' ) );
86
87
	}
88
89
	/**
90
	 * Check for Updates at the defined API endpoint and modify the update array.
91
	 *
92
	 * This function dives into the update API just when WordPress creates its update array,
93
	 * then adds a custom API call and injects the custom plugin data retrieved from the API.
94
	 * It is reassembled from parts of the native WordPress plugin update code.
95
	 * See wp-includes/update.php line 121 for the original wp_update_plugins() function.
96
	 *
97
	 * @uses api_request()
98
	 *
99
	 * @param array   $_transient_data Update array build by WordPress.
100
	 * @return array Modified update array with custom plugin data.
101
	 */
102
	public function check_update( $_transient_data ) {
103
104
		global $pagenow;
105
106
		if ( ! is_object( $_transient_data ) ) {
107
			$_transient_data = new stdClass;
108
		}
109
110
		if ( 'plugins.php' == $pagenow && is_multisite() ) {
111
			return $_transient_data;
112
		}
113
114
		if ( ! empty( $_transient_data->response ) && ! empty( $_transient_data->response[ $this->name ] ) && false === $this->wp_override ) {
115
			return $_transient_data;
116
		}
117
118
		$version_info = $this->get_cached_version_info();
119
120
		if ( false === $version_info ) {
121
			$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
122
123
			$this->set_version_info_cache( $version_info );
124
125
		}
126
127
		if ( false !== $version_info && is_object( $version_info ) && isset( $version_info->new_version ) ) {
128
129
			$no_update = false;
130
			if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
131
132
				$_transient_data->response[ $this->name ] = $version_info;
133
134
				// Make sure the plugin property is set to the plugin's name/location. See issue 1463 on Software Licensing's GitHub repo.
135
				$_transient_data->response[ $this->name ]->plugin = $this->name;
136
137
			} else {
138
				$no_update              = new stdClass();
139
				$no_update->id          = '';
140
				$no_update->slug        = $this->slug;
141
				$no_update->plugin      = $this->name;
142
				$no_update->new_version = $version_info->new_version;
143
				$no_update->url         = $version_info->homepage;
144
				$no_update->package     = $version_info->package;
145
				$no_update->icons       = $version_info->icons;
146
				$no_update->banners     = $version_info->banners;
147
				$no_update->banners_rtl = array();
148
			}
149
150
			$_transient_data->last_checked           = time();
151
			$_transient_data->checked[ $this->name ] = $this->version;
152
153
			if ( $no_update ) {
154
				$_transient_data->no_update[ $this->name ] = $no_update;
155
			}
156
		}
157
158
		return $_transient_data;
159
	}
160
161
	/**
162
	 * show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
163
	 *
164
	 * @param string  $file
165
	 * @param array   $plugin
166
	 */
167
	public function show_update_notification( $file, $plugin ) {
168
169
		if ( is_network_admin() ) {
170
			return;
171
		}
172
173
		if( ! current_user_can( 'update_plugins' ) ) {
174
			return;
175
		}
176
177
		if( ! is_multisite() ) {
178
			return;
179
		}
180
181
		if ( $this->name != $file ) {
182
			return;
183
		}
184
185
		// Remove our filter on the site transient
186
		remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
187
188
		$update_cache = get_site_transient( 'update_plugins' );
189
190
		$update_cache = is_object( $update_cache ) ? $update_cache : new stdClass();
191
192
		if ( empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
193
194
			$version_info = $this->get_cached_version_info();
195
196
			if ( false === $version_info ) {
197
				$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug, 'beta' => $this->beta ) );
198
199
				// Since we disabled our filter for the transient, we aren't running our object conversion on banners, sections, or icons. Do this now:
200
				if ( isset( $version_info->banners ) && ! is_array( $version_info->banners ) ) {
201
					$version_info->banners = $this->convert_object_to_array( $version_info->banners );
202
				}
203
204
				if ( isset( $version_info->sections ) && ! is_array( $version_info->sections ) ) {
205
					$version_info->sections = $this->convert_object_to_array( $version_info->sections );
206
				}
207
208
				if ( isset( $version_info->icons ) && ! is_array( $version_info->icons ) ) {
209
					$version_info->icons = $this->convert_object_to_array( $version_info->icons );
210
				}
211
212
				if ( isset( $version_info->contributors ) && ! is_array( $version_info->contributors ) ) {
213
					$version_info->contributors = $this->convert_object_to_array( $version_info->contributors );
214
				}
215
216
				$this->set_version_info_cache( $version_info );
217
			}
218
219
			if ( ! is_object( $version_info ) ) {
220
				return;
221
			}
222
223
			$no_update = false;
224
			if ( version_compare( $this->version, $version_info->new_version, '<' ) ) {
225
226
				$update_cache->response[ $this->name ] = $version_info;
227
228
			} else {
229
				$no_update              = new stdClass();
230
				$no_update->id          = '';
231
				$no_update->slug        = $this->slug;
232
				$no_update->plugin      = $this->name;
233
				$no_update->new_version = $version_info->new_version;
234
				$no_update->url         = $version_info->homepage;
235
				$no_update->package     = $version_info->package;
236
				$no_update->icons       = $version_info->icons;
237
				$no_update->banners     = $version_info->banners;
238
				$no_update->banners_rtl = array();
239
			}
240
241
			$update_cache->last_checked           = time();
242
			$update_cache->checked[ $this->name ] = $this->version;
243
			if ( $no_update ) {
244
				$update_cache->no_update[ $this->name ] = $no_update;
245
			}
246
247
			set_site_transient( 'update_plugins', $update_cache );
248
249
		} else {
250
251
			$version_info = $update_cache->response[ $this->name ];
252
253
		}
254
255
		// Restore our filter
256
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
257
258
		if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $version_info->new_version, '<' ) ) {
259
260
			// build a plugin list row, with update notification
261
			$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
262
			# <tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange">
263
			echo '<tr class="plugin-update-tr" id="' . $this->slug . '-update" data-slug="' . $this->slug . '" data-plugin="' . $this->slug . '/' . $file . '">';
264
			echo '<td colspan="3" class="plugin-update colspanchange">';
265
			echo '<div class="update-message notice inline notice-warning notice-alt">';
266
267
			$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' );
268
269
			if ( empty( $version_info->download_link ) ) {
270
				printf(
271
					__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s.', 'gravityview' ),
272
					esc_html( $version_info->name ),
273
					'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
274
					esc_html( $version_info->new_version ),
275
					'</a>'
276
				);
277
			} else {
278
				printf(
279
					__( 'There is a new version of %1$s available. %2$sView version %3$s details%4$s or %5$supdate now%6$s.', 'gravityview' ),
280
					esc_html( $version_info->name ),
281
					'<a target="_blank" class="thickbox" href="' . esc_url( $changelog_link ) . '">',
282
					esc_html( $version_info->new_version ),
283
					'</a>',
284
					'<a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) ) .'">',
285
					'</a>'
286
				);
287
			}
288
289
			do_action( "in_plugin_update_message-{$file}", $plugin, $version_info );
290
291
			echo '</div></td></tr>';
292
		}
293
	}
294
295
	/**
296
	 * Updates information on the "View version x.x details" page with custom data.
297
	 *
298
	 * @uses api_request()
299
	 *
300
	 * @param mixed   $_data
301
	 * @param string  $_action
302
	 * @param object  $_args
303
	 * @return object $_data
304
	 */
305
	public function plugins_api_filter( $_data, $_action = '', $_args = null ) {
306
307
		if ( $_action != 'plugin_information' ) {
308
309
			return $_data;
310
311
		}
312
313
		if ( ! isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
314
315
			return $_data;
316
317
		}
318
319
		$to_send = array(
320
			'slug'   => $this->slug,
321
			'is_ssl' => is_ssl(),
322
			'fields' => array(
323
				'banners' => array(),
324
				'reviews' => false,
325
				'icons'   => array(),
326
			)
327
		);
328
329
		// Get the transient where we store the api request for this plugin for 24 hours
330
		$edd_api_request_transient = $this->get_cached_version_info();
331
332
		//If we have no transient-saved value, run the API, set a fresh transient with the API value, and return that value too right now.
333
		if ( empty( $edd_api_request_transient ) ) {
334
335
			$api_response = $this->api_request( 'plugin_information', $to_send );
336
337
			// Expires in 3 hours
338
			$this->set_version_info_cache( $api_response );
339
340
			if ( false !== $api_response ) {
341
				$_data = $api_response;
342
			}
343
344
		} else {
345
			$_data = $edd_api_request_transient;
346
		}
347
348
		// Convert sections into an associative array, since we're getting an object, but Core expects an array.
349
		if ( isset( $_data->sections ) && ! is_array( $_data->sections ) ) {
350
			$_data->sections = $this->convert_object_to_array( $_data->sections );
351
		}
352
353
		// Convert banners into an associative array, since we're getting an object, but Core expects an array.
354
		if ( isset( $_data->banners ) && ! is_array( $_data->banners ) ) {
355
			$_data->banners = $this->convert_object_to_array( $_data->banners );
356
		}
357
358
		// Convert icons into an associative array, since we're getting an object, but Core expects an array.
359
		if ( isset( $_data->icons ) && ! is_array( $_data->icons ) ) {
360
			$_data->icons = $this->convert_object_to_array( $_data->icons );
361
		}
362
363
		// Convert contributors into an associative array, since we're getting an object, but Core expects an array.
364
		if ( isset( $_data->contributors ) && ! is_array( $_data->contributors ) ) {
365
			$_data->contributors = $this->convert_object_to_array( $_data->contributors );
366
		}
367
368
		if( ! isset( $_data->plugin ) ) {
369
			$_data->plugin = $this->name;
370
		}
371
372
		return $_data;
373
	}
374
375
	/**
376
	 * Convert some objects to arrays when injecting data into the update API
377
	 *
378
	 * Some data like sections, banners, and icons are expected to be an associative array, however due to the JSON
379
	 * decoding, they are objects. This method allows us to pass in the object and return an associative array.
380
	 *
381
	 * @since 3.6.5
382
	 *
383
	 * @param stdClass $data
384
	 *
385
	 * @return array
386
	 */
387
	private function convert_object_to_array( $data ) {
388
		$new_data = array();
389
		foreach ( $data as $key => $value ) {
0 ignored issues
show
Bug introduced by
The expression $data of type object<stdClass> is not traversable.
Loading history...
390
			$new_data[ $key ] = is_object( $value ) ? $this->convert_object_to_array( $value ) : $value;
391
		}
392
393
		return $new_data;
394
	}
395
396
	/**
397
	 * Disable SSL verification in order to prevent download update failures
398
	 *
399
	 * @param array   $args
400
	 * @param string  $url
401
	 * @return object $array
402
	 */
403
	public function http_request_args( $args, $url ) {
404
405
		$verify_ssl = $this->verify_ssl();
406
		if ( strpos( $url, 'https://' ) !== false && strpos( $url, 'edd_action=package_download' ) ) {
407
			$args['sslverify'] = $verify_ssl;
408
		}
409
		return $args;
410
411
	}
412
413
	/**
414
	 * Calls the API and, if successfull, returns the object delivered by the API.
415
	 *
416
	 * @uses get_bloginfo()
417
	 * @uses wp_remote_post()
418
	 * @uses is_wp_error()
419
	 *
420
	 * @param string  $_action The requested action.
421
	 * @param array   $_data   Parameters for the API action.
422
	 * @return false|object
423
	 */
424
	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...
425
426
		global $wp_version, $edd_plugin_url_available;
427
428
		$verify_ssl = $this->verify_ssl();
429
430
		// Do a quick status check on this domain if we haven't already checked it.
431
		$store_hash = md5( $this->api_url );
432
		if ( ! is_array( $edd_plugin_url_available ) || ! isset( $edd_plugin_url_available[ $store_hash ] ) ) {
433
			$test_url_parts = parse_url( $this->api_url );
434
435
			$scheme = ! empty( $test_url_parts['scheme'] ) ? $test_url_parts['scheme']     : 'http';
436
			$host   = ! empty( $test_url_parts['host'] )   ? $test_url_parts['host']       : '';
437
			$port   = ! empty( $test_url_parts['port'] )   ? ':' . $test_url_parts['port'] : '';
438
439
			if ( empty( $host ) ) {
440
				$edd_plugin_url_available[ $store_hash ] = false;
441
			} else {
442
				$test_url = $scheme . '://' . $host . $port;
443
				$response = wp_remote_get( $test_url, array( 'timeout' => $this->health_check_timeout, 'sslverify' => $verify_ssl ) );
444
				$edd_plugin_url_available[ $store_hash ] = is_wp_error( $response ) ? false : true;
445
			}
446
		}
447
448
		if ( false === $edd_plugin_url_available[ $store_hash ] ) {
449
			return;
450
		}
451
452
		$data = array_merge( $this->api_data, $_data );
453
454
		if ( $data['slug'] != $this->slug ) {
455
			return;
456
		}
457
458
		if( $this->api_url == trailingslashit ( home_url() ) ) {
459
			return false; // Don't allow a plugin to ping itself
460
		}
461
462
		$api_params = array(
463
			'edd_action' => 'get_version',
464
			'license'    => ! empty( $data['license'] ) ? $data['license'] : '',
465
			'item_name'  => isset( $data['item_name'] ) ? $data['item_name'] : false,
466
			'item_id'    => isset( $data['item_id'] ) ? $data['item_id'] : false,
467
			'version'    => isset( $data['version'] ) ? $data['version'] : false,
468
			'slug'       => $data['slug'],
469
			'author'     => $data['author'],
470
			'url'        => home_url(),
471
			'beta'       => ! empty( $data['beta'] ),
472
		);
473
474
		$request    = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
475
476
		if ( ! is_wp_error( $request ) ) {
477
			$request = json_decode( wp_remote_retrieve_body( $request ) );
478
		}
479
480
		if ( $request && isset( $request->sections ) ) {
481
			$request->sections = maybe_unserialize( $request->sections );
482
		} else {
483
			$request = false;
484
		}
485
486
		if ( $request && isset( $request->banners ) ) {
487
			$request->banners = maybe_unserialize( $request->banners );
488
		}
489
490
		if ( $request && isset( $request->icons ) ) {
491
			$request->icons = maybe_unserialize( $request->icons );
492
		}
493
494
		if( ! empty( $request->sections ) ) {
495
			foreach( $request->sections as $key => $section ) {
496
				$request->$key = (array) $section;
497
			}
498
		}
499
500
		return $request;
501
	}
502
503
	/**
504
	 * If available, show the changelog for sites in a multisite install.
505
	 */
506
	public function show_changelog() {
507
508
		global $edd_plugin_data;
509
510
		if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
511
			return;
512
		}
513
514
		if( empty( $_REQUEST['plugin'] ) ) {
515
			return;
516
		}
517
518
		if( empty( $_REQUEST['slug'] ) ) {
519
			return;
520
		}
521
522
		if( ! current_user_can( 'update_plugins' ) ) {
523
			wp_die( __( 'You do not have permission to install plugin updates', 'gravityview' ), __( 'Error', 'gravityview' ), array( 'response' => 403 ) );
524
		}
525
526
		$data         = $edd_plugin_data[ $_REQUEST['slug'] ];
527
		$version_info = $this->get_cached_version_info();
528
529
		if( false === $version_info ) {
530
531
			$api_params = array(
532
				'edd_action' => 'get_version',
533
				'item_name'  => isset( $data['item_name'] ) ? $data['item_name'] : false,
534
				'item_id'    => isset( $data['item_id'] ) ? $data['item_id'] : false,
535
				'slug'       => $_REQUEST['slug'],
536
				'author'     => $data['author'],
537
				'url'        => home_url(),
538
				'beta'       => ! empty( $data['beta'] )
539
			);
540
541
			$verify_ssl = $this->verify_ssl();
542
			$request    = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
543
544
			if ( ! is_wp_error( $request ) ) {
545
				$version_info = json_decode( wp_remote_retrieve_body( $request ) );
546
			}
547
548
			if ( ! empty( $version_info ) && isset( $version_info->sections ) ) {
549
				$version_info->sections = maybe_unserialize( $version_info->sections );
550
			} else {
551
				$version_info = false;
552
			}
553
554
			if( ! empty( $version_info ) ) {
555
				foreach( $version_info->sections as $key => $section ) {
556
					$version_info->$key = (array) $section;
557
				}
558
			}
559
560
			$this->set_version_info_cache( $version_info );
561
562
			// Delete the unneeded option
563
			delete_option( md5( 'edd_plugin_' . sanitize_key( $_REQUEST['plugin'] ) . '_' . $this->beta . '_version_info' ) );
564
		}
565
566
		if ( isset( $version_info->sections ) ) {
567
			$sections = $this->convert_object_to_array( $version_info->sections );
568
			if ( ! empty( $sections['changelog'] ) ) {
569
				echo '<div style="background:#fff;padding:10px;">' . wp_kses_post( $sections['changelog'] ) . '</div>';
570
			}
571
		}
572
573
		exit;
574
	}
575
576
	/**
577
	 * Gets the plugin's cached version information from the database.
578
	 *
579
	 * @param string $cache_key
580
	 * @return boolean|string
581
	 */
582
	public function get_cached_version_info( $cache_key = '' ) {
583
584
		if( empty( $cache_key ) ) {
585
			$cache_key = $this->cache_key;
586
		}
587
588
		$cache = get_option( $cache_key );
589
590
		if( empty( $cache['timeout'] ) || time() > $cache['timeout'] ) {
591
			return false; // Cache is expired
592
		}
593
594
		// We need to turn the icons into an array, thanks to WP Core forcing these into an object at some point.
595
		$cache['value'] = json_decode( $cache['value'] );
596
		if ( ! empty( $cache['value']->icons ) ) {
597
			$cache['value']->icons = (array) $cache['value']->icons;
598
		}
599
600
		return $cache['value'];
601
602
	}
603
604
	/**
605
	 * Adds the plugin version information to the database.
606
	 *
607
	 * @param string $value
608
	 * @param string $cache_key
609
	 */
610
	public function set_version_info_cache( $value = '', $cache_key = '' ) {
611
612
		if( empty( $cache_key ) ) {
613
			$cache_key = $this->cache_key;
614
		}
615
616
		$data = array(
617
			'timeout' => strtotime( '+3 hours', time() ),
618
			'value'   => json_encode( $value )
619
		);
620
621
		update_option( $cache_key, $data, 'no' );
622
623
		// Delete the duplicate option
624
		delete_option( 'edd_api_request_' . md5( serialize( $this->slug . $this->api_data['license'] . $this->beta ) ) );
625
	}
626
627
	/**
628
	 * Returns if the SSL of the store should be verified.
629
	 *
630
	 * @since  1.6.13
631
	 * @return bool
632
	 */
633
	private function verify_ssl() {
634
		return (bool) apply_filters( 'edd_sl_api_request_verify_ssl', true, $this );
635
	}
636
637
}
638