Completed
Push — master ( d0212e...d16ebc )
by
unknown
19:29 queued 09:04
created

AutoupdateSelf::get_github_data()   B

Complexity

Conditions 7
Paths 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
nc 4
nop 0
dl 0
loc 19
rs 8.8333
c 0
b 0
f 0
1
<?php
2
/**
3
 * Allow the Jetpack Beta plugin to autoupdate itself.
4
 *
5
 * @package automattic/jetpack-beta
6
 */
7
8
namespace Automattic\JetpackBeta;
9
10
use WP_Error;
11
12
/**
13
 * Allow the Jetpack Beta plugin to autoupdate itself.
14
 */
15
class AutoupdateSelf {
16
17
	/**
18
	 * Singleton class instance.
19
	 *
20
	 * @var static
21
	 */
22
	protected static $instance = null;
23
24
	const TRANSIENT_NAME = 'JETPACK_BETA_LATEST_TAG';
25
26
	/**
27
	 * Main Instance
28
	 */
29
	public static function instance() {
30
		if ( null === self::$instance ) {
31
			self::$instance = new self();
32
		}
33
34
		return self::$instance;
35
	}
36
37
	/**
38
	 * Constructor
39
	 */
40
	public function __construct() {
41
		if ( ! empty( self::$instance ) ) {
42
			return;
43
		}
44
45
		$this->config = array(
0 ignored issues
show
Bug introduced by
The property config 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...
46
			'plugin_file'        => JPBETA__PLUGIN_FOLDER . '/jetpack-beta.php',
47
			'slug'               => JPBETA__PLUGIN_FOLDER,
48
			'proper_folder_name' => JPBETA__PLUGIN_FOLDER,
49
			'api_url'            => 'https://api.github.com/repos/Automattic/jetpack-beta',
50
			'github_url'         => 'https://github.com/Automattic/jetpack-beta',
51
			'requires'           => '4.7',
52
			'tested'             => '4.7',
53
		);
54
55
		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'api_check' ) );
56
		add_filter( 'plugins_api', array( $this, 'get_plugin_info' ), 10, 3 );
57
		add_filter( 'upgrader_source_selection', array( $this, 'upgrader_source_selection' ), 10, 3 );
58
59
	}
60
61
	/** Set update arguments */
62
	public function set_update_args() {
63
		$plugin_data                  = $this->get_plugin_data();
64
		$this->config['plugin_name']  = $plugin_data['Name'];
65
		$this->config['version']      = $plugin_data['Version'];
66
		$this->config['author']       = $plugin_data['Author'];
67
		$this->config['homepage']     = $plugin_data['PluginURI'];
68
		$this->config['new_version']  = $this->get_latest_prerelease();
69
		$this->config['last_updated'] = $this->get_date();
70
		$this->config['description']  = $this->get_description();
71
		$this->config['zip_url']      = 'https://github.com/Automattic/jetpack-beta/zipball/' . $this->config['new_version'];
72
	}
73
74
	/** Check for latest pre-release plugin every six hours and update */
75
	public function get_latest_prerelease() {
76
		$tagged_version = get_site_transient( self::TRANSIENT_NAME );
77
		if ( $this->overrule_transients() || empty( $tagged_version ) ) {
78
			$raw_response = wp_remote_get( trailingslashit( $this->config['api_url'] ) . 'releases' );
79
			if ( is_wp_error( $raw_response ) ) {
80
				return false;
81
			}
82
			$releases       = json_decode( $raw_response['body'] );
83
			$tagged_version = false;
84
			if ( is_array( $releases ) ) {
85
				foreach ( $releases as $release ) {
86
					// Since 2.2, so that we don't have to maker the Jetpack Beta 2.0.3 as prerelease.
87
					if ( ! $release->prerelease ) {
88
						$tagged_version = $release->tag_name;
89
						break;
90
					}
91
				}
92
			}
93
			// Refresh every 6 hours.
94
			if ( ! empty( $tagged_version ) ) {
95
				set_site_transient( self::TRANSIENT_NAME, $tagged_version, 60 * 60 * 6 );
96
			}
97
		}
98
		return $tagged_version;
99
	}
100
101
	/** Override transients to force update */
102
	public function overrule_transients() {
103
		return ( defined( 'Jetpack_Beta_FORCE_UPDATE' ) && Jetpack_Beta_FORCE_UPDATE );
104
	}
105
106
	/** Get update data from Github */
