Completed
Push — update/twenty-sixteen-debugger ( ab952c...f79bf6 )
by
unknown
69:34 queued 59:56
created

Jetpack_Autoupdate::autoupdate_core()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 7
rs 9.4286
nc 2
cc 2
eloc 5
nop 2
1
<?php
2
3
/**
4
 * Handles items that have been selected for automatic updates.
5
 * Hooks into WP_Automatic_Updater
6
 */
7
class Jetpack_Autoupdate {
1 ignored issue
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
8
9
	public $updates_allowed;
10
	public $jetpack;
11
	public $autoupdate_results;
12
	public $is_updating = false;
13
14
	public $autoupdate_expected = array(
15
		'plugin'=> array(),
16
		'theme' => array(),
17
	);
18
19
	public $log = array(
20
		'plugin' => array(),
21
		'theme' => array(),
22
	);
23
24
	private static $instance = null;
25
26
	static function init() {
27
		if ( is_null( self::$instance ) ) {
28
			self::$instance = new Jetpack_Autoupdate;
29
		}
30
		return self::$instance;
31
	}
32
33
	private function __construct() {
34
35
		$this->updates_allowed = Jetpack::is_module_active( 'manage' );
36
		// Only run automatic updates if a user as opted in by activating the manage module.
37
		if ( $this->updates_allowed ) {
38
			add_filter( 'auto_update_plugin',  array( $this, 'autoupdate_plugin' ), 10, 2 );
39
			add_filter( 'auto_update_theme',   array( $this, 'autoupdate_theme' ), 10, 2 );
40
			add_filter( 'auto_update_core',    array( $this, 'autoupdate_core' ), 10, 2 );
41
			add_action( 'automatic_updates_complete', array( $this, 'automatic_updates_complete' ), 10, 1 );
42
			add_action( 'shutdown', array( $this, 'log_results' ) );
43
		}
44
	}
45
46 View Code Duplication
	function autoupdate_plugin( $update, $item ) {
47
		$autoupdate_plugin_list = Jetpack_Options::get_option( 'autoupdate_plugins', array() );
48
		if ( in_array( $item->plugin, $autoupdate_plugin_list ) ) {
49
			$this->expect( $item->plugin );
50
 			return true;
51
		}
52
53
		return $update;
54
	}
55
56 View Code Duplication
	function autoupdate_theme( $update, $item ) {
57
		$autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() );
58
		if ( in_array( $item->theme , $autoupdate_theme_list) ) {
59
			$this->expect( $item->theme, $type = 'theme' );
60
			return true;
61
		}
62
		return $update;
63
	}
64
65
	function autoupdate_core( $update, $item ) {
0 ignored issues
show
Unused Code introduced by
The parameter $item 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...
66
		$autoupdate_core = Jetpack_Options::get_option( 'autoupdate_core', false );
67
		if ( $autoupdate_core ) {
68
			return $autoupdate_core;
69
		}
70
		return $update;
71
	}
72
73
	/**
74
	 * Stores the an item identifier to the autoupdate_expected array.
75
	 *
76
	 * @param string $item  Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme'
77
	 * @param string $type 'plugin' or 'theme'
78
	 */
79
	function expect( $item, $type='plugin' ) {
80
		$this->is_updating = true;
81
		$this->autoupdate_expected[ $type ][] = $item;
82
	}
83
84
	/**
85
	 * On completion of an automatic update, let's store the results.
86
	 *
87
	 * @param $results - Sent by WP_Automatic_Updater after it completes an autoupdate action. Results may be empty.
88
	 */
89
	function automatic_updates_complete( $results ) {
90
		$this->autoupdate_results = $results;
91
	}
92
93
	/**
94
	 * On shutdown, let's check to see if we've preformed an automatic update.
95
	 * If so, let's compare the expected results to the actual results, and log our findings.
96
	 *
97
	 * Results are logged locally via Jetpack::log(), and globally via Jetpack::do_stats()
98
	 */
