PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.21
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.21
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / central / modules / updates.php

updates.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.21, at central/modules/updates.php

876 lines 30.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('UPDRAFTCENTRAL_CLIENT_DIR')) die('No access.');
4
5 class UpdraftCentral_Updates_Commands extends UpdraftCentral_Commands {
6
7 public function do_updates($updates) {
8
9 if (!is_array($updates)) $this->_generic_error_response('invalid_data');
10
11 if (!empty($updates['plugins']) && !current_user_can('update_plugins')) return $this->_generic_error_response('updates_permission_denied', 'update_plugins');
12
13 if (!empty($updates['themes']) && !current_user_can('update_themes')) return $this->_generic_error_response('updates_permission_denied', 'update_themes');
14
15 if (!empty($updates['core']) && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied', 'update_core');
16
17 if (!empty($updates['translations']) && !$this->user_can_update_translations()) return $this->_generic_error_response('updates_permission_denied', 'update_translations');
18
19 $this->_admin_include('plugin.php', 'update.php', 'file.php', 'template.php');
20 $this->_frontend_include('update.php');
21
22 if (!empty($updates['meta']) && isset($updates['meta']['filesystem_credentials'])) {
23 parse_str($updates['meta']['filesystem_credentials'], $filesystem_credentials);
24 if (is_array($filesystem_credentials)) {
25 foreach ($filesystem_credentials as $key => $value) {
26 // Put them into $_POST, which is where request_filesystem_credentials() checks for them.
27 $_POST[$key] = $value;
28 }
29 }
30 }
31
32 $plugins = empty($updates['plugins']) ? array() : $updates['plugins'];
33 $plugin_updates = array();
34 foreach ($plugins as $plugin_info) {
35 $plugin_updates[] = $this->_update_plugin($plugin_info['plugin'], $plugin_info['slug']);
36 }
37
38 $themes = empty($updates['themes']) ? array() : $updates['themes'];
39 $theme_updates = array();
40 foreach ($themes as $theme_info) {
41 $theme = $theme_info['theme'];
42 $theme_updates[] = $this->_update_theme($theme);
43 }
44
45 $cores = empty($updates['core']) ? array() : $updates['core'];
46 $core_updates = array();
47 foreach ($cores as $core) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- We dont use $core but we need the AS in the foreach so it needs to stay
48 $core_updates[] = $this->_update_core(null);
49 // Only one (and always we go to the latest version) - i.e. we ignore the passed parameters
50 break;
51 }
52
53 $translation_updates = array();
54 if (!empty($updates['translations'])) {
55 $translation_updates[] = $this->_update_translation();
56 }
57
58 return $this->_response(array(
59 'plugins' => $plugin_updates,
60 'themes' => $theme_updates,
61 'core' => $core_updates,
62 'translations' => $translation_updates,
63 ));
64
65 }
66
67 /**
68 * Updates a plugin. A facade method that exposes a private updates
69 * feature for other modules to consume.
70 *
71 * @param string $plugin Specific plugin to be updated
72 * @param string $slug Unique key passed for updates
73 *
74 * @return array
75 */
76 public function update_plugin($plugin, $slug) {
77 return $this->_update_plugin($plugin, $slug);
78 }
79
80 /**
81 * Updates a theme. A facade method that exposes a private updates
82 * feature for other modules to consume.
83 *
84 * @param string $theme Specific theme to be updated
85 *
86 * @return array
87 */
88 public function update_theme($theme) {
89 return $this->_update_theme($theme);
90 }
91
92 /**
93 * Gets available updates for a certain entity (e.g. plugin or theme). A facade method that
94 * exposes a private updates feature for other modules to consume.
95 *
96 * @param string $entity The name of the entity that this request is intended for (e.g. themes or plugins)
97 *
98 * @return array
99 */
100 public function get_item_updates($entity) {
101 $updates = array();
102 switch ($entity) {
103 case 'themes':
104 wp_update_themes();
105 $updates = $this->maybe_add_third_party_items(get_theme_updates(), 'theme');
106 break;
107 case 'plugins':
108 wp_update_plugins();
109 $updates = $this->maybe_add_third_party_items(get_plugin_updates(), 'plugin');
110 break;
111 }
112
113 return $updates;
114 }
115
116 /**
117 * Mostly from wp_ajax_update_plugin() in wp-admin/includes/ajax-actions.php (WP 4.5.2)
118 * Code-formatting style has been retained from the original, for ease of comparison/updating
119 *
120 * @param string $plugin Specific plugin to be updated
121 * @param string $slug Unique key passed for updates
122 * @return array
123 */
124 private function _update_plugin($plugin, $slug) {
125
126 $status = array(
127 'update' => 'plugin',
128 'plugin' => $plugin,
129 'slug' => sanitize_key($slug),
130 'oldVersion' => '',
131 'newVersion' => '',
132 );
133
134 if (false !== strpos($plugin, '..') || false !== strpos($plugin, ':') || !preg_match('#^[^\/]#i', $plugin)) {
135 $status['error'] = 'not_found';
136 return $status;
137 }
138
139 $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
140 if (!isset($plugin_data['Name']) || !isset($plugin_data['Author']) || ('' == $plugin_data['Name'] && '' == $plugin_data['Author'])) {
141 $status['error'] = 'not_found';
142 return $status;
143 }
144
145 if ($plugin_data['Version']) {
146 $status['oldVersion'] = $plugin_data['Version'];
147 }
148
149 if (!current_user_can('update_plugins')) {
150 $status['error'] = 'updates_permission_denied';
151 return $status;
152 }
153
154 include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
155
156 wp_update_plugins();
157
158 // WP < 3.7
159 if (!class_exists('Automatic_Upgrader_Skin')) include_once(UPDRAFTCENTRAL_CLIENT_DIR.'/classes/class-automatic-upgrader-skin.php');
160
161 $skin = new Automatic_Upgrader_Skin();
162 $upgrader = new Plugin_Upgrader($skin);
163 $result = $upgrader->bulk_upgrade(array($plugin));
164
165 if (is_array($result) && empty($result[$plugin]) && is_wp_error($skin->result)) {
166 $result = $skin->result;
167 }
168
169 $status['messages'] = $upgrader->skin->get_upgrade_messages();
170
171 if (is_array($result) && !empty($result[$plugin])) {
172 $plugin_update_data = current($result);
173
174 /*
175 * If the `update_plugins` site transient is empty (e.g. when you update
176 * two plugins in quick succession before the transient repopulates),
177 * this may be the return.
178 *
179 * Preferably something can be done to ensure `update_plugins` isn't empty.
180 * For now, surface some sort of error here.
181 */
182 if (true === $plugin_update_data) {
183 $status['error'] = 'update_failed';
184 return $status;
185 }
186
187 if (is_wp_error($result[$plugin])) {
188 $status['error'] = $result[$plugin]->get_error_code();
189 $status['error_message'] = $result[$plugin]->get_error_message();
190 return $status;
191 }
192
193 $plugin_data = get_plugins('/' . $result[$plugin]['destination_name']);
194 $plugin_data = reset($plugin_data);
195
196 if ($plugin_data['Version']) {
197 $status['newVersion'] = $plugin_data['Version'];
198 }
199 return $status;
200
201 } elseif (is_wp_error($result)) {
202 $status['error'] = $result->get_error_code();
203 $status['error_message'] = $result->get_error_message();
204 return $status;
205
206 } elseif (is_bool($result) && !$result) {
207 $status['error'] = 'unable_to_connect_to_filesystem';
208
209 global $wp_filesystem;
210
211 // Pass through the error from WP_Filesystem if one was raised
212 if (isset($wp_filesystem->errors) && is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) {
213 $status['error'] = $wp_filesystem->errors->get_error_code();
214 $status['error_message'] = $wp_filesystem->errors->get_error_message();
215 }
216
217 return $status;
218
219 } else {
220 // An unhandled error occurred
221 $status['error'] = 'update_failed';
222 return $status;
223 }
224 }
225
226 /**
227 * Adapted from _update_theme (above)
228 *
229 * @param string $core
230 * @return array
231 */
232 private function _update_core($core) {
233
234 global $wp_filesystem;
235
236 $status = array(
237 'update' => 'core',
238 'core' => $core,
239 'oldVersion' => '',
240 'newVersion' => '',
241 );
242
243 // THis is included so we can get $wp_version
244 include(ABSPATH.WPINC.'/version.php');
245
246 $status['oldVersion'] = $wp_version;// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- The variable is defined inside the ABSPATH.WPINC.'/version.php'.
247
248 if (!current_user_can('update_core')) {
249 $status['error'] = 'updates_permission_denied';
250 return $status;
251 }
252
253 include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
254
255 wp_version_check();
256
257 $locale = get_locale();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable -- Unused variable is for future use.
258
259 $core_update_key = false;
260 $core_update_latest_version = false;
261
262 $get_core_updates = get_core_updates();
263
264 // THis is included so we can get $wp_version
265 @include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function.
266
267 foreach ($get_core_updates as $k => $core_update) {
268 if (isset($core_update->version) && version_compare($core_update->version, $wp_version, '>') && version_compare($core_update->version, $core_update_latest_version, '>')) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- The variable is defined inside the ABSPATH.WPINC.'/version.php'.
269 $core_update_latest_version = $core_update->version;
270 $core_update_key = $k;
271 }
272 }
273
274 if (false === $core_update_key) {
275 $status['error'] = 'no_update_found';
276 return $status;
277 }
278
279 $update = $get_core_updates[$core_update_key];
280
281 // WP < 3.7
282 if (!class_exists('Automatic_Upgrader_Skin')) include_once(UPDRAFTCENTRAL_CLIENT_DIR.'/classes/class-automatic-upgrader-skin.php');
283
284 $skin = new Automatic_Upgrader_Skin();
285 $upgrader = new Core_Upgrader($skin);
286
287 $result = $upgrader->upgrade($update);
288
289 $status['messages'] = $upgrader->skin->get_upgrade_messages();
290
291 if (is_wp_error($result)) {
292 $status['error'] = $result->get_error_code();
293 $status['error_message'] = $result->get_error_message();
294 return $status;
295
296 } elseif (is_bool($result) && !$result) {
297 $status['error'] = 'unable_to_connect_to_filesystem';
298
299 // Pass through the error from WP_Filesystem if one was raised
300 if (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) {
301 $status['error'] = $wp_filesystem->errors->get_error_code();
302 $status['error_message'] = $wp_filesystem->errors->get_error_message();
303 }
304
305 return $status;
306
307
308 } elseif (preg_match('/^[0-9]/', $result)) {
309
310 $status['newVersion'] = $result;
311
312 return $status;
313
314 } else {
315 // An unhandled error occurred
316 $status['error'] = 'update_failed';
317 return $status;
318 }
319
320 }
321
322 private function _update_theme($theme) {
323
324 global $wp_filesystem;
325
326 $status = array(
327 'update' => 'theme',
328 'theme' => $theme,
329 'oldVersion' => '',
330 'newVersion' => '',
331 );
332
333 if (false !== strpos($theme, '/') || false !== strpos($theme, '\\')) {
334 $status['error'] = 'not_found';
335 return $status;
336 }
337
338 $theme_version = $this->get_theme_version($theme);
339 if (false === $theme_version) {
340 $status['error'] = 'not_found';
341 return $status;
342 }
343 $status['oldVersion'] = $theme_version;
344
345 if (!current_user_can('update_themes')) {
346 $status['error'] = 'updates_permission_denied';
347 return $status;
348 }
349
350 include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
351
352 wp_update_themes();
353
354 // WP < 3.7
355 if (!class_exists('Automatic_Upgrader_Skin')) include_once(UPDRAFTCENTRAL_CLIENT_DIR.'/classes/class-automatic-upgrader-skin.php');
356
357 $skin = new Automatic_Upgrader_Skin();
358 $upgrader = new Theme_Upgrader($skin);
359 $upgrader->init();
360 $result = $upgrader->bulk_upgrade(array($theme));
361
362 if (is_array($result) && empty($result[$theme]) && is_wp_error($skin->result)) {
363 $result = $skin->result;
364 }
365
366 $status['messages'] = $upgrader->skin->get_upgrade_messages();
367
368 if (is_array($result) && !empty($result[$theme])) {
369 $theme_update_data = current($result);
370
371 /*
372 * If the `update_themes` site transient is empty (e.g. when you update
373 * two plugins in quick succession before the transient repopulates),
374 * this may be the return.
375 *
376 * Preferably something can be done to ensure `update_themes` isn't empty.
377 * For now, surface some sort of error here.
378 */
379 if (true === $theme_update_data) {
380 $status['error'] = 'update_failed';
381 return $status;
382 }
383
384 $new_theme_version = $this->get_theme_version($theme);
385 if (false === $new_theme_version) {
386 $status['error'] = 'update_failed';
387 return $status;
388 }
389
390 $status['newVersion'] = $new_theme_version;
391
392 return $status;
393
394 } elseif (is_wp_error($result)) {
395 $status['error'] = $result->get_error_code();
396 $status['error_message'] = $result->get_error_message();
397 return $status;
398
399 } elseif (is_bool($result) && !$result) {
400 $status['error'] = 'unable_to_connect_to_filesystem';
401
402 // Pass through the error from WP_Filesystem if one was raised
403 if (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) {
404 $status['error'] = $wp_filesystem->errors->get_error_code();
405 $status['error_message'] = $wp_filesystem->errors->get_error_message();
406 }
407
408 return $status;
409
410 } else {
411 // An unhandled error occurred
412 $status['error'] = 'update_failed';
413 return $status;
414 }
415
416 }
417
418 /**
419 * Updates available translations for this website
420 *
421 * @return Array
422 */
423 private function _update_translation() {
424 global $wp_filesystem;
425
426 $status = array();
427
428 include_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
429 if (!class_exists('Automatic_Upgrader_Skin')) include_once(UPDRAFTCENTRAL_CLIENT_DIR.'/classes/class-automatic-upgrader-skin.php');
430
431 $skin = new Automatic_Upgrader_Skin();
432 $upgrader = new Language_Pack_Upgrader($skin);
433 $result = $upgrader->bulk_upgrade();
434
435 if (is_array($result) && !empty($result)) {
436 $status['success'] = true;
437 } elseif (is_wp_error($result)) {
438 $status['error'] = $result->get_error_code();
439 $status['error_message'] = $result->get_error_message();
440 } elseif (is_bool($result) && !$result) {
441 $status['error'] = 'unable_to_connect_to_filesystem';
442
443 // Pass through the error from WP_Filesystem if one was raised
444 if (is_wp_error($wp_filesystem->errors) && $wp_filesystem->errors->get_error_code()) {
445 $status['error'] = $wp_filesystem->errors->get_error_code();
446 $status['error_message'] = $wp_filesystem->errors->get_error_message();
447 }
448 } elseif (is_bool($result) && $result) {
449 $status['error'] = 'up_to_date';
450 } else {
451 // An unhandled error occurred
452 $status['error'] = 'update_failed';
453 }
454
455 return $status;
456 }
457
458 private function get_theme_version($theme) {
459
460 if (function_exists('wp_get_theme')) {
461 // Since WP 3.4.0
462 $theme = wp_get_theme($theme);
463
464 if (is_a($theme, 'WP_Theme')) {
465 return $theme->Version;
466 } else {
467 return false;
468 }
469
470 } else {
471 $theme_data = get_theme_data(WP_CONTENT_DIR . '/themes/'.$theme.'/style.css');
472
473 if (isset($theme_data['Version'])) {
474 return $theme_data['Version'];
475 } else {
476 return false;
477 }
478 }
479 }
480
481 /**
482 * Adding third-party plugins/theme for UDC automatic updates, for some updaters which store their information when the transient is set, instead of (like most) when it is fetched
483 *
484 * @param Array $items A collection of plugins or themes for updates
485 * @param String $type A string indicating which type of collection to process (e.g. 'plugin' or 'theme')
486 * @return Array An updated collection of plugins or themes for updates
487 */
488 private function maybe_add_third_party_items($items, $type) {
489
490 // Here we're preparing a dummy transient object that will be pass to the filter
491 // and gets populated by those plugins or themes that hooked into the "pre_set_site_transient_*" filter.
492 //
493 // We're setting some default properties so that plugins and themes won't be able to bypass populating them,
494 // because most of the plugins and themes updater scripts checks whether or not these properties are set and
495 // non-empty or passed the 12 hour period (where WordPress re-starts the process of checking updates for
496 // these plugins and themes), otherwise, they bypass populating the update/upgrade info for these items.
497 $transient = (object) array(
498 'last_checked' => time() - (13 * 3600), /* Making sure that we passed the 12 hour period check */
499 'checked' => array('default' => 'none'),
500 'response' => array('default' => 'none')
501 );
502
503 // Most of the premium plugin developers are hooking into the "pre_set_site_transient_update_plugins" and
504 // "pre_set_site_transient_update_themes" filters if they want their plugins or themes to support automatic
505 // updates. Thus, we're making sure here that if for some reason, those plugins or themes didn't get through
506 // and added to the "update_plugins" or "update_themes" transients when calling the get_site_transient('update_plugins')
507 // or get_site_transient('update_themes') we add them here manually.
508 $filters = apply_filters("pre_set_site_transient_update_{$type}s", $transient, "update_{$type}s");
509
510
511 $all_items = array();
512 switch ($type) {
513 case 'plugin':
514 $all_items = get_plugins();
515 break;
516 case 'theme':
517 $this->_frontend_include('theme.php');
518 if (function_exists('wp_get_themes')) {
519 $themes = wp_get_themes();
520 if (!empty($themes)) {
521 // We make sure that the return key matched the previous
522 // key from "get_themes", otherwise, no updates will be found
523 // even if it does have one. "get_themes" returns the name of the
524 // theme as the key while "wp_get_themes" returns the slug.
525 foreach ($themes as $theme) {
526 $all_items[$theme->Name] = $theme;
527 }
528 }
529 } else {
530 $all_items = get_themes();
531 }
532 break;
533 default:
534 break;
535 }
536
537
538 if (!empty($all_items)) {
539 $all_items = (array) $all_items;
540 foreach ($all_items as $key => $data) {
541 if (!isset($items[$key]) && isset($filters->response[$key])) {
542
543 $update_info = ('plugin' === $type) ? $filters->response[$key] : $data;
544
545 // If "package" is empty, it means that this plugin or theme does not support automatic updates
546 // currently, since the "package" field is the one holding the download link of these plugins/themes
547 // and WordPress is using this field to download the latest version of these items.
548 //
549 // Most of the time, this "package" field is not empty, but for premium plugins/themes this can be
550 // conditional, only then if the user provides a legit access or api key can this field be populated or available.
551 //
552 // We set this variable to "false" by default, as plugins/themes hosted in wordpress.org always sets this
553 // to the downloadable zip file of the plugin/theme.
554 //
555 // N.B. We only add premium plugins/themes that has this "package" field set and non-empty, otherwise, it
556 // does not support automatic updates as explained above.
557 $is_package_empty = false;
558
559 if (is_object($update_info)) {
560 if (!isset($update_info->package) || empty($update_info->package)) {
561 $is_package_empty = true;
562 }
563
564 } elseif (is_array($update_info)) {
565 if (!isset($update_info['package']) || empty($update_info['package'])) {
566 $is_package_empty = true;
567 }
568 }
569
570 // Add this plugin/theme to the current updates collection
571 if (!$is_package_empty) {
572 $items[$key] = ('plugin' === $type) ? (object) $data : $this->get_theme_info($key);
573 $items[$key]->update = $update_info;
574 }
575
576 }
577 }
578 }
579
580 return $this->prep_items_for_updates($items, $type);
581 }
582
583 /**
584 * Extracts theme's data or information
585 *
586 * @param string $theme A string representing a theme's name or slug.
587 * @return object|boolean If successful, an object containing the theme data or information, "false" otherwise.
588 */
589 private function get_theme_info($theme) {
590
591 if (function_exists('wp_get_theme')) {
592 $theme = wp_get_theme($theme);
593 if (is_a($theme, 'WP_Theme')) {
594 return $theme;
595 }
596 } else {
597 $theme_data = get_theme_data(WP_CONTENT_DIR.'/themes/'.$theme.'/style.css');
598 if (isset($theme_data['Version'])) {
599 if (!isset($theme_data['ThemeURI'])) $theme_data['ThemeURI'] = $theme_data['URI'];
600 return (object) $theme_data;
601 }
602 }
603
604 return false;
605 }
606
607 /**
608 * Fix items for update with missing "plugin" or "theme" field if applicable
609 *
610 * @param Array $items A collection of plugins or themes for updates
611 * @param String $type A string indicating which type of collection to process (e.g. 'plugin' or 'theme')
612 * @return Array An updated collection of plugins or themes for updates
613 */
614 private function prep_items_for_updates($items, $type) {
615
616 foreach ($items as $key => $data) {
617 $update_info = $data->update;
618
619 // Some plugins and/or themes does not adhere to the standard WordPress updates meta
620 // properties/fields. Thus, missing some fields such as "plugin" or "theme"
621 // in their update information results in "Automatic updates is unavailable for this item"
622 // in UDC since we're using these fields to process the updates.
623 //
624 // As a workaround, we're filling these missing fields in order to solve the above issue
625 // in case the developer of these plugins/themes forgot to include them.
626 if (is_object($update_info)) {
627 $update_info = (array) $update_info;
628 if (!isset($update_info[$type])) {
629 $update_info[$type] = $key;
630 }
631
632 $update_info = (object) $update_info;
633
634 } elseif (is_array($update_info)) {
635 if (!isset($update_info[$type])) {
636 $update_info[$type] = $key;
637 }
638 }
639
640 // Re-assign the updated info to the original "update" property
641 $items[$key]->update = $update_info;
642 }
643
644 return $items;
645 }
646
647 /**
648 * Custom validation for translation permission. Since the 'install_languages' capability insn't available until 4.9
649 * therefore, we wrapped the validation check in this block to support older version of WP.
650 *
651 * @return Boolean
652 */
653 private function user_can_update_translations() {
654 global $updraftcentral_main;
655 $wp_version = $updraftcentral_main->get_wordpress_version();
656
657 if (version_compare($wp_version, '4.9', '<')) {
658 if (current_user_can('update_core') || current_user_can('update_plugins') || current_user_can('update_themes')) return true;
659 } else {
660 if (current_user_can('install_languages')) return true;
661 }
662
663 return false;
664 }
665
666 public function get_updates($options) {
667
668 // Forcing Elegant Themes (Divi) updates component to load if it exist.
669 if (function_exists('et_register_updates_component')) et_register_updates_component();
670
671 if (!current_user_can('update_plugins') && !current_user_can('update_themes') && !current_user_can('update_core')) return $this->_generic_error_response('updates_permission_denied');
672
673 $this->_admin_include('plugin.php', 'update.php', 'file.php', 'template.php');
674 $this->_frontend_include('update.php');
675
676 if (!is_array($options)) $options = array();
677
678 // Normalise it
679 $plugin_updates = array();
680 if (current_user_can('update_plugins')) {
681
682 // Detect if refresh needed
683 $transient = get_site_transient('update_plugins');
684 if (!empty($options['force_refresh']) || false === $transient) {
685 delete_site_transient('update_plugins');
686 wp_update_plugins();
687 }
688
689 $get_plugin_updates = $this->maybe_add_third_party_items(get_plugin_updates(), 'plugin');
690 if (is_array($get_plugin_updates)) {
691 foreach ($get_plugin_updates as $update) {
692
693 // For some reason, some 3rd-party (premium) plugins are returning the same version
694 // with that of the currently installed version in WordPress. Thus, we're making sure here to
695 // only return those items for update that has new versions greater than the currently installed version.
696 if (version_compare($update->Version, $update->update->new_version, '>=')) continue;
697
698 $plugin_updates[] = array(
699 'name' => $update->Name,
700 'plugin_uri' => $update->PluginURI,
701 'version' => $update->Version,
702 'description' => $update->Description,
703 'author' => $update->Author,
704 'author_uri' => $update->AuthorURI,
705 'title' => $update->Title,
706 'author_name' => $update->AuthorName,
707 'update' => array(
708 // With Affiliates-WP, if you have not connected, this is null.
709 'plugin' => isset($update->update->plugin) ? $update->update->plugin : null,
710 'slug' => $update->update->slug,
711 'new_version' => $update->update->new_version,
712 'package' => $update->update->package,
713 'tested' => isset($update->update->tested) ? $update->update->tested : null,
714 'compatibility' => isset($update->update->compatibility) ? (array) $update->update->compatibility : null,
715 'sections' => isset($update->update->sections) ? (array) $update->update->sections : null,
716 ),
717 );
718 }
719 }
720 }
721
722 $theme_updates = array();
723 if (current_user_can('update_themes')) {
724
725 // Detect if refresh needed
726 $transient = get_site_transient('update_themes');
727 if (!empty($options['force_refresh']) || false === $transient) {
728 delete_site_transient('update_themes');
729 wp_update_themes();
730 }
731 $get_theme_updates = $this->maybe_add_third_party_items(get_theme_updates(), 'theme');
732 if (is_array($get_theme_updates)) {
733 foreach ($get_theme_updates as $update) {
734
735 // We're making sure here to only return those items for update that has new
736 // versions greater than the currently installed version.
737 if (version_compare($update->Version, $update->update['new_version'], '>=')) continue;
738
739 $name = $update->Name;
740 $theme_name = !empty($name) ? $name : $update->update['theme'];
741
742 $theme_updates[] = array(
743 'name' => $theme_name,
744 'theme_uri' => $update->ThemeURI,
745 'version' => $update->Version,
746 'description' => $update->Description,
747 'author' => $update->Author,
748 'author_uri' => $update->AuthorURI,
749 'update' => array(
750 'theme' => $update->update['theme'],
751 'new_version' => $update->update['new_version'],
752 'package' => $update->update['package'],
753 'url' => $update->update['url'],
754 ),
755 );
756
757 }
758 }
759 }
760
761 $core_updates = array();
762 if (current_user_can('update_core')) {
763
764 // Detect if refresh needed
765 $transient = get_site_transient('update_core');
766 if (!empty($options['force_refresh']) || false === $transient) {
767 // The next line is only needed for older WP versions - otherwise, the parameter to wp_version_check forces a check.
768 delete_site_transient('update_core');
769 wp_version_check(array(), true);
770 }
771
772 $get_core_updates = get_core_updates();
773
774 if (is_array($get_core_updates)) {
775
776 $core_update_key = false;
777 $core_update_latest_version = false;
778
779 // THis is included so we can get $wp_version
780 @include(ABSPATH.WPINC.'/version.php');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged -- Silenced to suppress errors that may arise because of the function.
781
782 foreach ($get_core_updates as $k => $core_update) {
783 if (isset($core_update->version) && version_compare($core_update->version, $wp_version, '>') && version_compare($core_update->version, $core_update_latest_version, '>')) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- The variable is defined inside the ABSPATH.WPINC.'/version.php'.
784 $core_update_latest_version = $core_update->version;
785 $core_update_key = $k;
786 }
787 }
788
789 if (false !== $core_update_key) {
790
791 $update = $get_core_updates[$core_update_key];
792
793 global $wpdb;
794
795 $mysql_version = $wpdb->db_version();
796
797 $is_mysql = (file_exists(WP_CONTENT_DIR . '/db.php') && empty($wpdb->is_mysql)) ? false : true;
798
799 // We're making sure here to only return those items for update that has new
800 // versions greater than the currently installed version.
801 if (version_compare($wp_version, $update->version, '<')) {// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- The variable is defined inside the ABSPATH.WPINC.'/version.php'.
802 $core_updates[] = array(
803 'download' => $update->download,
804 'version' => $update->version,
805 'php_version' => $update->php_version,
806 'mysql_version' => $update->mysql_version,
807 'installed' => array(
808 'version' => $wp_version,// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- The variable is defined inside the ABSPATH.WPINC.'/version.php'.
809 'mysql' => $mysql_version,
810 'php' => PHP_VERSION,
811 'is_mysql' => $is_mysql,
812 ),
813 'sufficient' => array(
814 'mysql' => version_compare($mysql_version, $update->mysql_version, '>='),
815 'php' => version_compare(PHP_VERSION, $update->php_version, '>='),
816 ),
817 );
818 }
819
820 }
821 }
822
823 }
824
825 $translation_updates = array();
826 if (function_exists('wp_get_translation_updates') && $this->user_can_update_translations()) {
827 $translations = wp_get_translation_updates();
828
829 $translation_updates = array(
830 'items' => $translations
831 );
832 }
833
834 // Do we need to ask the user for filesystem credentials?
835 $request_filesystem_credentials = array();
836 $check_fs = array(
837 'plugins' => WP_PLUGIN_DIR,
838 'themes' => WP_CONTENT_DIR.'/themes',
839 'core' => untrailingslashit(ABSPATH)
840 );
841
842 if (!empty($translation_updates)) {
843 // 'en_US' don't usually have the "languages" folder, thus, we
844 // check if there's a need to ask for filesystem credentials for that
845 // folder if it exists, most especially for locale other than 'en_US'.
846 $language_dir = WP_CONTENT_DIR.'/languages';
847 if ('en_US' !== get_locale() && is_dir($language_dir)) {
848 $check_fs['translations'] = $language_dir;
849 }
850 }
851
852 foreach ($check_fs as $entity => $dir) {
853 $filesystem_method = get_filesystem_method(array(), $dir);
854 ob_start();
855 $filesystem_credentials_are_stored = request_filesystem_credentials(site_url());
856 $filesystem_form = strip_tags(ob_get_contents(), '<div><h2><p><input><label><fieldset><legend><span><em>');
857 ob_end_clean();
858 $request_filesystem_credentials[$entity] = ('direct' != $filesystem_method && !$filesystem_credentials_are_stored);
859 }
860
861 $automatic_backups = (class_exists('UpdraftPlus_Options') && class_exists('UpdraftPlus_Addon_Autobackup') && UpdraftPlus_Options::get_updraft_option('updraft_autobackup_default', true)) ? true : false;
862
863 return $this->_response(array(
864 'plugins' => $plugin_updates,
865 'themes' => $theme_updates,
866 'core' => $core_updates,
867 'translations' => $translation_updates,
868 'meta' => array(
869 'request_filesystem_credentials' => $request_filesystem_credentials,
870 'filesystem_form' => $filesystem_form,
871 'automatic_backups' => $automatic_backups
872 ),
873 ));
874 }
875 }
876