PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / trunk
MainWP Dashboard: Self-hosted WordPress Management for Agencies vtrunk
6.2 6.1.8 6.1.7 6.1.6 6.1.5 6.1.4 6.1.3 6.1.2 6.1.1 6.1 6.0.12 6.0.11 4.6.0.1 5.0 5.0.1 5.0.2 5.0.3 5.0.3.1 5.0.3.2 5.1 5.1.1 5.2 5.2.1 5.2.2 5.3 All 153 releases
mainwp / widgets / widget-mainwp-updates-overview.php

widget-mainwp-updates-overview.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies trunk, at widgets/widget-mainwp-updates-overview.php

1,455 lines 69.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * MainWP Updates Overview Widget
4 *
5 * Grab Child Sites update status & build widget.
6 *
7 * @package MainWP/Updates_Overview
8 */
9
10 namespace MainWP\Dashboard;
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17
18 /**
19 * Class MainWP_Updates_Overview
20 *
21 * @package MainWP\Dashboard
22 */
23 class MainWP_Updates_Overview { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
24
25 /**
26 * Method get_class_name()
27 *
28 * Get Class Name
29 *
30 * @return string __CLASS__ Class Name.
31 */
32 public static function get_class_name() {
33 return __CLASS__;
34 }
35
36 /**
37 * Method init()
38 *
39 * Add plugins api filter.
40 */
41 public static function init() {
42 add_filter( 'plugins_api', array( __CLASS__, 'plugins_api' ), 10, 3 );
43 }
44
45 /**
46 * Method plugins_api()
47 *
48 * Grab Child Sites update status & build widget.
49 *
50 * @param mixed $default_value Default.
51 * @param mixed $action Action.
52 * @param mixed $args Slug.
53 *
54 * @return mixed $default|$res
55 */
56 public static function plugins_api( $default_value, $action, $args ) {
57
58 if ( ( is_object( $args ) && property_exists( $args, 'slug' ) && ( 'mainwp' === $args->slug ) ) || ( is_array( $args ) && ! empty( $args['slug'] ) && 'mainwp' === $args['slug'] ) ) {
59 return $default_value;
60 }
61
62 $url = 'http://api.wordpress.org/plugins/info/1.0/';
63 $ssl = wp_http_supports( array( 'ssl' ) );
64 if ( $ssl ) {
65 $url = set_url_scheme( $url, 'https' );
66 }
67
68 $args = array(
69 'timeout' => 15,
70 'body' => array(
71 'action' => $action,
72 'request' => serialize( $args ), // phpcs:ignore -- WP.org API params.
73 ),
74 );
75 $request = wp_remote_post( $url, $args );
76
77 if ( is_wp_error( $request ) ) {
78 $url = isset( $_REQUEST['url'] ) ? esc_url_raw( wp_unslash( $_REQUEST['url'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
79 $name = isset( $_REQUEST['name'] ) ? wp_unslash( $_REQUEST['name'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
80 return new \WP_Error( 'plugins_api_failed', esc_html__( '<h3>No plugin information found.</h3> This may be a premium plugin and no other details are available from WordPress.', 'mainwp' ) . ' ' . ( empty( $url ) ? esc_html__( 'Please visit the plugin website for more information.', 'mainwp' ) : esc_html__( 'Please visit the plugin website for more information: ', 'mainwp' ) . '<a href="' . esc_html( rawurldecode( $url ) ) . '" target="_blank">' . esc_html( rawurldecode( $name ) ) . '</a>' ), $request->get_error_message() );
81 }
82 return $default_value;
83 }
84
85 /**
86 * Method get_name()
87 *
88 * Define Widget Title.
89 */
90 public static function get_name() {
91 return esc_html__( 'Update Overview', 'mainwp' );
92 }
93
94 /**
95 * Method render()
96 *
97 * Check if $_GET['dashboard'] then run render_sites().
98 */
99 public static function render() {
100 static::render_sites();
101 }
102
103 /**
104 * Method render_sites()
105 *
106 * Grab available Child Sites updates a build Widget.
107 *
108 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_user_extension()
109 * @uses \MainWP\Dashboard\MainWP_DB_Common::get_last_sync_status()
110 * @uses \MainWP\Dashboard\MainWP_DB::query()
111 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
112 * @uses \MainWP\Dashboard\MainWP_DB::get_website_option()
113 * @uses \MainWP\Dashboard\MainWP_DB::data_seek()::fetch_object()
114 * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
115 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_current_wpid()
116 * @uses \MainWP\Dashboard\MainWP_Utility::format_timestamp()
117 */
118 public static function render_sites() { // phpcs:ignore -- NOSONAR - current complexity required to achieve desired results. Pull request solutions appreciated.
119
120 $globalView = true;
121
122 /**
123 * Current user global.
124 *
125 * @global string
126 */
127 global $current_user;
128
129 $current_wpid = (int) MainWP_System_Utility::get_current_wpid();
130 $is_staging = 'no';
131
132 if ( $current_wpid ) {
133 $sql = MainWP_DB::instance()->get_sql_website_by_id( $current_wpid, false, array( 'wp_upgrades', 'ignored_wp_upgrades', 'ignored_trans_updates', 'premium_upgrades', 'plugins_outdate_dismissed', 'themes_outdate_dismissed', 'plugins_outdate_info', 'themes_outdate_info', 'favi_icon' ) );
134 $globalView = false;
135 } else {
136 $staging_enabled = is_plugin_active( 'mainwp-staging-extension/mainwp-staging-extension.php' ) || is_plugin_active( 'mainwp-timecapsule-extension/mainwp-timecapsule-extension.php' );
137 // To support staging extension.
138 if ( $staging_enabled ) {
139 $staging_updates_view = MainWP_System_Utility::get_select_staging_view_sites();
140 if ( 'staging' === $staging_updates_view ) {
141 $is_staging = 'yes';
142 }
143 }
144 // end support.
145
146 $sql = MainWP_DB::instance()->get_sql_websites_for_current_user( false, null, 'wp.url', false, false, null, false, array( 'wp_upgrades', 'ignored_wp_upgrades', 'ignored_trans_updates', 'premium_upgrades', 'plugins_outdate_dismissed', 'themes_outdate_dismissed', 'plugins_outdate_info', 'themes_outdate_info', 'favi_icon' ), $is_staging, array( 'connected' => 'yes' ) );
147 }
148
149 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
150
151 $mainwp_show_language_updates = get_option( 'mainwp_show_language_updates', 1 );
152 $count_websites = 0;
153
154 $total_wp_upgrades = 0;
155 $total_plugin_upgrades = 0;
156 $total_translation_upgrades = 0;
157 $total_theme_upgrades = 0;
158
159 $total_plugins_outdate = 0;
160 $total_themes_outdate = 0;
161
162 $sites_ids = array();
163
164 $currentSite = null;
165
166 $count_plugins = 0;
167 $count_themes = 0;
168
169 $cache_overview = array();
170 $use_cached = false;
171
172 $cache_group = '';
173 if ( $globalView ) {
174 $count_websites = MainWP_DB::instance()->get_websites_count();
175 $cache_group = MainWP_Cache_Helper::CGR_UPDATES;
176 $cache_key = MainWP_Cache_Helper::get_cache_key( 'updates_overview', $cache_group, array( 'staging' => $is_staging ) );
177 $cache_overview = MainWP_Cache_Helper::instance()->get_cache(
178 $cache_key,
179 $cache_group
180 );
181 }
182
183 if ( ! empty( $cache_overview ) && is_array( $cache_overview ) ) {
184 $use_cached = true;
185 $total_wp_upgrades = isset( $cache_overview['total_wp_upgrades'] ) ? intval( $cache_overview['total_wp_upgrades'] ) : 0;
186 $total_plugin_upgrades = isset( $cache_overview['total_plugin_upgrades'] ) ? intval( $cache_overview['total_plugin_upgrades'] ) : 0;
187 $total_translation_upgrades = isset( $cache_overview['total_translation_upgrades'] ) ? intval( $cache_overview['total_translation_upgrades'] ) : 0;
188 $total_theme_upgrades = isset( $cache_overview['total_theme_upgrades'] ) ? intval( $cache_overview['total_theme_upgrades'] ) : 0;
189
190 $count_plugins = isset( $cache_overview['count_plugins'] ) ? intval( $cache_overview['count_plugins'] ) : 0;
191 $count_themes = isset( $cache_overview['count_themes'] ) ? intval( $cache_overview['count_themes'] ) : 0;
192
193 $total_plugins_outdate = isset( $cache_overview['total_plugins_outdate'] ) ? intval( $cache_overview['total_plugins_outdate'] ) : 0;
194 $total_themes_outdate = isset( $cache_overview['total_themes_outdate'] ) ? intval( $cache_overview['total_themes_outdate'] ) : 0;
195
196 $sites_ids = isset( $cache_overview['sites_ids'] ) && is_array( $cache_overview['sites_ids'] ) ? $cache_overview['sites_ids'] : array();
197 } else {
198 $decodedDismissedPlugins = ! empty( $userExtension->dismissed_plugins ) ? json_decode( $userExtension->dismissed_plugins, true ) : array();
199 $decodedDismissedThemes = ! empty( $userExtension->dismissed_themes ) ? json_decode( $userExtension->dismissed_themes, true ) : array();
200 $decodedIgnoredCores = ! empty( $userExtension->ignored_wp_upgrades ) ? json_decode( $userExtension->ignored_wp_upgrades, true ) : array();
201 if ( ! is_array( $decodedIgnoredCores ) ) {
202 $decodedIgnoredCores = array();
203 }
204 }
205
206 if ( ! $globalView || ! $use_cached ) {
207 $websites = MainWP_DB::instance()->query( $sql );
208 MainWP_DB::data_seek( $websites, 0 );
209 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
210 if ( ! $globalView ) {
211 $currentSite = $website;
212 }
213
214 $sites_ids[] = $website->id;
215
216 $count_plugins += ! empty( $website->plugins ) ? count( json_decode( $website->plugins, true ) ) : 0;
217 $count_themes += ! empty( $website->themes ) ? count( json_decode( $website->themes, true ) ) : 0;
218
219 $pluginsIgnoredAbandoned_perSites = array();
220 $themesIgnoredAbandoned_perSites = array();
221
222 $wp_upgrades = ! empty( $website->wp_upgrades ) ? json_decode( $website->wp_upgrades, true ) : array();
223 $ignored_core_upgrades = ! empty( $website->ignored_wp_upgrades ) ? json_decode( $website->ignored_wp_upgrades, true ) : array();
224
225 if ( $website->is_ignoreCoreUpdates || MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $ignored_core_upgrades, 'core' ) || MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $decodedIgnoredCores, 'core' ) ) {
226 $wp_upgrades = array();
227 }
228
229 if ( is_array( $wp_upgrades ) && ! empty( $wp_upgrades ) ) {
230 ++$total_wp_upgrades;
231 }
232
233 $translation_upgrades = ! empty( $website->translation_upgrades ) ? json_decode( $website->translation_upgrades, true ) : array();
234
235 if ( ! empty( $website->ignored_trans_updates ) ) {
236 $translation_upgrades = array();
237 }
238
239 $plugin_upgrades = ! empty( $website->plugin_upgrades ) ? json_decode( $website->plugin_upgrades, true ) : array();
240
241 if ( $website->is_ignorePluginUpdates ) {
242 $plugin_upgrades = array();
243 }
244
245 $theme_upgrades = ! empty( $website->theme_upgrades ) ? json_decode( $website->theme_upgrades, true ) : array();
246 if ( $website->is_ignoreThemeUpdates ) {
247 $theme_upgrades = array();
248 }
249
250 $decodedPremiumUpgrades = MainWP_DB::instance()->get_website_option( $website, 'premium_upgrades' );
251 $decodedPremiumUpgrades = ! empty( $decodedPremiumUpgrades ) ? json_decode( $decodedPremiumUpgrades, true ) : array();
252
253 if ( is_array( $decodedPremiumUpgrades ) ) {
254 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
255 $premiumUpgrade['premium'] = true;
256
257 if ( 'plugin' === $premiumUpgrade['type'] ) {
258 if ( ! is_array( $plugin_upgrades ) ) {
259 $plugin_upgrades = array();
260 }
261 if ( ! $website->is_ignorePluginUpdates ) {
262
263 $premiumUpgrade = array_filter( $premiumUpgrade );
264 if ( ! isset( $plugin_upgrades[ $crrSlug ] ) ) {
265 continue;
266 }
267
268 $plugin_upgrades[ $crrSlug ] = array_merge( $plugin_upgrades[ $crrSlug ], $premiumUpgrade );
269 }
270 } elseif ( 'theme' === $premiumUpgrade['type'] ) {
271 if ( ! is_array( $theme_upgrades ) ) {
272 $theme_upgrades = array();
273 }
274 if ( ! $website->is_ignoreThemeUpdates ) {
275 $theme_upgrades[ $crrSlug ] = $premiumUpgrade;
276 }
277 }
278 }
279 }
280
281 if ( is_array( $translation_upgrades ) ) {
282 $total_translation_upgrades += count( $translation_upgrades );
283 }
284
285 if ( is_array( $plugin_upgrades ) ) {
286 $ignored_plugins = ! empty( $website->ignored_plugins ) ? json_decode( $website->ignored_plugins, true ) : array();
287 if ( is_array( $ignored_plugins ) ) {
288 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins );
289
290 }
291
292 $ignored_plugins = ! empty( $userExtension->ignored_plugins ) ? json_decode( $userExtension->ignored_plugins, true ) : array();
293 if ( is_array( $ignored_plugins ) ) {
294 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins );
295
296 }
297
298 $total_plugin_upgrades += count( $plugin_upgrades );
299 }
300
301 if ( is_array( $theme_upgrades ) ) {
302 $ignored_themes = ! empty( $website->ignored_themes ) ? json_decode( $website->ignored_themes, true ) : array();
303 if ( is_array( $ignored_themes ) ) {
304 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes );
305 }
306
307 $ignored_themes = ! empty( $userExtension->ignored_themes ) ? json_decode( $userExtension->ignored_themes, true ) : array();
308 if ( is_array( $ignored_themes ) ) {
309 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes );
310 }
311
312 $total_theme_upgrades += count( $theme_upgrades );
313 }
314
315 $pluginsIgnoredAbandoned_perSites = MainWP_DB::instance()->get_website_option( $website, 'plugins_outdate_dismissed' );
316 $pluginsIgnoredAbandoned_perSites = ! empty( $pluginsIgnoredAbandoned_perSites ) ? json_decode( $pluginsIgnoredAbandoned_perSites, true ) : array();
317 if ( is_array( $pluginsIgnoredAbandoned_perSites ) ) {
318 $pluginsIgnoredAbandoned_perSites = array_filter( $pluginsIgnoredAbandoned_perSites );
319 }
320
321 $themesIgnoredAbandoned_perSites = MainWP_DB::instance()->get_website_option( $website, 'themes_outdate_dismissed' );
322 $themesIgnoredAbandoned_perSites = ! empty( $themesIgnoredAbandoned_perSites ) ? json_decode( $themesIgnoredAbandoned_perSites, true ) : array();
323 if ( is_array( $themesIgnoredAbandoned_perSites ) ) {
324 $themesIgnoredAbandoned_perSites = array_filter( $themesIgnoredAbandoned_perSites );
325 }
326
327 $plugins_outdate = MainWP_DB::instance()->get_website_option( $website, 'plugins_outdate_info' );
328 $plugins_outdate = ! empty( $plugins_outdate ) ? json_decode( $plugins_outdate, true ) : array();
329
330 $themes_outdate = MainWP_DB::instance()->get_website_option( $website, 'themes_outdate_info' );
331 $themes_outdate = ! empty( $themes_outdate ) ? json_decode( $themes_outdate, true ) : array();
332
333 if ( is_array( $plugins_outdate ) ) {
334 if ( is_array( $pluginsIgnoredAbandoned_perSites ) ) {
335 $plugins_outdate = array_diff_key( $plugins_outdate, $pluginsIgnoredAbandoned_perSites );
336 }
337
338 if ( is_array( $decodedDismissedPlugins ) ) {
339 $plugins_outdate = array_diff_key( $plugins_outdate, $decodedDismissedPlugins );
340 }
341
342 $total_plugins_outdate += count( $plugins_outdate );
343 }
344
345 if ( is_array( $themes_outdate ) ) {
346 if ( is_array( $themesIgnoredAbandoned_perSites ) ) {
347 $themes_outdate = array_diff_key( $themes_outdate, $themesIgnoredAbandoned_perSites );
348 }
349
350 if ( is_array( $decodedDismissedThemes ) ) {
351 $themes_outdate = array_diff_key( $themes_outdate, $decodedDismissedThemes );
352 }
353
354 $total_themes_outdate += count( $themes_outdate );
355 }
356 }
357
358 if ( $globalView && ! empty( $cache_key ) ) {
359 $data = array(
360 'total_wp_upgrades',
361 'total_plugin_upgrades',
362 'total_translation_upgrades',
363 'total_theme_upgrades',
364 'total_plugins_outdate',
365 'total_themes_outdate',
366 'count_plugins',
367 'count_themes',
368 'sites_ids',
369 );
370 MainWP_Cache_Helper::add_cache( $cache_key, $cache_group, compact( $data ) );
371 }
372 }
373
374 // WP Upgrades part.
375 $total_upgrades = $total_wp_upgrades + $total_plugin_upgrades + $total_theme_upgrades;
376
377 // to fix incorrect total updates.
378 if ( $mainwp_show_language_updates ) {
379 $total_upgrades += $total_translation_upgrades;
380 }
381
382 $trustedPlugins = ! empty( $userExtension->trusted_plugins ) ? json_decode( $userExtension->trusted_plugins, true ) : array();
383 if ( ! is_array( $trustedPlugins ) ) {
384 $trustedPlugins = array();
385 }
386 $trustedThemes = ! empty( $userExtension->trusted_themes ) ? json_decode( $userExtension->trusted_themes, true ) : array();
387 if ( ! is_array( $trustedThemes ) ) {
388 $trustedThemes = array();
389 }
390
391 /**
392 * Filter: mainwp_limit_updates_all
393 *
394 * Limits the number of updates that will be processed in a single run on Update Everything action.
395 *
396 * @since 4.0
397 */
398 $limit_updates_all = apply_filters( 'mainwp_limit_updates_all', 0 );
399
400 if ( ! $globalView ) {
401 $last_dtsSync = $currentSite->dtsSync;
402 } else {
403 $result = MainWP_DB_Common::instance()->get_last_sync_status( $is_staging );
404 $sync_status = $result['sync_status'];
405 $last_sync = $result['last_sync'];
406 $last_dtsSync = $result['last_sync'];
407
408 if ( 'all_synced' === $sync_status ) {
409 $last_dtsSync = get_option( 'mainwp_last_synced_all_sites', $last_sync );
410 }
411 }
412
413 $lastSyncMsg = '';
414 if ( $last_dtsSync ) {
415 $lastSyncMsg = esc_html__( 'Last synchronization completed on: ', 'mainwp' ) . MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $last_dtsSync ) );
416 }
417
418 $user_can_update_translation = \mainwp_current_user_can( 'dashboard', 'update_translations' );
419 $user_can_update_wordpress = \mainwp_current_user_can( 'dashboard', 'update_wordpress' );
420 $user_can_update_themes = \mainwp_current_user_can( 'dashboard', 'update_themes' );
421 $user_can_update_plugins = \mainwp_current_user_can( 'dashboard', 'update_plugins' );
422
423 $can_total_update = ( $user_can_update_wordpress && $user_can_update_plugins && $user_can_update_themes && $user_can_update_translation ) ? true : false;
424
425 static::render_updates_overview_widget_header( $lastSyncMsg );
426 ?>
427 <div class="mainwp-scrolly-overflow">
428
429 <div class="ui small cards mainwp-cards">
430
431 <?php static::render_total_update( $total_upgrades, $can_total_update, $limit_updates_all, $count_websites, $count_plugins, $count_themes, $current_wpid ); ?>
432 <?php static::render_wordpress_update( $user_can_update_wordpress, $total_wp_upgrades, $globalView, $current_wpid, $count_websites ); ?>
433 <?php static::render_plugins_update( $user_can_update_plugins, $total_plugin_upgrades, $globalView, $current_wpid, $count_plugins ); ?>
434 <?php static::render_themes_update( $user_can_update_themes, $total_theme_upgrades, $globalView, $current_wpid, $count_themes ); ?>
435 <?php if ( 1 === (int) $mainwp_show_language_updates ) : ?>
436 <?php static::render_language_update( $user_can_update_translation, $total_translation_upgrades, $globalView, $current_wpid ); ?>
437 <?php endif; ?>
438 <?php static::render_abandoned_plugins( $total_plugins_outdate, $globalView, $current_wpid, $count_plugins ); ?>
439 <?php static::render_abandoned_themes( $total_themes_outdate, $globalView, $current_wpid, $count_themes ); ?>
440
441 <?php
442 /**
443 * Action: mainwp_updates_overview_after_update_details
444 *
445 * Fires at the bottom of the Update Details section in the Updates Overview widget.
446 *
447 * @since 4.1
448 */
449 do_action( 'mainwp_updates_overview_after_update_details', $currentSite, $globalView, $userExtension );
450 ?>
451
452 </div>
453
454 </div>
455 <div id="mainwp_prepare_global_update_all_container" style="display: none"></div>
456 <?php
457
458 static::render_bottom( $sites_ids, $globalView );
459 }
460
461 /**
462 * Method prepare_update_data().
463 *
464 * @param string $update_type: Values all, core, plugin, theme, trans.
465 * @param int $current_wpid Current site id.
466 */
467 public static function prepare_update_data( $update_type, $current_wpid ) { // phpcs:ignore -- NOSONAR - long function.
468
469 $process = array(
470 'core' => in_array( $update_type, array( 'all', 'core' ), true ),
471 'plugin' => in_array( $update_type, array( 'all', 'plugin' ), true ),
472 'theme' => in_array( $update_type, array( 'all', 'theme' ), true ),
473 'trans' => in_array( $update_type, array( 'all', 'trans' ), true ),
474 );
475
476 if ( $current_wpid ) {
477 $sql = MainWP_DB::instance()->get_sql_website_by_id( $current_wpid, false, array( 'wp_upgrades', 'ignored_wp_upgrades', 'ignored_trans_updates', 'premium_upgrades', 'plugins_outdate_dismissed', 'themes_outdate_dismissed', 'plugins_outdate_info', 'themes_outdate_info', 'favi_icon' ) );
478 } else {
479 $staging_enabled = is_plugin_active( 'mainwp-staging-extension/mainwp-staging-extension.php' ) || is_plugin_active( 'mainwp-timecapsule-extension/mainwp-timecapsule-extension.php' );
480 // To support staging extension.
481 $is_staging = 'no';
482 if ( $staging_enabled ) {
483 $staging_updates_view = MainWP_System_Utility::get_select_staging_view_sites();
484 if ( 'staging' === $staging_updates_view ) {
485 $is_staging = 'yes';
486 }
487 }
488 // end support.
489
490 $sql = MainWP_DB::instance()->get_sql_websites_for_current_user( false, null, 'wp.url', false, false, null, false, array( 'wp_upgrades', 'ignored_wp_upgrades', 'ignored_trans_updates', 'premium_upgrades', 'plugins_outdate_dismissed', 'themes_outdate_dismissed', 'plugins_outdate_info', 'themes_outdate_info', 'favi_icon' ), $is_staging, array( 'connected' => 'yes' ) );
491 }
492
493 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
494
495 $total_wp_upgrades = 0;
496 $total_plugin_upgrades = 0;
497 $total_translation_upgrades = 0;
498 $total_theme_upgrades = 0;
499
500 $all_wp_updates = array();
501 $all_plugins_updates = array();
502 $all_themes_updates = array();
503 $all_translations_updates = array();
504
505 $decodedIgnoredCores = MainWP_Utility::get_decoded_array( $userExtension->ignored_wp_upgrades );
506 $decodedIgnoredPlugins = MainWP_Utility::get_decoded_array( $userExtension->ignored_plugins );
507 $decodedIgnoredThemes = MainWP_Utility::get_decoded_array( $userExtension->ignored_themes );
508
509 $websites = MainWP_DB::instance()->query( $sql );
510 MainWP_DB::data_seek( $websites, 0 );
511 while ( $websites && ( $website = MainWP_DB::fetch_object( $websites ) ) ) {
512
513 $plugin_upgrades = array();
514 $theme_upgrades = array();
515
516 if ( $process['core'] ) {
517
518 $wp_upgrades = MainWP_Utility::get_decoded_array( $website->wp_upgrades );
519 $ignored_core_upgrades = MainWP_Utility::get_decoded_array( $website->ignored_wp_upgrades );
520
521 if (
522 $website->is_ignoreCoreUpdates ||
523 MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $ignored_core_upgrades, 'core' ) ||
524 MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $decodedIgnoredCores, 'core' )
525 ) {
526 $wp_upgrades = array();
527 }
528
529 if ( ! empty( $wp_upgrades ) ) {
530 ++$total_wp_upgrades;
531
532 $all_wp_updates[] = array(
533 'id' => $website->id,
534 'name' => $website->name,
535 'is_suspended' => $website->suspended ? 1 : 0,
536 );
537 }
538 }
539
540 if ( $process['trans'] ) {
541
542 $translation_upgrades = MainWP_Utility::get_decoded_array( $website->translation_upgrades );
543
544 if ( ! empty( $website->ignored_trans_updates ) ) {
545 $translation_upgrades = array();
546 }
547
548 if ( is_array( $translation_upgrades ) ) {
549
550 $total_translation_upgrades += count( $translation_upgrades );
551
552 foreach ( $translation_upgrades as $trans_upgrade ) {
553 $all_translations_updates[] = array(
554 'id' => $website->id,
555 'name' => $website->name,
556 'translation_slug' => rawurlencode( $trans_upgrade['slug'] ),
557 'is_suspended' => $website->suspended ? 1 : 0,
558 );
559 }
560 }
561 }
562
563 $decodedPremiumUpgrades = array();
564
565 if ( $process['plugin'] || $process['theme'] ) {
566 $decodedPremiumUpgrades = MainWP_DB::instance()->get_website_option( $website, 'premium_upgrades' );
567 $decodedPremiumUpgrades = MainWP_Utility::get_decoded_array( $decodedPremiumUpgrades );
568 }
569
570 if ( $process['plugin'] ) {
571 $plugin_upgrades = MainWP_Utility::get_decoded_array( $website->plugin_upgrades );
572
573 if ( $website->is_ignorePluginUpdates ) {
574 $plugin_upgrades = array();
575 }
576 if ( is_array( $decodedPremiumUpgrades ) ) {
577 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
578 $premiumUpgrade['premium'] = true;
579 if ( 'plugin' === $premiumUpgrade['type'] ) {
580 if ( ! is_array( $plugin_upgrades ) ) {
581 $plugin_upgrades = array();
582 }
583 if ( ! $website->is_ignorePluginUpdates ) {
584
585 $premiumUpgrade = array_filter( $premiumUpgrade );
586 if ( ! isset( $plugin_upgrades[ $crrSlug ] ) ) {
587 continue;
588 }
589
590 $plugin_upgrades[ $crrSlug ] = array_merge( $plugin_upgrades[ $crrSlug ], $premiumUpgrade );
591 }
592 }
593 }
594 }
595 }
596
597 if ( $process['theme'] ) {
598 $theme_upgrades = MainWP_Utility::get_decoded_array( $website->theme_upgrades );
599 if ( $website->is_ignoreThemeUpdates ) {
600 $theme_upgrades = array();
601 }
602
603 if ( is_array( $decodedPremiumUpgrades ) ) {
604 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
605 $premiumUpgrade['premium'] = true;
606 if ( 'theme' === $premiumUpgrade['type'] ) {
607 if ( ! is_array( $theme_upgrades ) ) {
608 $theme_upgrades = array();
609 }
610 if ( ! $website->is_ignoreThemeUpdates ) {
611 $theme_upgrades[ $crrSlug ] = $premiumUpgrade;
612 }
613 }
614 }
615 }
616 }
617
618 if ( $process['plugin'] && is_array( $plugin_upgrades ) ) {
619 $ignored_plugins = MainWP_Utility::get_decoded_array( $website->ignored_plugins );
620 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins );
621
622 if ( is_array( $decodedIgnoredPlugins ) ) {
623 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $decodedIgnoredPlugins );
624
625 }
626
627 $total_plugin_upgrades += count( $plugin_upgrades );
628
629 if ( ! empty( $plugin_upgrades ) ) {
630 foreach ( $plugin_upgrades as $slug => $value ) {
631 $all_plugins_updates[] = array(
632 'id' => $website->id,
633 'name' => $website->name,
634 'plugin_slug' => $slug,
635 'is_suspended' => $website->suspended ? 1 : 0,
636 );
637 }
638 }
639 }
640
641 if ( $process['theme'] && is_array( $theme_upgrades ) ) {
642 $ignored_themes = MainWP_Utility::get_decoded_array( $website->ignored_themes );
643 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes );
644
645 if ( is_array( $decodedIgnoredThemes ) ) {
646 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $decodedIgnoredThemes );
647 }
648
649 $total_theme_upgrades += count( $theme_upgrades );
650
651 if ( ! empty( $theme_upgrades ) ) {
652 foreach ( $theme_upgrades as $slug => $value ) {
653 $all_themes_updates[] = array(
654 'id' => $website->id,
655 'name' => $website->name,
656 'theme_slug' => $slug,
657 'is_suspended' => $website->suspended ? 1 : 0,
658 );
659 }
660 }
661 }
662 }
663
664 switch ( $update_type ) {
665 case 'core':
666 return compact( 'total_wp_upgrades', 'all_wp_updates' );
667 case 'plugin':
668 return compact( 'total_plugin_upgrades', 'all_plugins_updates' );
669 case 'theme':
670 return compact( 'total_theme_upgrades', 'all_themes_updates' );
671 case 'trans':
672 return compact( 'total_translation_upgrades', 'all_translations_updates' );
673 case 'all':
674 default:
675 return compact( 'total_wp_upgrades', 'total_plugin_upgrades', 'total_translation_upgrades', 'total_theme_upgrades', 'all_wp_updates', 'all_plugins_updates', 'all_themes_updates', 'all_translations_updates' );
676 }
677 }
678
679
680 /**
681 * Renders Updates Overview widget header.
682 *
683 * @param string $lastSyncMsg last sync info.
684 */
685 public static function render_updates_overview_widget_header( $lastSyncMsg ) {
686 ?>
687 <div class="ui grid mainwp-widget-header">
688 <div class="sixteen wide column">
689 <h2 class="ui header handle-drag">
690 <?php
691 /**
692 * Filter: mainwp_updates_overview_widget_title
693 *
694 * Filters the Updates Overview widget title text.
695 *
696 * @since 4.1
697 */
698 echo esc_html( apply_filters( 'mainwp_updates_overview_widget_title', esc_html__( 'Updates Overview', 'mainwp' ) ) );
699 ?>
700 <div class="sub header"><?php echo $lastSyncMsg; // phpcs:ignore WordPress.Security.EscapeOutput ?></div>
701 </h2>
702 </div>
703 </div>
704 <?php
705 }
706
707 /**
708 * Renders Updates Overview widget footer.
709 */
710 public static function render_updates_overview_widget_footer() {
711 ?>
712 <div class="ui two column grid mainwp-widget-footer">
713 <div class="left aligned middle aligned column"></div>
714 <div class="right aligned middle aligned column"></div>
715 </div>
716 <?php
717 }
718
719 /**
720 * Render total update.
721 *
722 * @param int $total_upgrades number of update.
723 * @param bool $can_total_update permission to update all.
724 * @param int $limit_updates_all limit number of update per request, 0 is no limit.
725 * @param int $count_websites count websites.
726 * @param int $count_plugins count plugins.
727 * @param int $count_themes count themes.
728 * @param int $current_wpid Current site id.
729 */
730 public static function render_total_update( $total_upgrades, $can_total_update, $limit_updates_all, $count_websites, $count_plugins, $count_themes, $current_wpid ) { // phpcs:ignore -- NOSONAR - complex.
731
732 if ( 0 < $count_plugins ) {
733 $outdated_percentage = round( ( ( intval( $total_upgrades ) / intval( $count_themes + $count_plugins + $count_websites ) ) * 100 ), 2 ) . '%';
734 } else {
735 $outdated_percentage = '0.00%';
736 }
737
738 ?>
739 <input type="hidden" name="updatesoverview_limit_updates_all" id="updatesoverview_limit_updates_all" value="<?php echo intval( $limit_updates_all ); ?>">
740 <?php
741 /**
742 * Action: mainwp_updates_overview_before_total_updates
743 *
744 * Fires before the total updates section in the Updates Overview widget.
745 *
746 * @since 4.1
747 */
748 do_action( 'mainwp_updates_overview_before_total_updates' );
749
750 /**
751 * Filter: mainwp_update_everything_button_text
752 *
753 * Filters the Update Everything button text.
754 *
755 * @since 4.1
756 */
757 ?>
758 <div class="ui card">
759 <div class="content">
760 <div class="header">
761 <span class="ui large text"><i class="sync alternate icon"></i> <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_upgrades ) ) ); ?></span>
762 <?php if ( intval( $total_upgrades ) > 0 ) : ?>
763 <span class="ui small text">(<?php echo esc_html( $outdated_percentage ); ?>)</span>
764 <?php else : ?>
765 <span class="ui small text">(0%)</span>
766 <?php endif; ?>
767 </div>
768 <div class="description"><?php esc_html_e( 'Available updates.', 'mainwp' ); ?></div>
769 </div>
770 <div class="extra content">
771 <div class="ui grid">
772 <div class="center aligned middle alidgned column">
773 <?php if ( ! get_option( 'mainwp_hide_update_everything', false ) ) : ?>
774 <?php if ( $can_total_update ) : ?>
775 <a href="#" <?php echo empty( $total_upgrades ) ? 'disabled' : 'onClick="updatesoverview_global_upgrade_all( \'all\', ' . intval( $current_wpid ) . ' ); return false;"'; ?> class="ui mini basic green fluid button" id="mainwp-update-everything-button"><?php echo esc_html( apply_filters( 'mainwp_update_everything_button_text', esc_html__( 'Update Everything', 'mainwp' ) ) ); ?></a>
776 <?php endif; ?>
777 <?php endif; ?>
778 </div>
779 </div>
780 </div>
781 </div>
782 <?php
783 /**
784 * Action: mainwp_updates_overview_after_total_updates
785 *
786 * Fires after the total updates section in the Updates Overview widget.
787 *
788 * @since 4.1
789 */
790 do_action( 'mainwp_updates_overview_after_total_updates' );
791 }
792
793 /**
794 * Renders WordPress update details.
795 *
796 * @param bool $user_can_update_wordpress Permission to update WordPress.
797 * @param int $total_wp_upgrades Total number of WordPress update.
798 * @param bool $globalView Global view or not.
799 * @param int $current_wpid Current site ID.
800 * @param int $count_websites Number of sites.
801 *
802 * @uses \MainWP\Dashboard\MainWP_Updates::set_continue_update_html_selector()
803 * @uses \MainWP\Dashboard\MainWP_Updates::get_continue_update_selector()
804 */
805 public static function render_wordpress_update( $user_can_update_wordpress, $total_wp_upgrades, $globalView, $current_wpid, $count_websites ) { //phpcs:ignore -- NOSONAR - complexity.
806 if ( 0 < $count_websites ) {
807 $outdated_percentage = round( ( ( intval( $total_wp_upgrades ) / $count_websites ) * 100 ), 2 ) . '%';
808 } else {
809 $outdated_percentage = '0.00%';
810 }
811
812 $wpcore_update_disabled_by = '';
813 if ( $globalView ) {
814 $detail_wp_up = 'admin.php?page=UpdatesManage&tab=wordpress-updates';
815 } else {
816 $detail_wp_up = 'admin.php?page=managesites&updateid=' . $current_wpid . '&tab=wordpress-updates';
817 $wpcore_update_disabled_by = MainWP_System_Utility::disabled_wpcore_update_by( $current_wpid );
818 }
819
820 /**
821 * Action: mainwp_updates_overview_before_update_details
822 *
823 * Fires at the top of the Update Details section in the Updates Overview widget.
824 *
825 * @since 4.1
826 */
827 do_action( 'mainwp_updates_overview_before_update_details' );
828
829 /**
830 * Action: mainwp_updates_overview_before_wordpress_updates
831 *
832 * Fires before the WordPress updates section in the Updates Overview widget.
833 *
834 * @since 4.1
835 */
836 do_action( 'mainwp_updates_overview_before_wordpress_updates' );
837 ?>
838
839 <div class="ui card">
840 <div class="content">
841 <div class="header">
842 <span class="ui large text"><i class="wordpress icon"></i> <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_wp_upgrades ) ) ); ?></span> <?php // keep `wordpress`. ?>
843 <?php if ( intval( $total_wp_upgrades ) > 0 ) : ?>
844 <span class="ui small red text">(<?php echo esc_html( $outdated_percentage ); ?>)</span>
845 <?php else : ?>
846 <span class="ui small green text">(0%)</span>
847 <?php endif; ?>
848 </div>
849 <div class="description"><?php esc_html_e( 'Available WordPress core updates.', 'mainwp' ); ?></div>
850 </div>
851 <div class="extra content">
852 <div class="ui two column grid">
853 <div class="left aligned middle aligned column">
854 <?php if ( $user_can_update_wordpress ) : ?>
855 <?php if ( 0 < $total_wp_upgrades ) : ?>
856 <?php MainWP_Updates::set_continue_update_html_selector( 'wpcore_global_upgrade_all' ); ?>
857 <?php if ( ! empty( $wpcore_update_disabled_by ) ) : ?>
858 <a href="javascript:void(0)" class="ui mini button basic green disabled mainwp-update-all-button"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
859 <?php else : ?>
860 <a href="#" onClick="updatesoverview_global_upgrade_all('wp', <?php echo intval( $current_wpid ); ?>); return false;" class="ui mini green button mainwp-update-all-button <?php MainWP_Updates::get_continue_update_selector(); // phpcs:ignore WordPress.Security.EscapeOutput ?>"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
861 <?php endif; ?>
862 <?php else : ?>
863 <a href="#" class="ui disabled green mini button mainwp-update-all-button"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
864 <?php endif; ?>
865 <?php endif; ?>
866 </div>
867 <div class="right aligned middle aligned column">
868 <?php if ( 0 < $total_wp_upgrades ) : ?>
869 <a href="<?php echo esc_url( $detail_wp_up ); ?>" class="ui mini basic button" aria-label="<?php esc_attr_e( 'View WordPress core updates details', 'mainwp' ); ?>"><?php esc_html_e( 'Details', 'mainwp' ); ?></a>
870 <?php endif; ?>
871 </div>
872 </div>
873 </div>
874 </div>
875 <?php
876 /**
877 * Action: mainwp_updates_overview_after_wordpress_updates
878 *
879 * Fires after the WordPress updates section in the Updates Overview widget.
880 *
881 * @since 4.1
882 */
883 do_action( 'mainwp_updates_overview_after_wordpress_updates' );
884 }
885
886 /**
887 * Renders Plugins update detail.
888 *
889 * @param bool $user_can_update_plugins permission to update.
890 * @param int $total_plugin_upgrades total number of update.
891 * @param bool $globalView global view or not.
892 * @param int $current_wpid current site id.
893 * @param int $count_plugins count plugin.
894 *
895 * @uses \MainWP\Dashboard\MainWP_Updates::set_continue_update_html_selector()
896 * @uses \MainWP\Dashboard\MainWP_Updates::get_continue_update_selector()
897 */
898 public static function render_plugins_update( $user_can_update_plugins, $total_plugin_upgrades, $globalView, $current_wpid, $count_plugins ) { //phpcs:ignore -- NOSONAR - complexity.
899 if ( 0 < $count_plugins ) {
900 $outdated_percentage = round( ( ( intval( $total_plugin_upgrades ) / $count_plugins ) * 100 ), 2 ) . '%';
901 } else {
902 $outdated_percentage = '0.00%';
903 }
904
905 if ( $globalView ) {
906 $detail_plugins_up = 'admin.php?page=UpdatesManage&tab=plugins-updates';
907 } else {
908 $detail_plugins_up = 'admin.php?page=managesites&updateid=' . $current_wpid . '&tab=plugins-updates';
909 }
910
911 /**
912 * Action: mainwp_updates_overview_before_plugin_updates
913 *
914 * Fires before the Plugin updates section in the Updates Overview widget.
915 *
916 * @since 4.1
917 */
918 do_action( 'mainwp_updates_overview_before_plugin_updates' );
919 ?>
920 <div class="ui card">
921 <div class="content">
922 <div class="header">
923 <span class="ui large text"><i class="plug icon"></i> <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_plugin_upgrades ) ) ); ?></span>
924 <?php if ( intval( $total_plugin_upgrades ) > 0 ) : ?>
925 <span class="ui small red text">(<?php echo esc_html( $outdated_percentage ); ?>)</span>
926 <?php else : ?>
927 <span class="ui small green text">(0%)</span>
928 <?php endif; ?>
929 </div>
930 <div class="description"><?php esc_html_e( 'Available plugin updates.', 'mainwp' ); ?></div>
931 </div>
932 <div class="extra content">
933 <div class="ui two column grid">
934 <div class="left aligned middle aligned column">
935 <?php if ( $user_can_update_plugins ) : ?>
936 <?php if ( ! empty( $total_plugin_upgrades ) ) : ?>
937 <?php MainWP_Updates::set_continue_update_html_selector( 'plugins_global_upgrade_all' ); ?>
938 <a href="#" onClick="updatesoverview_global_upgrade_all('plugin', <?php echo intval( $current_wpid ); ?>); return false;" class="ui mini green mainwp-update-all-button button <?php MainWP_Updates::get_continue_update_selector(); // phpcs:ignore WordPress.Security.EscapeOutput ?>"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
939 <?php else : ?>
940 <a href="#" class="ui disabled green mini button mainwp-update-all-button"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
941 <?php endif; ?>
942 <?php endif; ?>
943 </div>
944 <div class="right aligned middle aligned column">
945 <?php if ( ! empty( $total_plugin_upgrades ) ) : ?>
946 <a href="<?php echo esc_url( $detail_plugins_up ); ?>" class="ui mini basic button" aria-label="<?php esc_attr_e( 'View plugin updates details', 'mainwp' ); ?>"><?php esc_html_e( 'Details', 'mainwp' ); ?></a>
947 <?php endif; ?>
948 </div>
949 </div>
950 </div>
951 </div>
952 <?php
953 /**
954 * Action: mainwp_updates_overview_after_plugin_updates
955 *
956 * Fires after the Plugin updates section in the Updates Overview widget.
957 *
958 * @since 4.1
959 */
960 do_action( 'mainwp_updates_overview_after_plugin_updates' );
961 }
962
963 /**
964 * Render Themes update detail.
965 *
966 * @param bool $user_can_update_themes permission to update.
967 * @param int $total_theme_upgrades total number of update.
968 * @param bool $globalView global view or not.
969 * @param int $current_wpid current site id.
970 * @param int $count_themes count themes.
971 *
972 * @uses \MainWP\Dashboard\MainWP_Updates::set_continue_update_html_selector()
973 * @uses \MainWP\Dashboard\MainWP_Updates::get_continue_update_selector()
974 */
975 public static function render_themes_update( $user_can_update_themes, $total_theme_upgrades, $globalView, $current_wpid, $count_themes ) { //phpcs:ignore -- NOSONAR - complexity.
976 if ( 0 < $count_themes ) {
977 $outdated_percentage = round( ( ( intval( $total_theme_upgrades ) / $count_themes ) * 100 ), 2 ) . '%';
978 } else {
979 $outdated_percentage = '0.00%';
980 }
981
982 if ( $globalView ) {
983 $detail_themes_up = 'admin.php?page=UpdatesManage&tab=themes-updates';
984 } else {
985 $detail_themes_up = 'admin.php?page=managesites&updateid=' . $current_wpid . '&tab=themes-updates';
986 }
987
988 /**
989 * Action: mainwp_updates_overview_before_theme_updates
990 *
991 * Fires before the Theme updates section in the Updates Overview widget.
992 *
993 * @since 4.1
994 */
995 do_action( 'mainwp_updates_overview_before_theme_updates' );
996 ?>
997 <div class="ui card">
998 <div class="content">
999 <div class="header">
1000 <span class="ui large text"><i class="tint icon"></i> <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_theme_upgrades ) ) ); ?></span>
1001 <?php if ( intval( $total_theme_upgrades ) > 0 ) : ?>
1002 <span class="ui small red text">(<?php echo esc_html( $outdated_percentage ); ?>)</span>
1003 <?php else : ?>
1004 <span class="ui small green text">(0%)</span>
1005 <?php endif; ?>
1006 </div>
1007 <div class="description"><?php esc_html_e( 'Available theme updates.', 'mainwp' ); ?></div>
1008 </div>
1009 <div class="extra content">
1010 <div class="ui two column grid">
1011 <div class="left aligned middle aligned column">
1012 <?php if ( $user_can_update_themes ) : ?>
1013 <?php if ( ! empty( $total_theme_upgrades ) ) : ?>
1014 <?php MainWP_Updates::set_continue_update_html_selector( 'themes_global_upgrade_all' ); ?>
1015 <a href="#" onClick="updatesoverview_global_upgrade_all('theme', <?php echo intval( $current_wpid ); ?>); return false;" class="ui mini green mainwp-update-all-button button <?php MainWP_Updates::get_continue_update_selector(); // phpcs:ignore WordPress.Security.EscapeOutput ?>"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
1016 <?php else : ?>
1017 <a href="#" class="ui disabled green mini button mainwp-update-all-button"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
1018 <?php endif; ?>
1019 <?php endif; ?>
1020 </div>
1021 <div class="right aligned middle aligned column">
1022 <?php if ( ! empty( $total_theme_upgrades ) ) : ?>
1023 <a href="<?php echo esc_url( $detail_themes_up ); ?>" class="ui mini basic button" aria-label="<?php esc_attr_e( 'View theme updates details', 'mainwp' ); ?>"><?php esc_html_e( 'Details', 'mainwp' ); ?></a>
1024 <?php endif; ?>
1025 </div>
1026 </div>
1027 </div>
1028 </div>
1029 <?php
1030 /**
1031 * Action: mainwp_updates_overview_after_theme_updates
1032 *
1033 * Fires after the Theme updates section in the Updates Overview widget.
1034 *
1035 * @since 4.1
1036 */
1037 do_action( 'mainwp_updates_overview_after_theme_updates' );
1038 }
1039 /**
1040 * Render language update details.
1041 *
1042 * @param bool $user_can_update_translation Permission to update.
1043 * @param int $total_translation_upgrades Total number of update.
1044 * @param bool $globalView Global view or not.
1045 * @param int $current_wpid Current site id.
1046 *
1047 * @uses \MainWP\Dashboard\MainWP_Updates::set_continue_update_html_selector()
1048 * @uses \MainWP\Dashboard\MainWP_Updates::get_continue_update_selector()
1049 */
1050 public static function render_language_update( $user_can_update_translation, $total_translation_upgrades, $globalView, $current_wpid ) {
1051 if ( $globalView ) {
1052 $detail_trans_up = 'admin.php?page=UpdatesManage&tab=translations-updates';
1053 } else {
1054 $detail_trans_up = 'admin.php?page=managesites&updateid=' . $current_wpid . '&tab=translations-updates';
1055 }
1056 /**
1057 * Action: mainwp_updates_overview_before_translation_updates
1058 *
1059 * Fires before the Translation updates section in the Updates Overview widget.
1060 *
1061 * @since 4.1
1062 */
1063 do_action( 'mainwp_updates_overview_before_translation_updates' );
1064 ?>
1065 <div class="ui card">
1066 <div class="content">
1067 <div class="header">
1068 <span class="ui large text"><i class="language icon"></i> <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_translation_upgrades ) ) ); ?></span>
1069 </div>
1070 <div class="description"><?php esc_html_e( 'Available translation updates.', 'mainwp' ); ?></div>
1071 </div>
1072 <div class="extra content">
1073 <div class="ui two column grid">
1074 <div class="left aligned middle aligned column">
1075 <?php if ( $user_can_update_translation ) : ?>
1076 <?php if ( ! empty( $total_translation_upgrades ) ) : ?>
1077 <?php MainWP_Updates::set_continue_update_html_selector( 'translations_global_upgrade_all' ); ?>
1078 <a href="#" onClick="updatesoverview_global_upgrade_all('translation', <?php echo intval( $current_wpid ); ?>); return false;" class="ui mini green mainwp-update-all-button button <?php MainWP_Updates::get_continue_update_selector(); // phpcs:ignore WordPress.Security.EscapeOutput ?>"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
1079 <?php else : ?>
1080 <a href="#" class="ui disabled green mini button mainwp-update-all-button"><?php esc_html_e( 'Update All', 'mainwp' ); ?></a>
1081 <?php endif; ?>
1082 <?php endif; ?>
1083 </div>
1084 <div class="right aligned middle aligned column">
1085 <?php if ( ! empty( $total_translation_upgrades ) ) : ?>
1086 <a href="<?php echo esc_url( $detail_trans_up ); ?>" class="ui mini basic button" aria-label="<?php esc_attr_e( 'View translation updates details', 'mainwp' ); ?>"><?php esc_html_e( 'Details', 'mainwp' ); ?></a>
1087 <?php endif; ?>
1088 </div>
1089 </div>
1090 </div>
1091 </div>
1092 <?php
1093 /**
1094 * Action: mainwp_updates_overview_after_translation_updates
1095 *
1096 * Fires after the Translation updates section in the Updates Overview widget.
1097 *
1098 * @since 4.1
1099 */
1100 do_action( 'mainwp_updates_overview_after_translation_updates' );
1101 }
1102
1103 /**
1104 * Renders abandoned plugins detail.
1105 *
1106 * @param int $total_plugins_outdate total number of update.
1107 * @param bool $globalView global view or not.
1108 * @param int $current_wpid current site id.
1109 * @param int $count_plugins count plugins.
1110 */
1111 public static function render_abandoned_plugins( $total_plugins_outdate, $globalView, $current_wpid, $count_plugins ) {
1112 if ( $globalView ) {
1113 $detail_aban_plugins = 'admin.php?page=PluginsAbandoned';
1114 } else {
1115 $detail_aban_plugins = 'admin.php?page=managesites&updateid=' . $current_wpid . '&tab=abandoned-plugins';
1116 }
1117
1118 if ( 0 < $count_plugins ) {
1119 $outdated_percentage = round( ( ( intval( $total_plugins_outdate ) / $count_plugins ) * 100 ), 2 ) . '%';
1120 } else {
1121 $outdated_percentage = '0.00%';
1122 }
1123 /**
1124 * Action: mainwp_updates_overview_before_abandoned_plugins_themes
1125 *
1126 * Fires at the top of the Abandoned Plugins & Themes section in the Updates Overview widget.
1127 *
1128 * @since 4.1
1129 */
1130 do_action( 'mainwp_updates_overview_before_abandoned_plugins_themes' );
1131 ?>
1132 <div class="ui light card">
1133 <div class="content">
1134 <div class="header">
1135 <span class="ui large text">
1136 <i class="icons">
1137 <i class="plug icon"></i>
1138 <i class="inverted corner clock icon"></i>
1139 </i>
1140 <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_plugins_outdate ) ) ); ?>
1141 </span>
1142 <?php if ( intval( $total_plugins_outdate ) > 0 ) : ?>
1143 <span class="ui small red text">(<?php echo esc_html( $outdated_percentage ); ?>)</span>
1144 <?php else : ?>
1145 <span class="ui small green text">(0%)</span>
1146 <?php endif; ?>
1147 </div>
1148 <div class="description"><?php esc_html_e( 'Detected abandoned plugins.', 'mainwp' ); ?></div>
1149 </div>
1150 <div class="extra content">
1151 <div class="ui two column grid">
1152 <div class="left aligned middle aligned column">
1153
1154 </div>
1155 <div class="right aligned middle aligned column">
1156 <a href="<?php echo esc_url( $detail_aban_plugins ); ?>" class="ui mini basic button" aria-label="<?php esc_attr_e( 'View abandoned plugins details', 'mainwp' ); ?>"><?php esc_html_e( 'Details', 'mainwp' ); ?></a>
1157 </div>
1158 </div>
1159 </div>
1160 </div>
1161 <?php
1162 }
1163
1164 /**
1165 * Renders abandoned themes detail.
1166 *
1167 * @param int $total_themes_outdate Total number of update.
1168 * @param bool $globalView global View or not.
1169 * @param int $current_wpid Current site ID.
1170 * @param int $count_themes count themes.
1171 */
1172 public static function render_abandoned_themes( $total_themes_outdate, $globalView, $current_wpid, $count_themes ) {
1173 if ( $globalView ) {
1174 $detail_aban_themes = 'admin.php?page=ThemesAbandoned';
1175 } else {
1176 $detail_aban_themes = 'admin.php?page=managesites&updateid=' . $current_wpid . '&tab=abandoned-themes';
1177 }
1178
1179 if ( 0 < $count_themes ) {
1180 $outdated_percentage = round( ( ( intval( $total_themes_outdate ) / $count_themes ) * 100 ), 2 ) . '%';
1181 } else {
1182 $outdated_percentage = '0.00%';
1183 }
1184
1185 ?>
1186 <div class="ui light card">
1187 <div class="content">
1188 <div class="header">
1189 <span class="ui large text">
1190 <i class="icons">
1191 <i class="tint icon"></i>
1192 <i class="inverted corner clock icon"></i>
1193 </i>
1194 <?php echo esc_html( MainWP_Utility::short_number_format( intval( $total_themes_outdate ) ) ); ?>
1195 </span>
1196 <?php if ( intval( $total_themes_outdate ) > 0 ) : ?>
1197 <span class="ui small red text">(<?php echo esc_html( $outdated_percentage ); ?>)</span>
1198 <?php else : ?>
1199 <span class="ui small green text">(0%)</span>
1200 <?php endif; ?>
1201 </div>
1202 <div class="description"><?php esc_html_e( 'Detected abandoned themes.', 'mainwp' ); ?></div>
1203 </div>
1204 <div class="extra content">
1205 <div class="ui two column grid">
1206 <div class="left aligned middle aligned column">
1207
1208 </div>
1209 <div class="right aligned middle aligned column">
1210 <a href="<?php echo esc_url( $detail_aban_themes ); ?>" class="ui mini basic button" aria-label="<?php esc_attr_e( 'View abandoned themes details', 'mainwp' ); ?>"><?php esc_html_e( 'Details', 'mainwp' ); ?></a>
1211 </div>
1212 </div>
1213 </div>
1214 </div>
1215 <?php
1216 /**
1217 * Action: mainwp_updates_overview_after_abandoned_plugins_themes
1218 *
1219 * Fires at the bottom of the Abandoned Plugins & Themes section in the Updates Overview widget.
1220 *
1221 * @since 4.1
1222 */
1223 do_action( 'mainwp_updates_overview_after_abandoned_plugins_themes' );
1224 }
1225
1226 /**
1227 * Method render_global_update()
1228 *
1229 * Render global updates.
1230 *
1231 * @param string $update_type Update type.
1232 * @param bool $user_can_update_wordpress Permission to update WordPress.
1233 * @param int $total_wp_upgrades Total WordPress update.
1234 * @param array $all_wp_updates All WordPress update list.
1235 *
1236 * @param bool $user_can_update_plugins permission to update plugings.
1237 * @param int $total_plugin_upgrades total WordPress update.
1238 * @param array $all_plugins_updates all WordPress update list.
1239 *
1240 * @param bool $user_can_update_themes permission to update themes.
1241 * @param int $total_theme_upgrades total themes update.
1242 * @param mixed $all_themes_updates all themes update list.
1243 *
1244 * @param mixed $mainwp_show_language_updates MainWP Language Updates.
1245 * @param bool $user_can_update_translation permission to update languages.
1246 * @param int $total_translation_upgrades total WordPress update.
1247 * @param mixed $all_translations_updates all transations update list.
1248 */
1249 public static function render_global_update( // phpcs:ignore -- NOSONAR - complex.
1250 $update_type,
1251 $user_can_update_wordpress,
1252 $total_wp_upgrades,
1253 $all_wp_updates,
1254 $user_can_update_plugins,
1255 $total_plugin_upgrades,
1256 $all_plugins_updates,
1257 $user_can_update_themes,
1258 $total_theme_upgrades,
1259 $all_themes_updates,
1260 $mainwp_show_language_updates,
1261 $user_can_update_translation,
1262 $total_translation_upgrades,
1263 $all_translations_updates
1264 ) {
1265
1266 $process = array(
1267 'core' => in_array( $update_type, array( 'all', 'core' ), true ),
1268 'plugin' => in_array( $update_type, array( 'all', 'plugin' ), true ),
1269 'theme' => in_array( $update_type, array( 'all', 'theme' ), true ),
1270 'trans' => in_array( $update_type, array( 'all', 'trans' ), true ),
1271 );
1272
1273 ?>
1274
1275 <div id="wp_upgrades">
1276 <?php
1277 if ( $process['core'] && $user_can_update_wordpress && $total_wp_upgrades > 0 ) {
1278 foreach ( $all_wp_updates as $item ) {
1279 ?>
1280 <div updated="0" site_id="<?php echo intval( $item['id'] ); ?>" site_name="<?php echo esc_attr( $item['name'] ); ?>" is-suspended="<?php echo ! empty( $item['is_suspended'] ) ? esc_attr( $item['is_suspended'] ) : ''; ?>"></div>
1281 <?php
1282 }
1283 }
1284 ?>
1285 </div>
1286
1287 <div id="wp_plugin_upgrades">
1288 <?php
1289 if ( $process['plugin'] && $user_can_update_plugins && $total_plugin_upgrades > 0 ) {
1290 foreach ( $all_plugins_updates as $item ) {
1291 ?>
1292 <div updated="0" site_id="<?php echo intval( $item['id'] ); ?>" site_name="<?php echo esc_attr( $item['name'] ); ?>" plugin_slug="<?php echo esc_attr( $item['plugin_slug'] ); ?>" is-suspended="<?php echo ! empty( $item['is_suspended'] ) ? esc_attr( $item['is_suspended'] ) : ''; ?>"></div>
1293 <?php
1294 }
1295 }
1296 ?>
1297 </div>
1298 <div id="wp_theme_upgrades">
1299
1300 <?php
1301 if ( $process['theme'] && $user_can_update_themes && $total_theme_upgrades > 0 ) {
1302 foreach ( $all_themes_updates as $item ) {
1303 ?>
1304 <div updated="0" site_id="<?php echo intval( $item['id'] ); ?>" site_name="<?php echo esc_attr( $item['name'] ); ?>" theme_slug="<?php echo esc_attr( $item['theme_slug'] ); ?>" is-suspended="<?php echo ! empty( $item['is_suspended'] ) ? esc_attr( $item['is_suspended'] ) : ''; ?>"></div>
1305 <?php
1306 }
1307 }
1308 ?>
1309
1310 </div>
1311 <?php if ( 1 === (int) $mainwp_show_language_updates ) : ?>
1312 <div id="wp_translation_upgrades">
1313
1314 <?php
1315 if ( $process['trans'] && $user_can_update_translation && $total_translation_upgrades > 0 ) {
1316 foreach ( $all_translations_updates as $item ) {
1317 ?>
1318 <div updated="0" site_id="<?php echo intval( $item['id'] ); ?>" site_name="<?php echo esc_attr( $item['name'] ); ?>" translation_slug="<?php echo esc_attr( $item['translation_slug'] ); ?>" is-suspended="<?php echo ! empty( $item['is_suspended'] ) ? esc_attr( $item['is_suspended'] ) : ''; ?>"></div>
1319 <?php
1320 }
1321 }
1322 ?>
1323 </div>
1324 <?php endif; ?>
1325 <?php
1326 }
1327
1328 /**
1329 * Render bottom of widget.
1330 *
1331 * @param array $sites_ids Child sites ids.
1332 * @param bool $globalView Whether it's global or individual site view.
1333 *
1334 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
1335 * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
1336 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
1337 */
1338 public static function render_bottom( $sites_ids, $globalView ) {
1339
1340 /**
1341 * Action: mainwp_updatesoverview_widget_bottom
1342 *
1343 * Fires at the bottom of the Updates Overview widgets.
1344 *
1345 * @param array $side_ids Array of sites IDs.
1346 * @param bool $globalView Whether it's global or individual site view.
1347 *
1348 * @since 4.0
1349 */
1350 do_action( 'mainwp_updatesoverview_widget_bottom', $sites_ids, $globalView );
1351 ?>
1352 <div class="ui modal" id="updatesoverview-backup-box" tabindex="0">
1353 <div class="header"><?php esc_html_e( 'Backup Check', 'mainwp' ); ?></div>
1354 <div class="scrolling content mainwp-modal-content"></div>
1355 <div class="actions mainwp-modal-actions">
1356 <input id="updatesoverview-backup-all" type="button" name="<?php esc_attr_e( 'Backup All', 'mainwp' ); ?>" value="<?php esc_attr_e( 'Backup All', 'mainwp' ); ?>" class="ui basic button"/>
1357 <a id="updatesoverview-backup-now" href="#" target="_blank" style="display: none" class="ui basic button"><?php esc_html_e( 'Backup Now', 'mainwp' ); ?></a>&nbsp;
1358 <input id="updatesoverview-backup-ignore" type="button" name="<?php esc_attr_e( 'Ignore', 'mainwp' ); ?>" value="<?php esc_attr_e( 'Ignore', 'mainwp' ); ?>" class="button"/>
1359 </div>
1360 </div>
1361 <?php
1362 }
1363
1364 /**
1365 * Method dismiss_sync_errors()
1366 *
1367 * @param bool $dismiss true|false.
1368 *
1369 * @return bool true
1370 */
1371 public static function dismiss_sync_errors( $dismiss = true ) {
1372 global $current_user;
1373 update_user_option( $current_user->ID, 'mainwp_syncerrors_dismissed', $dismiss );
1374
1375 return true;
1376 }
1377
1378 /**
1379 * Method checkbackups()
1380 *
1381 * Check if Child Site needs to be backed up before updates.
1382 *
1383 * @return mixed $output
1384 *
1385 * @uses \MainWP\Dashboard\MainWP_Backup_Handler::is_archive()
1386 * @uses \MainWP\Dashboard\MainWP_DB::get_website_by_id()
1387 * @uses \MainWP\Dashboard\MainWP_DB::get_website_option()
1388 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_primary_backup()
1389 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir()
1390 */
1391 public static function check_backups() { // phpcs:ignore -- NOSONAR - complex.
1392 if ( empty( $_POST['sites'] ) || ! is_array( $_POST['sites'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- NOSONAR - verified before.
1393 return true;
1394 }
1395
1396 $primaryBackup = MainWP_System_Utility::get_primary_backup();
1397 $global_backup_before_upgrade = get_option( 'mainwp_backup_before_upgrade' );
1398
1399 $mainwp_backup_before_upgrade_days = get_option( 'mainwp_backup_before_upgrade_days' );
1400 if ( empty( $mainwp_backup_before_upgrade_days ) || ! ctype_digit( $mainwp_backup_before_upgrade_days ) ) {
1401 $mainwp_backup_before_upgrade_days = 7;
1402 }
1403
1404 $output = array();
1405 if ( isset( $_POST['sites'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1406 foreach ( array_map( 'sanitize_text_field', wp_unslash( $_POST['sites'] ) ) as $siteId ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1407 $website = MainWP_DB::instance()->get_website_by_id( $siteId );
1408 if ( ( 0 === (int) $website->backup_before_upgrade ) || ( ( 2 === (int) $website->backup_before_upgrade ) && empty( $global_backup_before_upgrade ) ) ) {
1409 continue;
1410 }
1411
1412 $backup_method = '';
1413 if ( property_exists( $website, 'primary_backup_method' ) ) {
1414 if ( '' === $website->primary_backup_method || 'global' === $website->primary_backup_method ) {
1415 $backup_method = $primaryBackup;
1416 } else {
1417 $backup_method = $website->primary_backup_method;
1418 }
1419 }
1420
1421 if ( ! empty( $backup_method ) ) {
1422 $lastBackup = MainWP_DB::instance()->get_website_option( $website, 'primary_lasttime_backup' );
1423
1424 if ( -1 !== $lastBackup ) { // installed backup plugin.
1425 $output['sites'][ $siteId ] = ( $lastBackup < ( time() - ( $mainwp_backup_before_upgrade_days * 24 * 60 * 60 ) ) ? false : true );
1426 }
1427 $output['primary_backup'] = $backup_method;
1428 } else {
1429 $dir = MainWP_System_Utility::get_mainwp_specific_dir( $siteId );
1430 // Check if backup ok.
1431 $lastBackup = - 1;
1432 if ( file_exists( $dir ) ) {
1433 $dh = opendir( $dir ); // NOSONAR.
1434 if ( $dh ) {
1435 while ( false !== ( $file = readdir( $dh ) ) ) {
1436 if ( '.' !== $file && '..' !== $file ) {
1437 $theFile = $dir . $file;
1438 if ( MainWP_Backup_Handler::is_archive( $file ) && ! MainWP_Backup_Handler::is_sql_archive( $file ) && ( filemtime( $theFile ) > $lastBackup ) ) {
1439 $lastBackup = filemtime( $theFile );
1440 }
1441 }
1442 }
1443 closedir( $dh );
1444 }
1445 }
1446
1447 $output['sites'][ $siteId ] = ( $lastBackup < ( time() - ( $mainwp_backup_before_upgrade_days * 24 * 60 * 60 ) ) ? false : true );
1448 }
1449 }
1450 }
1451
1452 return $output;
1453 }
1454 }
1455