107
	public function get_github_data() {
108
		if ( ! empty( $this->github_data ) ) {
109
			$github_data = $this->github_data;
0 ignored issues
show
Bug introduced by
The property github_data 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...
110
		} else {
111
			$github_data = get_site_transient( md5( $this->config['slug'] ) . '_github_data' );
112
			if ( $this->overrule_transients() || ( ! isset( $github_data ) || ! $github_data || '' === $github_data ) ) {
113
				$github_data = wp_remote_get( $this->config['api_url'] );
114
				if ( is_wp_error( $github_data ) ) {
115
					return false;
116
				}
117
				$github_data = json_decode( $github_data['body'] );
118
				// Refresh every 6 hours.
119
				set_site_transient( md5( $this->config['slug'] ) . '_github_data', $github_data, 60 * 60 * 6 );
120
			}
121
			// Store the data in this class instance for future calls.
122
			$this->github_data = $github_data;
123
		}
124
		return $github_data;
125
	}
126
127
	/** Get date of update in GMT*/
128
	public function get_date() {
129
		$_date = $this->get_github_data();
130
		return ! empty( $_date->updated_at ) ? gmdate( 'Y-m-d', strtotime( $_date->updated_at ) ) : false;
131
	}
132
133
	/** Get latest update's description */
134
	public function get_description() {
135
		$_description = $this->get_github_data();
136
		return ! empty( $_description->description ) ? $_description->description : false;
137
	}
138
139
	/** Get plugin update data */
140
	public function get_plugin_data() {
141
		return get_plugin_data( WP_PLUGIN_DIR . '/' . $this->config['plugin_file'] );
142
	}
143
144
	/** Check if there's a newer version */
145
	public function has_never_version() {
146
		if ( ! isset( $this->config['new_version'] ) ) {
147
			$this->set_update_args();
148
		}
149
		return version_compare( $this->config['new_version'], $this->config['version'], '>' );
150
151
	}
152
153
	/**
154
	 * Check the latest transient data and update if necessary.
155
	 *
156
	 * @param string $transient - the transient we're checking.
157
	 */
158
	public function api_check( $transient ) {
159
		// Check if the transient contains the 'checked' information.
160
		// If not, just return its value without hacking it.
161
		if ( ! isset( $transient->no_update ) ) {
162
			return $transient;
163
		}
164
		// Get the latest version.
165
		delete_site_transient( self::TRANSIENT_NAME );
166
167
		if ( $this->has_never_version() ) {
168
			$response = (object) array(
169
				'plugin'      => $this->config['slug'],
170
				'new_version' => $this->config['new_version'],
171
				'slug'        => $this->config['slug'],
172
				'url'         => $this->config['github_url'],
173
				'package'     => $this->config['zip_url'],
174
			);
175
			// If response is false, don't alter the transient.
176
			if ( false !== $response ) {
177
				$transient->response[ $this->config['plugin_file'] ] = $response;
178
			}
179
		}
180
		return $transient;
181
	}
182
183
	/**
184
	 * Get latest plugin information
185
	 *
186
	 * @param string $false Result from plugins_api.
187
	 * @param string $action The type of information being requested from the Plugin Installation API.
188
	 * @param object $response The response from plugins_api.
189
	 */
190
	public function get_plugin_info( $false, $action, $response ) {
191
		// Check if this call API is for the right plugin.
192
		if ( ! isset( $response->slug ) || $response->slug !== $this->config['slug'] ) {
193
			return false;
194
		}
195
		// Update tags.
196
		$this->set_update_args();
197
		$response->slug          = $this->config['slug'];
198
		$response->plugin        = $this->config['slug'];
199
		$response->name          = $this->config['plugin_name'];
200
		$response->plugin_name   = $this->config['plugin_name'];
201
		$response->version       = $this->config['new_version'];
202
		$response->author        = $this->config['author'];
203
		$response->homepage      = $this->config['homepage'];
204
		$response->requires      = $this->config['requires'];
205
		$response->tested        = $this->config['tested'];
206
		$response->downloaded    = 0;
207
		$response->last_updated  = $this->config['last_updated'];
208
		$response->sections      = array( 'description' => $this->config['description'] );
209
		$response->download_link = $this->config['zip_url'];
210
		return $response;
211
	}
212
213
	/**
214
	 * Updates the source file location for the upgrade package.
215
	 *
216
	 * @param string $source - File source location..
217
	 * @param string $remote_source - Remote file source location.
218
	 */
219
	public function upgrader_source_selection( $source, $remote_source ) {
220
		global $wp_filesystem;
221
		if ( strstr( $source, '/Automattic-jetpack-beta-' ) ) {
222
			$corrected_source = trailingslashit( $remote_source ) . trailingslashit( $this->config['proper_folder_name'] );
223
			if ( $wp_filesystem->move( $source, $corrected_source, true ) ) {
224
				return $corrected_source;
225
			} else {
226
				return new WP_Error();
227
			}
228
		}
229
		return $source;
230
	}
231
}
232