99
	function log_results() {
100
101
		if ( $this->is_updating ) {
102
103
			$this->jetpack = Jetpack::init();
104
			$items_to_log = array( 'plugin', 'theme' );
105
106
			foreach( $items_to_log as $items ) {
107
				$this->log_items( $items );
108
			}
109
110
			$this->jetpack->do_stats( 'server_side' );
111
			$this->jetpack->log( 'autoupdates', $this->log );
112
		}
113
	}
114
115
	/**
116
	 * Iterates through expected items ( plugins or themes ) and compares them to actual results.
117
	 *
118
	 * @param $items 'plugin' or 'theme'
119
	 */
120
	function log_items( $items ) {
121
		$num_items_updated = 0;
122
		$num_items_failed  = 0;
123
		$item_results      = $this->get_successful_updates( $items );
124
		$items_failed      = array();
125
126
		foreach( $this->autoupdate_expected[ $items ] as $item ) {
127
			if ( in_array( $item, $item_results ) ) {
128
				$num_items_updated++;
129
				$this->log[ $items ][ $item ] = true;
130
			} else {
131
				$num_items_failed++;
132
				$this->log[ $items ][ $item ] = new WP_Error( "$items-fail", $this->get_error_message( $item, $type = $items ) );
133
				$items_failed[] = $item;
134
			}
135
		}
136
137
		if ( $num_items_updated ) {
138
			$this->jetpack->stat( "autoupdates/$items-success", $num_items_updated );
139
		}
140
141
		if ( $num_items_failed ) {
142
			// bump stats
143
			$this->jetpack->stat( "autoupdates/$items-fail", $num_items_failed );
144
			Jetpack::load_xml_rpc_client();
145
			$xml = new Jetpack_IXR_Client( array(
146
				'user_id' => get_current_user_id()
147
			) );
148
			$request = array(
149
				'plugins' => $items_failed,
150
				'blog_id' => Jetpack_Options::get_option( 'id' ),
151
			);
152
			$xml->query( 'jetpack.debug_autoupdate', $request );
153
		}
154
155
	}
156
157
	/**
158
	 * Parses the autoupdate results generated by WP_Automatic_Updater and returns a simple array of successful items
159
	 *
160
	 * @param string $type 'plugin' or 'theme'
161
	 *
162
	 * @return array
163
	 */
164
	private function get_successful_updates( $type = 'plugin' ) {
165
		$successful_updates = array();
166
167
		if ( ! isset( $this->autoupdate_results[ $type ] ) ) {
168
			return $successful_updates;
169
		}
170
171
		foreach( $this->autoupdate_results[ $type ] as $result ) {
172
			if ( $result->result ) {
173 View Code Duplication
				switch( $type ) {
174
					case 'theme':
175
						$successful_updates[] = $result->item->theme;
176
						break;
177
					default:
178
						$successful_updates[] = $result->item->plugin;
179
				}
180
			}
181
		}
182
183
		return $successful_updates;
184
	}
185
186
	/**
187
	 * Cycles through results generated by WP_Automatic_Updater to find the messages for the given item and item type.
188
	 *
189
	 * @param $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme'
190
	 * @param string $type 'plugin' or 'theme'
191
	 *
192
	 * @return bool|string
193
	 */
194
	private function get_error_message( $item, $type = 'plugin' ) {
195
		if ( ! isset( $this->autoupdate_results[ $type ] ) ) {
196
			return false;
197
		}
198
		foreach( $this->autoupdate_results[ $type ] as $result ) {
199 View Code Duplication
			switch( $type ) {
200
				case 'theme':
201
					$id = $result->item->theme;
202
					break;
203
				default:
204
					$id = $result->item->plugin;
205
			}
206
			if ( $id == $item && isset( $result->messages ) ) {
207
				return implode( ', ', $result->messages );
208
			}
209
		}
210
		return false;
211
	}
212
213
}
214
Jetpack_Autoupdate::init();
215