These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
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 { |
||
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 | $this->updates_allowed = Jetpack::is_module_active( 'manage' ); |
||
35 | |||
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 | // Anytime WordPress saves update data, we'll want to update our Jetpack option as well. |
||
46 | if ( is_main_site() ) { |
||
47 | add_action( 'set_site_transient_update_plugins', array( $this, 'save_update_data' ) ); |
||
48 | add_action( 'set_site_transient_update_themes', array( $this, 'save_update_data' ) ); |
||
49 | add_action( 'set_site_transient_update_core', array( $this, 'save_update_data' ) ); |
||
50 | } |
||
51 | |||
52 | } |
||
53 | |||
54 | View Code Duplication | function autoupdate_plugin( $update, $item ) { |
|
55 | $autoupdate_plugin_list = Jetpack_Options::get_option( 'autoupdate_plugins', array() ); |
||
56 | if ( in_array( $item->plugin, $autoupdate_plugin_list ) ) { |
||
57 | $this->expect( $item->plugin ); |
||
58 | return true; |
||
59 | } |
||
60 | |||
61 | return $update; |
||
62 | } |
||
63 | |||
64 | View Code Duplication | function autoupdate_theme( $update, $item ) { |
|
65 | $autoupdate_theme_list = Jetpack_Options::get_option( 'autoupdate_themes', array() ); |
||
66 | if ( in_array( $item->theme , $autoupdate_theme_list) ) { |
||
67 | $this->expect( $item->theme, $type = 'theme' ); |
||
68 | return true; |
||
69 | } |
||
70 | return $update; |
||
71 | } |
||
72 | |||
73 | function autoupdate_core( $update, $item ) { |
||
0 ignored issues
–
show
|
|||
74 | $autoupdate_core = Jetpack_Options::get_option( 'autoupdate_core', false ); |
||
75 | if ( $autoupdate_core ) { |
||
76 | return $autoupdate_core; |
||
77 | } |
||
78 | return $update; |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * Stores the an item identifier to the autoupdate_expected array. |
||
83 | * |
||
84 | * @param string $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme' |
||
85 | * @param string $type 'plugin' or 'theme' |
||
86 | */ |
||
87 | function expect( $item, $type='plugin' ) { |
||
88 | $this->is_updating = true; |
||
89 | $this->autoupdate_expected[ $type ][] = $item; |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * Calculates available updates and saves them to a Jetpack Option |
||
94 | * Update data is saved in the following schema: |
||
95 | * |
||
96 | * array ( |
||
97 | * 'plugins' => (int) number of plugin updates available |
||
98 | * 'themes' => (int) number of theme updates available |
||
99 | * 'wordpress' => (int) number of wordpress core updates available |
||
100 | * 'translations' => (int) number of translation updates available |
||
101 | * 'total' => (int) total of all available updates |
||
102 | * 'wp_version' => (string) the current version of WordPress that is running |
||
103 | * 'wp_update_version' => (string) the latest available version of WordPress, only present if a WordPress update is needed |
||
104 | * 'site_is_version_controlled' => (bool) is the site under version control |
||
105 | * ) |
||
106 | */ |
||
107 | function save_update_data() { |
||
108 | global $wp_version; |
||
109 | |||
110 | $update_data = wp_get_update_data(); |
||
111 | |||
112 | // Stores the individual update counts as well as the total count. |
||
113 | if ( isset( $update_data['counts'] ) ) { |
||
114 | $updates = $update_data['counts']; |
||
115 | } |
||
116 | |||
117 | // Stores the current version of WordPress. |
||
118 | $updates['wp_version'] = $wp_version; |
||
0 ignored issues
–
show
The variable
$updates does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
119 | |||
120 | // If we need to update WordPress core, let's find the latest version number. |
||
121 | View Code Duplication | if ( ! empty( $updates['wordpress'] ) ) { |
|
122 | $cur = get_preferred_from_update_core(); |
||
123 | if ( isset( $cur->response ) && 'upgrade' === $cur->response ) { |
||
124 | $updates['wp_update_version'] = $cur->current; |
||
125 | } |
||
126 | } |
||
127 | |||
128 | $updates['site_is_version_controlled'] = (bool) $this->is_version_controlled(); |
||
129 | Jetpack_Options::update_option( 'updates', $updates ); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Finds out if a site is using a version control system. |
||
134 | * We'll store that information as a transient with a 24 expiration. |
||
135 | * We only need to check once per day. |
||
136 | * |
||
137 | * @return string ( '1' | '0' ) |
||
138 | */ |
||
139 | function is_version_controlled() { |
||
140 | $is_version_controlled = get_transient( 'jetpack_site_is_vcs' ); |
||
141 | |||
142 | if ( false === $is_version_controlled ) { |
||
143 | include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php'; |
||
144 | $updater = new WP_Automatic_Updater(); |
||
145 | $is_version_controlled = strval( $updater->is_vcs_checkout( $context = ABSPATH ) ); |
||
146 | // transients should not be empty |
||
147 | if ( empty( $is_version_controlled ) ) { |
||
148 | $is_version_controlled = '0'; |
||
149 | } |
||
150 | set_transient( 'jetpack_site_is_vcs', $is_version_controlled, DAY_IN_SECONDS ); |
||
151 | } |
||
152 | |||
153 | return $is_version_controlled; |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * On completion of an automatic update, let's store the results. |
||
158 | * |
||
159 | * @param $results - Sent by WP_Automatic_Updater after it completes an autoupdate action. Results may be empty. |
||
160 | */ |
||
161 | function automatic_updates_complete( $results ) { |
||
162 | $this->autoupdate_results = $results; |
||
163 | } |
||
164 | |||
165 | /** |
||
166 | * On shutdown, let's check to see if we've preformed an automatic update. |
||
167 | * If so, let's compare the expected results to the actual results, and log our findings. |
||
168 | * |
||
169 | * Results are logged locally via Jetpack::log(), and globally via Jetpack::do_stats() |
||
170 | */ |
||
171 | function log_results() { |
||
172 | |||
173 | if ( $this->is_updating ) { |
||
174 | |||
175 | $this->jetpack = Jetpack::init(); |
||
176 | $items_to_log = array( 'plugin', 'theme' ); |
||
177 | |||
178 | foreach( $items_to_log as $items ) { |
||
179 | $this->log_items( $items ); |
||
180 | } |
||
181 | |||
182 | $this->jetpack->do_stats( 'server_side' ); |
||
183 | $this->jetpack->log( 'autoupdates', $this->log ); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Iterates through expected items ( plugins or themes ) and compares them to actual results. |
||
189 | * |
||
190 | * @param $items 'plugin' or 'theme' |
||
191 | */ |
||
192 | function log_items( $items ) { |
||
193 | $items_updated = 0; |
||
194 | $items_failed = 0; |
||
195 | $item_results = $this->get_successful_updates( $items ); |
||
196 | |||
197 | foreach( $this->autoupdate_expected[ $items ] as $item ) { |
||
198 | if ( in_array( $item, $item_results ) ) { |
||
199 | $items_updated++; |
||
200 | $this->log[ $items ][ $item ] = true; |
||
201 | } else { |
||
202 | $items_failed++; |
||
203 | $this->log[ $items ][ $item ] = new WP_Error( "$items-fail", $this->get_error_message( $item, $type = $items ) ); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | if ( $items_updated ) { |
||
208 | $this->jetpack->stat( "autoupdates/$items-success", $items_updated ); |
||
209 | } |
||
210 | |||
211 | if ( $items_failed ) { |
||
212 | $this->jetpack->stat( "autoupdates/$items-fail", $items_failed ); |
||
213 | } |
||
214 | |||
215 | } |
||
216 | |||
217 | /** |
||
218 | * Parses the autoupdate results generated by WP_Automatic_Updater and returns a simple array of successful items |
||
219 | * |
||
220 | * @param string $type 'plugin' or 'theme' |
||
221 | * |
||
222 | * @return array |
||
223 | */ |
||
224 | private function get_successful_updates( $type = 'plugin' ) { |
||
225 | $successful_updates = array(); |
||
226 | |||
227 | if ( ! isset( $this->autoupdate_results[ $type ] ) ) { |
||
228 | return $successful_updates; |
||
229 | } |
||
230 | |||
231 | foreach( $this->autoupdate_results[ $type ] as $result ) { |
||
232 | if ( $result->result ) { |
||
233 | View Code Duplication | switch( $type ) { |
|
234 | case 'theme': |
||
235 | $successful_updates[] = $result->item->theme; |
||
236 | break; |
||
237 | default: |
||
238 | $successful_updates[] = $result->item->plugin; |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | return $successful_updates; |
||
244 | } |
||
245 | |||
246 | /** |
||
247 | * Cycles through results generated by WP_Automatic_Updater to find the messages for the given item and item type. |
||
248 | * |
||
249 | * @param $item Example: 'jetpack/jetpack.php' for type 'plugin' or 'twentyfifteen' for type 'theme' |
||
250 | * @param string $type 'plugin' or 'theme' |
||
251 | * |
||
252 | * @return bool|string |
||
253 | */ |
||
254 | private function get_error_message( $item, $type = 'plugin' ) { |
||
255 | if ( ! isset( $this->autoupdate_results[ $type ] ) ) { |
||
256 | return false; |
||
257 | } |
||
258 | foreach( $this->autoupdate_results[ $type ] as $result ) { |
||
259 | View Code Duplication | switch( $type ) { |
|
260 | case 'theme': |
||
261 | $id = $result->item->theme; |
||
262 | break; |
||
263 | default: |
||
264 | $id = $result->item->plugin; |
||
265 | } |
||
266 | if ( $id == $item && isset( $result->messages ) ) { |
||
267 | return implode( ', ', $result->messages ); |
||
268 | } |
||
269 | } |
||
270 | return false; |
||
271 | } |
||
272 | |||
273 | } |
||
274 | Jetpack_Autoupdate::init(); |
This check looks from parameters that have been defined for a function or method, but which are not used in the method body.