PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.2
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.2
6.2.2 6.2.1 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 All 155 releases
mainwp / class / class-mainwp-manage-sites-list-table.php

class-mainwp-manage-sites-list-table.php in MainWP Dashboard: Self-hosted WordPress Management for Agencies 6.2.2, at class/class-mainwp-manage-sites-list-table.php

2,616 lines 136.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Manage Sites List Table.
4 *
5 * @package MainWP/Dashboard
6 */
7
8 namespace MainWP\Dashboard;
9
10 // Exit if accessed directly.
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 /**
16 * Class MainWP_Manage_Sites_List_Table
17 *
18 * @package MainWP\Dashboard
19 */
20 class MainWP_Manage_Sites_List_Table { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR.
21
22 /**
23 * Protected variable to hold User extension.
24 *
25 * @var mixed Default null.
26 */
27 protected $userExtension = null;
28
29 /**
30 * Public variable to hold Items information.
31 *
32 * @var array
33 */
34 public $items;
35
36 /**
37 * Public variable to hold total items number.
38 *
39 * @var integer
40 */
41 public $total_items;
42
43 /**
44 * Protected variable to hold columns headers
45 *
46 * @var array
47 */
48 protected $column_headers;
49
50 /**
51 * Public variable to hold primary backup method.
52 *
53 * @var string
54 */
55 public $primary_backup = null;
56
57 /**
58 * Public variable.
59 *
60 * @var bool
61 */
62 public $site_health_disabled = false;
63
64 /**
65 * MainWP_Manage_Sites_List_Table constructor.
66 *
67 * Run each time the class is called.
68 * Add action to generate tabletop.
69 */
70 public function __construct() {
71 add_action( 'mainwp_managesites_tabletop', array( &$this, 'generate_tabletop' ) );
72 $this->site_health_disabled = get_option( 'mainwp_disableSitesHealthMonitoring', 1 ) ? true : false; // disabled by default.
73 }
74
75 /**
76 * Get the default primary column name.
77 *
78 * @return string Child Site name.
79 */
80 protected function get_default_primary_column_name() {
81 return 'site_combo';
82 }
83
84 /**
85 * Method column_backup()
86 *
87 * Backup Column.
88 *
89 * @param mixed $item List of backups.
90 *
91 * @return mixed $backupnow_lnk.
92 *
93 * @uses \MainWP\Dashboard\MainWP_Backup_Handler::is_archive()
94 * @uses \MainWP\Dashboard\MainWP_DB::instance()::get_website_option()
95 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_mainwp_specific_dir()
96 * @uses \MainWP\Dashboard\MainWP_System_Utility::get_wp_file_system()
97 * @uses \MainWP\Dashboard\MainWP_Utility::format_timestamp()
98 * @uses \MainWP\Dashboard\MainWP_Utility::get_timestamp()
99 */
100 public function column_backup( $item ) { // phpcs:ignore -- NOSONAR - complex.
101 if ( null === $this->primary_backup ) {
102 $this->primary_backup = MainWP_System_Utility::get_primary_backup();
103 }
104
105 $backup_method = empty( $item['primary_backup_method'] ) || 'global' === $item['primary_backup_method'] ? $this->primary_backup : $item['primary_backup_method'];
106
107 $lastBackup = MainWP_DB::instance()->get_website_option( $item, 'primary_lasttime_backup' );
108
109 /**
110 * Filter: mainwp_managesites_getbackuplink
111 *
112 * Filters the link for the last backup item.
113 *
114 * @param int $item['id'] Child site ID.
115 * @param string $lastBackup Last backup timestamp for the child site.
116 *
117 * @since Unknown
118 */
119 $backupnow_lnk = apply_filters( 'mainwp_managesites_getbackuplink', '', $item['id'], $lastBackup, $backup_method );
120
121 if ( ! empty( $backupnow_lnk ) ) {
122 return $backupnow_lnk;
123 }
124
125 if ( ! \mainwp_current_user_can( 'dashboard', 'execute_backups' ) ) {
126 return '';
127 }
128
129 $dir = MainWP_System_Utility::get_mainwp_specific_dir( $item['id'] );
130 $lastbackup = 0;
131
132 $hasWPFileSystem = MainWP_System_Utility::get_wp_file_system();
133
134 /**
135 * WordPress files system object.
136 *
137 * @global object
138 */
139 global $wp_filesystem;
140
141 if ( $hasWPFileSystem && $wp_filesystem->exists( $dir ) ) {
142 $dh = opendir( $dir );
143 if ( $dh ) {
144 while ( false !== ( $file = readdir( $dh ) ) ) {
145 if ( '.' !== $file && '..' !== $file ) {
146 $theFile = $dir . $file;
147 if ( MainWP_Backup_Handler::is_archive( $file ) && ! MainWP_Backup_Handler::is_sql_archive( $file ) && $wp_filesystem->mtime( $theFile ) > $lastbackup ) {
148 $lastbackup = $wp_filesystem->mtime( $theFile );
149 }
150 }
151 }
152 closedir( $dh );
153 }
154 }
155
156 $output = '';
157 if ( 0 < $lastbackup ) {
158 $output = MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $lastbackup ) ) . '<br />';
159 } else {
160 $output = '<div class="ui red label">Never</div><br/>';
161 }
162
163 return $output;
164 }
165
166 /**
167 * Method column_site_preview()
168 *
169 * Site preview column.
170 *
171 * @param mixed $item List of backups.
172 *
173 * @return mixed preview content.
174 */
175 public function column_site_preview( $item ) {
176 $site_mshot = MainWP_UI::get_mshots_image_sources( $item['url'], 900 );
177
178 return '<span class="mainwp-preview-item ui mini grey icon basic button" data-position="left center" data-inverted="" data-tooltip="' . esc_html__( 'Click to see the site homepage screenshot.', 'mainwp' ) . '" preview-site-url="' . esc_url( $item['url'] ) . '" data-mainwp-mshot-src="' . esc_url( $site_mshot['src'] ) . '" data-mainwp-mshot-requeue-src="' . esc_url( $site_mshot['requeue_src'] ) . '" ><i class="camera icon"></i></span>';
179 }
180
181 /**
182 * Set the column names.
183 *
184 * @param mixed $item MainWP Sitetable Item.
185 * @param string $column_name Column name to use.
186 *
187 * @return string Column Name.
188 */
189 public function column_default( $item, $column_name ) { // phpcs:ignore -- NOSONAR - complex function. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
190
191 /**
192 * Filter is being replaced with mainwp_sitestable_item
193 *
194 * @deprecated
195 */
196 $item = apply_filters_deprecated( 'mainwp-sitestable-item', array( $item, $item ), '4.0.7.2', 'mainwp_sitestable_item' ); // NOSONAR - not IP.
197
198 /**
199 * Filter: mainwp_sitestable_item
200 *
201 * Filters the Manage Sites table column items. Allows user to create new column item.
202 *
203 * @param array $item Array containing child site data.
204 *
205 * @since Unknown
206 */
207 $item = apply_filters( 'mainwp_sitestable_item', $item, $column_name );
208
209 switch ( $column_name ) {
210 case 'status':
211 case 'favicon':
212 case 'site_combo':
213 case 'site':
214 case 'login':
215 case 'url':
216 case 'tags':
217 case 'update':
218 case 'wpcore_update':
219 case 'plugin_update':
220 case 'theme_update':
221 case 'backup':
222 case 'wpcore_version':
223 case 'security':
224 case 'uptime':
225 case 'last_sync':
226 case 'last_post':
227 case 'site_health':
228 case 'status_code':
229 case 'notes':
230 case 'phpversion':
231 case 'language':
232 case 'index':
233 case 'site_actions':
234 return '';
235 default:
236 return isset( $item[ $column_name ] ) ? $item[ $column_name ] : '';
237 }
238 }
239
240 /**
241 * Get sortable columns.
242 *
243 * @return array $sortable_columns Array of sortable column names.
244 */
245 public function get_sortable_columns() {
246 $sortable_columns = array(
247 'site_combo' => array( 'site_combo', false ),
248 'site' => array( 'site', false ),
249 'url' => array( 'url', false ),
250 'tags' => array( 'tags', false ),
251 'client_name' => array( 'client_name', false ),
252 'security' => array( 'security', false ),
253 'last_sync' => array( 'last_sync', false ),
254 'last_post' => array( 'last_post', false ),
255 'site_health' => array( 'site_health', false ),
256 'status_code' => array( 'status_code', false ),
257 'notes' => array( 'notes', false ),
258 'ip' => array( 'ip', false ),
259 'phpversion' => array( 'phpversion', false ),
260 'wpcore_version' => array( 'wpcore_version', false ),
261 'update' => array( 'update', false ),
262 'added_datetime' => array( 'added_datetime', false ),
263 'backup' => array( 'backup', false ),
264 );
265
266 if ( ! MainWP_Uptime_Monitoring_Edit::is_enable_global_monitoring() ) {
267 unset( $sortable_columns['status_code'] );
268 }
269
270 // disable this hook for sortable columns.
271 // $sortable_columns = apply_filters( 'mainwp_sitestable_sortable_columns', $sortable_columns ); //.
272
273 return $sortable_columns;
274 }
275
276 /**
277 * Default Manage Sites table columns.
278 *
279 * Returns the array of default columns for the Manage Sites table.
280 *
281 * @return array Array of default columns names.
282 */
283 public function get_default_columns() {
284 $columns = array(
285 'cb' => '<input type="checkbox" />',
286 'status' => '',
287 'favicon' => '',
288 'site_combo' => esc_html__( 'Site', 'mainwp' ),
289 'site' => esc_html__( 'Site Title', 'mainwp' ),
290 'login' => '<i class="sign in alternate icon"></i>',
291 'url' => esc_html__( 'URL', 'mainwp' ),
292 'tags' => esc_html__( 'Tags', 'mainwp' ),
293 'client_name' => esc_html__( 'Client', 'mainwp' ),
294 'update' => esc_html__( 'Updates', 'mainwp' ),
295 'wpcore_update' => '<i class="icon wordpress"></i>', // phpcs:ignore -- Prevent modify WP icon.
296 'plugin_update' => '<i class="plug icon"></i>',
297 'theme_update' => '<i class="tint icon"></i>',
298 'wpcore_version' => esc_html__( 'Core', 'mainwp' ),
299 'security' => esc_html__( 'Security', 'mainwp' ),
300 'language' => esc_html__( 'Language', 'mainwp' ),
301 'ip' => esc_html__( 'Server IP', 'mainwp' ),
302 'index' => esc_html__( 'Index', 'mainwp' ),
303 'uptime' => esc_html__( 'Uptime', 'mainwp' ),
304 'last_sync' => esc_html__( 'Last Sync', 'mainwp' ),
305 'backup' => esc_html__( 'Backups', 'mainwp' ),
306 'phpversion' => esc_html__( 'PHP', 'mainwp' ),
307 'last_post' => esc_html__( 'Last Post', 'mainwp' ),
308 'site_health' => esc_html__( 'Health', 'mainwp' ),
309 'status_code' => esc_html__( 'HTTP Status', 'mainwp' ),
310 'added_datetime' => esc_html__( 'Connected', 'mainwp' ),
311 'site_preview' => '<i class="camera icon"></i>',
312 'notes' => esc_html__( 'Notes', 'mainwp' ),
313 );
314
315 if ( ! MainWP_Uptime_Monitoring_Edit::is_enable_global_monitoring() ) {
316 unset( $columns['status_code'] );
317 unset( $columns['uptime'] );
318 }
319
320 if ( ! \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) {
321 unset( $columns['client_name'] );
322 }
323
324 if ( $this->site_health_disabled ) {
325 unset( $columns['site_health'] );
326 }
327
328 return $columns;
329 }
330
331 /**
332 * Method get_columns()
333 *
334 * Combine all columns.
335 *
336 * @return array $columns Array of column names.
337 */
338 public function get_columns() {
339
340 $columns = $this->get_default_columns();
341
342 /**
343 * Filter is being replaced with mainwp_sitestable_getcolumns
344 *
345 * @deprecated
346 */
347 $columns = apply_filters_deprecated( 'mainwp-sitestable-getcolumns', array( $columns, $columns ), '4.0.7.2', 'mainwp_sitestable_getcolumns' ); // NOSONAR - not IP.
348
349 /**
350 * Filter: mainwp_sitestable_getcolumns
351 *
352 * Filters the Manage Sites table columns. Allows user to create a new column.
353 *
354 * @param array $columns Array containing table columns.
355 *
356 * @since Unknown
357 */
358 $columns = apply_filters( 'mainwp_sitestable_getcolumns', $columns, $columns );
359
360 $columns['site_actions'] = '';
361
362 $disable_backup = false;
363 $primaryBackup = get_option( 'mainwp_primaryBackup' );
364
365 $primary_methods = array();
366 $primary_methods = apply_filters_deprecated( 'mainwp-getprimarybackup-methods', array( $primary_methods ), '4.0.7.2', 'mainwp_getprimarybackup_methods' ); // NOSONAR - not IP.
367
368 /** This filter is documented in ../pages/page-mainwp-server-information-handler.php */
369 $primaryBackupMethods = apply_filters( 'mainwp_getprimarybackup_methods', $primary_methods );
370
371 if ( empty( $primaryBackup ) ) {
372 if ( ! get_option( 'mainwp_enableLegacyBackupFeature' ) ) {
373 $disable_backup = true;
374 }
375 } elseif ( ! is_array( $primaryBackupMethods ) || empty( $primaryBackupMethods ) ) {
376 $disable_backup = true;
377 }
378
379 if ( $disable_backup && isset( $columns['backup'] ) ) {
380 unset( $columns['backup'] );
381 }
382
383 return $columns;
384 }
385
386 /**
387 * Instantiate Columns.
388 *
389 * @return array $init_cols
390 */
391 public function get_columns_init() {
392 $cols = $this->get_columns();
393 $init_cols = array();
394 foreach ( $cols as $key => $val ) {
395 $init_cols[] = array( 'data' => esc_html( $key ) );
396 }
397 return $init_cols;
398 }
399
400 /**
401 * Get column defines.
402 *
403 * @return array $defines
404 */
405 public function get_columns_defines() {
406 $defines = array();
407 $defines[] = array(
408 'targets' => 'no-sort',
409 'orderable' => false,
410 );
411 $defines[] = array(
412 'targets' => 'manage-cb-column',
413 'className' => 'check-column collapsing',
414 );
415 $defines[] = array(
416 'targets' => 'manage-site-column',
417 'className' => 'column-site-bulk mainwp-site-cell collapsing',
418 );
419 $defines[] = array(
420 'targets' => 'manage-url-column',
421 'className' => 'mainwp-url-cell collapsing',
422 );
423 $defines[] = array(
424 'targets' => array( 'manage-last_sync-column', 'manage-last_post-column', 'manage-site_actions-column', 'extra-column' ),
425 'className' => 'collapsing',
426 );
427 $defines[] = array(
428 'targets' => array( 'manage-status_code-column' ),
429 'className' => 'left aligned collapsing',
430 );
431 $defines[] = array(
432 'targets' => array( 'manage-client_name-column' ),
433 'className' => 'left aligned',
434 );
435 $defines[] = array(
436 'targets' => array( 'manage-security-column' ),
437 'className' => 'center aligned collapsing',
438 );
439 $defines[] = array(
440 'targets' => array( 'manage-login-column', 'manage-wpcore_update-column', 'manage-plugin_update-column', 'manage-theme_update-column', 'manage-backup-column' ),
441 'className' => 'center aligned collapsing',
442 );
443 $defines[] = array(
444 'targets' => 'manage-update-column',
445 'className' => 'cented aligned collapsing',
446 );
447 $defines[] = array(
448 'targets' => 'manage-favicon-column',
449 'className' => 'collapsing',
450 );
451 $defines[] = array(
452 'targets' => 'manage-atarim_tasks-column',
453 'className' => 'center aligned collapsing',
454 );
455 $defines[] = array(
456 'targets' => array( 'manage-notes-column' ),
457 'className' => 'center aligned collapsing',
458 );
459 $defines[] = array(
460 'targets' => array( 'manage-site_preview-column' ),
461 'className' => 'center aligned collapsing',
462 );
463 $defines[] = array(
464 'targets' => array( 'manage-site_health-column' ),
465 'className' => 'center aligned collapsing',
466 );
467 $defines[] = array(
468 'targets' => array( 'manage-phpversion-column', 'manage-status-column' ),
469 'className' => 'collapsing',
470 );
471 $defines[] = array(
472 'targets' => array( 'manage-uptime-column' ),
473 'className' => 'right aligned collapsing',
474 );
475 $defines[] = array(
476 'targets' => array( 'manage-language-column' ),
477 'className' => 'center aligned collapsing',
478 );
479 $defines[] = array(
480 'targets' => array( 'manage-ip-column' ),
481 'className' => 'center aligned collapsing',
482 );
483 $defines[] = array(
484 'targets' => array( 'manage-index-column' ),
485 'className' => 'center aligned collapsing',
486 );
487 $defines[] = array(
488 'targets' => array( 'manage-wpcore_version-column' ),
489 'className' => 'right aligned collapsing',
490 );
491 $defines[] = array(
492 'targets' => array( 'manage-site_actions-column' ),
493 'className' => 'collapsing not-selectable',
494 );
495 return $defines;
496 }
497
498 /**
499 * Method generate_tabletop()
500 *
501 * Run the render_manage_sites_table_top menthod.
502 */
503 public function generate_tabletop() {
504 $this->render_manage_sites_table_top();
505 }
506
507 /**
508 * Create Bulk Actions Drop Down.
509 *
510 * @return array $actions Available bulk actions.
511 */
512 public function get_bulk_actions() {
513
514 $actions = array(
515 'sync' => esc_html__( 'Sync Data', 'mainwp' ),
516 'reconnect' => esc_html__( 'Reconnect', 'mainwp' ),
517 'suspend' => esc_html__( 'Suspend', 'mainwp' ),
518 'unsuspend' => esc_html__( 'Unsuspend', 'mainwp' ),
519 'refresh_favico' => esc_html__( 'Reload Favicon', 'mainwp' ),
520 'delete' => esc_html__( 'Remove', 'mainwp' ),
521 'open_wpadmin' => esc_html__( 'Go to WP Admin', 'mainwp' ),
522 'open_frontpage' => esc_html__( 'Go to Site', 'mainwp' ),
523 'update_plugins' => esc_html__( 'Update Plugins', 'mainwp' ),
524 'update_themes' => esc_html__( 'Update Themes', 'mainwp' ),
525 'update_wpcore' => esc_html__( 'Update WordPress', 'mainwp' ),
526 'update_translations' => esc_html__( 'Update Translations', 'mainwp' ),
527 'update_everything' => esc_html__( 'Update Everything', 'mainwp' ),
528 'check_abandoned_plugin' => esc_html__( 'Check Abandoned Plugins', 'mainwp' ),
529 'check_abandoned_theme' => esc_html__( 'Check Abandoned Themes', 'mainwp' ),
530 );
531
532 /**
533 * Filter: mainwp_managesites_bulk_actions
534 *
535 * Filters bulk actions on the Manage Sites page. Allows user to hook in new actions or remove default ones.
536 *
537 * @since Unknown
538 */
539 return apply_filters( 'mainwp_managesites_bulk_actions', $actions );
540 }
541
542 /**
543 * Render Manage Sites Table Top.
544 *
545 * @uses \MainWP\Dashboard\MainWP_DB_Common::instance()::get_groups_for_manage_sites()
546 */
547 public function render_manage_sites_table_top() { // phpcs:ignore -- NOSONAR - complexity.
548 $items_bulk = $this->get_bulk_actions();
549 $filters_row_style = 'display:none';
550
551 // phpcs:disable WordPress.Security.NonceVerification,Missing,Missing,Missing,Missing,Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
552 $selected_status = isset( $_REQUEST['status'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : '';
553 $selected_group = isset( $_REQUEST['g'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['g'] ) ) : '';
554 $selected_group_logic = isset( $_REQUEST['group_logic'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['group_logic'] ) ) : '';
555 $selected_client = isset( $_REQUEST['client'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['client'] ) ) : '';
556 $is_not = isset( $_REQUEST['isnot'] ) && ( 'yes' === $_REQUEST['isnot'] ) ? true : false;
557 $selected_one_time_siteids = isset( $_REQUEST['selected_sites'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['selected_sites'] ) ) : '';
558 $reset_filter = isset( $_REQUEST['reset'] ) && ( 'yes' === $_REQUEST['reset'] ) ? true : false;
559 // phpcs:enable WordPress.Security.NonceVerification,Missing,Missing,Missing,Missing,Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
560
561 if ( ! empty( $selected_one_time_siteids ) ) {
562 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_onetime_selected_siteids', $selected_one_time_siteids );
563 }
564
565 if ( ! $reset_filter && empty( $selected_status ) && empty( $selected_group ) && empty( $selected_client ) && empty( $selected_one_time_siteids ) && '' === $selected_group_logic ) {
566 $selected_status = get_user_option( 'mainwp_managesites_filter_status' );
567 $selected_group = get_user_option( 'mainwp_managesites_filter_group' );
568 $selected_client = get_user_option( 'mainwp_managesites_filter_client' );
569 $is_not = get_user_option( 'mainwp_managesites_filter_is_not' );
570 $selected_group_logic = get_user_option( 'mainwp_managesites_filter_group_logic' );
571 }
572 $selected_group_logic = ( 'and' === $selected_group_logic ) ? 'and' : 'or';
573
574 $default_filter = true;
575 if ( ! empty( $is_not ) || ( ! empty( $selected_status ) && 'all' !== $selected_status ) || ! empty( $selected_group ) || ! empty( $selected_client ) || 'and' === $selected_group_logic ) {
576 $filters_row_style = 'display:flex';
577 $default_filter = false;
578 }
579
580 ?>
581 <div class="ui stackable grid">
582 <div class="eight wide middle aligned column">
583 <div id="mainwp-sites-bulk-actions-menu" class="ui selection mini dropdown">
584 <div class="default text"><?php esc_html_e( 'Bulk Actions', 'mainwp' ); ?></div>
585 <i class="dropdown icon"></i>
586 <div class="menu">
587 <?php foreach ( $items_bulk as $value => $title ) : ?>
588 <div class="item" data-value="<?php echo esc_attr( $value ); ?>"><?php echo esc_html( $title ); ?></div>
589 <?php endforeach; ?>
590 </div>
591 </div>
592 <button class="ui mini basic button" id="mainwp-do-sites-bulk-actions"><?php esc_html_e( 'Apply', 'mainwp' ); ?></button>
593 </div>
594
595 <div class="eight wide right aligned middle aligned column">
596 <?php static::render_page_navigation_left_items(); ?>
597 </div>
598 </div>
599
600 <div class="ui stackable grid" id="mainwp-sites-filters-row" style="<?php echo esc_attr( $filters_row_style ); ?>">
601 <div class="twelve wide column">
602 <div class="ui selection mini compact dropdown seg_is_not" id="mainwp_is_not_site">
603 <input type="hidden" value="<?php echo $is_not ? 'yes' : ''; ?>">
604 <i class="dropdown icon"></i>
605 <div class="default text"><?php esc_html_e( 'Is', 'mainwp' ); ?></div>
606 <div class="menu">
607 <div class="item" data-value=""><?php esc_html_e( 'Is', 'mainwp' ); ?></div>
608 <div class="item" data-value="yes"><?php esc_html_e( 'Is not', 'mainwp' ); ?></div>
609 </div>
610 </div>
611 <div class="ui mini action input mainwp-tags-filter-action">
612 <div id="mainwp-filter-sites-group" class="ui selection multiple mini dropdown seg_site_tags">
613 <input type="hidden" value="<?php echo esc_html( $selected_group ); ?>">
614 <i class="dropdown icon"></i>
615 <div class="default text"><?php esc_html_e( 'All tags', 'mainwp' ); ?></div>
616 <div class="menu">
617 <?php
618 $groups = MainWP_DB_Common::instance()->get_groups_for_manage_sites();
619 foreach ( $groups as $group ) {
620 ?>
621 <div class="item" data-value="<?php echo intval( $group->id ); ?>"><?php echo esc_html( stripslashes( $group->name ) ); ?></div>
622 <?php
623 }
624 ?>
625 <div class="item" data-value="nogroups"><?php esc_html_e( 'No Tags', 'mainwp' ); ?></div>
626 </div>
627 </div>
628 <div id="mainwp-filter-sites-group-logic" class="ui basic mini dropdown button seg_site_tags_logic">
629 <input type="hidden" value="<?php echo esc_html( $selected_group_logic ); ?>">
630 <div class="text"><?php echo 'and' === $selected_group_logic ? esc_html__( 'Match all (AND)', 'mainwp' ) : esc_html__( 'Match any (OR)', 'mainwp' ); ?></div>
631 <i class="dropdown icon"></i>
632 <div class="menu">
633 <div class="item" data-value="or"><?php esc_html_e( 'Match any (OR)', 'mainwp' ); ?></div>
634 <div class="item" data-value="and"><?php esc_html_e( 'Match all (AND)', 'mainwp' ); ?></div>
635 </div>
636 </div>
637 </div>
638 <div class="ui selection mini dropdown seg_site_status" id="mainwp-filter-sites-status">
639 <input type="hidden" value="<?php echo esc_html( $selected_status ); ?>">
640 <div class="default text"><?php esc_html_e( 'All statuses', 'mainwp' ); ?></div>
641 <i class="dropdown icon"></i>
642 <div class="menu">
643 <div class="item" data-value="all" ><?php esc_html_e( 'All statuses', 'mainwp' ); ?></div>
644 <div class="item" data-value="connected"><?php esc_html_e( 'Connected', 'mainwp' ); ?></div>
645 <div class="item" data-value="disconnected"><?php esc_html_e( 'Disconnected', 'mainwp' ); ?></div>
646 <div class="item" data-value="suspended"><?php esc_html_e( 'Suspended', 'mainwp' ); ?></div>
647 <div class="item" data-value="update"><?php esc_html_e( 'Available update', 'mainwp' ); ?></div>
648 <div class="item" data-value="sitehealthnotgood"><?php esc_html_e( 'Site Health needs improvement', 'mainwp' ); ?></div>
649 <div class="item" data-value="phpver8"><?php esc_html_e( 'PHP < 8.0', 'mainwp' ); ?></div>
650 <div class="item" data-value="phpver81"><?php esc_html_e( 'PHP < 8.1', 'mainwp' ); ?></div>
651 <div class="item" data-value="phpver82"><?php esc_html_e( 'PHP < 8.2', 'mainwp' ); ?></div>
652 <div class="item" data-value="phpver83"><?php esc_html_e( 'PHP < 8.3', 'mainwp' ); ?></div>
653 <div class="item" data-value="phpver84"><?php esc_html_e( 'PHP < 8.4', 'mainwp' ); ?></div>
654 </div>
655 </div>
656 <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_clients' ) ) { ?>
657 <div id="mainwp-filter-clients" class="ui selection mini multiple dropdown seg_site_clients">
658 <input type="hidden" value="<?php echo esc_html( $selected_client ); ?>">
659 <i class="dropdown icon"></i>
660 <div class="default text"><?php esc_html_e( 'All clients', 'mainwp' ); ?></div>
661 <div class="menu">
662 <?php
663 $clients = MainWP_DB_Client::instance()->get_wp_client_by( 'all' );
664 foreach ( $clients as $client ) {
665 ?>
666 <div class="item" data-value="<?php echo intval( $client->client_id ); ?>"><?php echo esc_html( stripslashes( $client->name ) ); ?></div>
667 <?php
668 }
669 ?>
670 <div class="item" data-value="noclients"><?php esc_html_e( 'No Client', 'mainwp' ); ?></div>
671 </div>
672 </div>
673 <?php } ?>
674 <button onclick="mainwp_manage_sites_filter()" class="ui mini green basic button"><i class="filter icon"></i><?php esc_html_e( 'Filter', 'mainwp' ); ?></button>
675 <button onclick="mainwp_manage_sites_reset_filters(this)" id="mainwp_manage_sites_reset_filters" class="ui mini button" reset-filters="0" <?php echo $default_filter ? 'disabled="disabled"' : ''; ?>><i class="times icon"></i><?php esc_html_e( 'Reset', 'mainwp' ); ?></button>
676 </div>
677
678 <?php MainWP_Manage_Sites_Filter_Segment::get_instance()->render_filters_segment(); ?>
679
680 </div>
681 <?php
682 MainWP_UI::render_modal_save_segment();
683 }
684
685
686 /**
687 * Method render_page_navigation_left_items()
688 *
689 * Render page navigation left items.
690 */
691 public static function render_page_navigation_left_items() {
692 $siteViewMode = MainWP_Utility::get_siteview_mode();
693 $nonce = wp_create_nonce( 'viewmode' );
694 ?>
695 <span data-tooltip="<?php esc_html_e( 'Switch between Table or Grid view.', 'mainwp' ); ?>" data-position="bottom right" data-inverted="">
696 <div class="ui mini buttons view-mode-manage-site">
697 <a class="ui button basic <?php echo 'table' === $siteViewMode ? 'green' : ''; ?> icon" <?php echo 'table' === $siteViewMode ? 'style="pointer-events:none"' : ''; ?> href="admin.php?page=managesites&viewmode=table&modenonce=<?php echo esc_html( $nonce ); ?>">
698 <i class="bars icon"></i>
699 </a>
700 <a class="ui button basic <?php echo 'grid' === $siteViewMode ? 'green' : ''; ?> icon" <?php echo 'grid' === $siteViewMode ? 'style="pointer-events:none"' : ''; ?> href="admin.php?page=managesites&viewmode=grid&modenonce=<?php echo esc_html( $nonce ); ?>">
701 <i class="grid layout icon"></i>
702 </a>
703 </div>
704 </span>
705 <a href="#" class="ui mini basic button" id="mainwp-manage-sites-filter-toggle-button">
706 <i class="filter icon"></i> <?php esc_html_e( 'Show Filters', 'mainwp' ); ?>
707 </a>
708 <?php
709 }
710
711 /**
712 * Html output if no Child Sites are connected.
713 *
714 * @uses \MainWP\Dashboard\MainWP_DB::instance()::get_websites_count()
715 */
716 public function no_items() {
717 ?>
718 <div class="ui center aligned segment">
719 <i class="globe massive icon"></i>
720 <div class="ui header">
721 <?php esc_html_e( 'No websites connected to the MainWP Dashboard yet.', 'mainwp' ); ?>
722 </div>
723 <a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&do=new' ) ); ?>" class="ui big green button"><?php esc_html_e( 'Connect Your WordPress Sites', 'mainwp' ); ?></a>
724 <div class="ui sub header">
725 <?php
726 /* translators: 1: Opening anchor tag, 2: Closing anchor tag with external link icon */
727 printf( esc_html__( 'If all your child sites are missing from your MainWP Dashboard, please check this %1$shelp document%2$s.', 'mainwp' ), '<a href="https://docs.mainwp.com/troubleshooting/potential-issues" target="_blank">', '</a> <i class="external alternate icon"></i>' ); // NOSONAR - noopener - open safe.
728 ?>
729
730 </div>
731 </div>
732 <?php
733 }
734
735 /**
736 * Method has_items().
737 *
738 * Verify if items exist.
739 */
740 public function has_items() {
741 return ! empty( $this->items );
742 }
743
744 /**
745 * Prepare the items to be listed.
746 *
747 * @param bool $optimize true|false Whether or not to optimize.
748 *
749 * @uses \MainWP\Dashboard\MainWP_DB_Common::instance()::get_user_extension()
750 * @uses \MainWP\Dashboard\MainWP_DB::instance()::query()
751 * @uses \MainWP\Dashboard\MainWP_DB::instance()::get_sql_search_websites_for_current_user()
752 * @uses \MainWP\Dashboard\MainWP_DB::fetch_object()
753 * @uses \MainWP\Dashboard\MainWP_DB::data_seek()
754 * @uses \MainWP\Dashboard\MainWP_DB::num_rows()
755 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
756 * @uses \MainWP\Dashboard\MainWP_Utility::update_option()
757 */
758 public function prepare_items( $optimize = true ) { // phpcs:ignore -- NOSONAR -Current complexity is the only way to achieve desired results, pull request solutions appreciated.
759
760 if ( null === $this->userExtension ) {
761 $this->userExtension = MainWP_DB_Common::instance()->get_user_extension();
762 }
763
764 $orderby = 'wp.name';
765
766 $req_orderby = null;
767 $req_order = null;
768
769 $extra_view = apply_filters( 'mainwp_sitestable_prepare_extra_view', array( 'favi_icon', 'health_site_status' ) );
770 $extra_view = array_unique( $extra_view );
771
772 if ( $optimize ) {
773 // phpcs:disable WordPress.Security.NonceVerification,Missing,Missing,Missing,Missing,Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
774 if ( isset( $_REQUEST['order'] ) ) {
775 $order_values = MainWP_Utility::instance()->get_table_orders( $_REQUEST );
776 $req_orderby = $order_values['orderby'];
777 $req_order = $order_values['order'];
778 }
779 // phpcs:enable
780 if ( isset( $req_orderby ) ) {
781 if ( 'site' === $req_orderby ) {
782 $orderby = 'wp.name ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
783 } elseif ( 'site_combo' === $req_orderby ) {
784 $orderby = 'wp.name ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
785 } elseif ( 'url' === $req_orderby ) {
786 $orderby = 'wp.url ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
787 } elseif ( 'tags' === $req_orderby ) {
788 $orderby = 'GROUP_CONCAT(gr.name ORDER BY gr.name SEPARATOR ",") ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
789 } elseif ( 'update' === $req_orderby ) {
790 $orderby = 'CASE true
791 WHEN (offline_check_result = -1)
792 THEN 2
793 WHEN (wp_sync.sync_errors IS NOT NULL) AND (wp_sync.sync_errors <> "")
794 THEN 3
795 ELSE 4
796 + (CASE wp_upgrades WHEN "[]" THEN 0 ELSE 1 END)
797 + (CASE plugin_upgrades WHEN "[]" THEN 0 ELSE LENGTH(plugin_upgrades) - LENGTH(REPLACE(plugin_upgrades, "\"Name\":", "\"Name\"")) END)
798 + (CASE theme_upgrades WHEN "[]" THEN 0 ELSE LENGTH(theme_upgrades) - LENGTH(REPLACE(theme_upgrades, "\"Name\":", "\"Name\"")) END)
799 END ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
800 } elseif ( 'phpversion' === $req_orderby ) {
801 $orderby = " INET_ATON(
802 SUBSTRING_INDEX(
803 CONCAT(SUBSTRING_INDEX(owp_phpversion.value, '-', 1), '.0.0.0.0'),
804 '.', 4
805 )
806 ) " . ( 'asc' === $req_order ? 'asc' : 'desc' );
807
808 } elseif ( 'wpcore_version' === $req_orderby ) {
809 $orderby = ' wpversion_order_num ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
810 } elseif ( 'ip' === $req_orderby ) {
811 // Sort by Server IP (string sort covers both IPv4 and IPv6).
812 $orderby = ' wp.ip ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
813 } elseif ( 'status' === $req_orderby ) {
814 $orderby = 'CASE true
815 WHEN (offline_check_result = -1)
816 THEN 2
817 WHEN (wp_sync.sync_errors IS NOT NULL) AND (wp_sync.sync_errors <> "")
818 THEN 3
819 ELSE 4
820 + (CASE plugin_upgrades WHEN "[]" THEN 0 ELSE LENGTH(plugin_upgrades) - LENGTH(REPLACE(plugin_upgrades, "\"Name\":", "\"Name\"")) END)
821 + (CASE theme_upgrades WHEN "[]" THEN 0 ELSE LENGTH(theme_upgrades) - LENGTH(REPLACE(theme_upgrades, "\"Name\":", "\"Name\"")) END)
822 + (CASE wp_upgrades WHEN "[]" THEN 0 ELSE 1 END)
823 END ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
824 } elseif ( 'last_post' === $req_orderby ) {
825 $orderby = 'wp_sync.last_post_gmt ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
826 } elseif ( 'status_code' === $req_orderby ) {
827 $orderby = 'wp.http_response_code ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
828 } elseif ( 'added_datetime' === $req_orderby ) {
829 $orderby = 'added_timestamp ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
830 } elseif ( 'site_health' === $req_orderby ) {
831 $orderby = 'wp_sync.health_value ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
832 } elseif ( 'client_name' === $req_orderby ) {
833 $orderby = 'client_name ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
834 } elseif ( 'last_sync' === $req_orderby ) {
835 $orderby = 'wp_sync.dtsSync ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
836 } elseif ( 'security' === $req_orderby ) {
837 $orderby = 'wp.securityIssues ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
838 } elseif ( 'backup' === $req_orderby ) {
839 $orderby = 'primary_lasttime_backup ' . ( 'asc' === $req_order ? 'asc' : 'desc' );
840 if ( ! in_array( 'primary_lasttime_backup', $extra_view ) ) {
841 $extra_view[] = 'primary_lasttime_backup';
842 }
843 }
844 }
845 }
846
847 // phpcs:disable WordPress.Security.NonceVerification,Missing,Missing,Missing,Missing,Missing,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
848 if ( ! $optimize ) {
849 $perPage = 9999;
850 $start = 0;
851 } else {
852 $perPage = isset( $_REQUEST['length'] ) ? intval( $_REQUEST['length'] ) : 25;
853 if ( -1 === (int) $perPage ) {
854 $perPage = 9999;
855 }
856 $start = isset( $_REQUEST['start'] ) ? intval( $_REQUEST['start'] ) : 0;
857 }
858
859 $reset_filter = isset( $_REQUEST['reset'] ) && ( 'yes' === $_REQUEST['reset'] ) ? true : false;
860
861 $search = isset( $_REQUEST['search']['value'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search']['value'] ) ) : '';
862 $request_group_logic = isset( $_REQUEST['group_logic'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['group_logic'] ) ) : '';
863 $request_group_logic = in_array( $request_group_logic, array( 'and', 'or' ) ) ? $request_group_logic : '';
864 $get_saved_state = empty( $search ) && ! isset( $_REQUEST['g'] ) && ! isset( $_REQUEST['status'] ) && ! isset( $_REQUEST['client'] ) && 'and' !== $request_group_logic;
865 $get_all = ( '' === $search ) && ( isset( $_REQUEST['status'] ) && 'all' === $_REQUEST['status'] ) && empty( $_REQUEST['g'] ) && empty( $_REQUEST['client'] ) && 'and' !== $request_group_logic ? true : false;
866 $is_not = ( isset( $_REQUEST['isnot'] ) && 'yes' === $_REQUEST['isnot'] ) ? true : false;
867
868 if ( $reset_filter ) {
869 $get_all = false;
870 $get_saved_state = false;
871 }
872
873 $selected_one_time_siteids = get_user_option( 'mainwp_managesites_filter_onetime_selected_siteids' );
874
875 if ( ! empty( $selected_one_time_siteids ) ) {
876 $userid = get_current_user_id();
877 if ( ! empty( $userid ) ) {
878 delete_user_option( $userid, 'mainwp_managesites_filter_onetime_selected_siteids' );
879 $get_all = true;
880 } else {
881 $selected_one_time_siteids = '';
882 }
883 }
884
885 $group_ids = false;
886 $client_ids = false;
887 $site_status = '';
888 $group_logic = 'or';
889
890 if ( ! isset( $_REQUEST['status'] ) ) {
891 if ( $get_saved_state ) {
892 $site_status = get_user_option( 'mainwp_managesites_filter_status' );
893 } else {
894 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_status', '' );
895 }
896 } else {
897 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_status', sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) );
898 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_is_not', $is_not );
899 $site_status = sanitize_text_field( wp_unslash( $_REQUEST['status'] ) );
900 }
901
902 if ( $get_all && ! $selected_one_time_siteids ) {
903 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_group', '' );
904 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_client', '' );
905 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_group_logic', 'or' );
906 }
907
908 if ( ! $get_all ) {
909 if ( ! isset( $_REQUEST['g'] ) ) {
910 if ( $get_saved_state ) {
911 $group_ids = get_user_option( 'mainwp_managesites_filter_group' );
912 } else {
913 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_group', '' );
914 }
915 } else {
916 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_group', sanitize_text_field( wp_unslash( $_REQUEST['g'] ) ) );
917 $group_ids = sanitize_text_field( wp_unslash( $_REQUEST['g'] ) ); // may be multi groups.
918 }
919
920 if ( '' === $request_group_logic ) {
921 if ( $get_saved_state ) {
922 $group_logic = get_user_option( 'mainwp_managesites_filter_group_logic' );
923 } else {
924 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_group_logic', 'or' );
925 }
926 } else {
927 $group_logic = ( 'and' === $request_group_logic ) ? 'and' : 'or';
928 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_group_logic', $group_logic );
929 }
930
931 if ( ! isset( $_REQUEST['client'] ) ) {
932 if ( $get_saved_state ) {
933 $client_ids = get_user_option( 'mainwp_managesites_filter_client' );
934 } else {
935 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_client', '' );
936 }
937 } else {
938 MainWP_Utility::update_user_option( 'mainwp_managesites_filter_client', sanitize_text_field( wp_unslash( $_REQUEST['client'] ) ) );
939 $client_ids = sanitize_text_field( wp_unslash( $_REQUEST['client'] ) ); // may be multi groups.
940 }
941 }
942 $group_logic = ( 'and' === $group_logic ) ? 'and' : 'or';
943 // phpcs:enable
944
945 $where = null;
946
947 if ( '' !== $site_status && 'all' !== $site_status ) {
948 if ( 'connected' === $site_status ) {
949 $where = 'wp_sync.sync_errors = ""';
950 if ( $is_not ) {
951 $where = 'wp_sync.sync_errors <> ""';
952 }
953 } elseif ( 'disconnected' === $site_status ) {
954 $where = 'wp_sync.sync_errors <> ""';
955 if ( $is_not ) {
956 $where = 'wp_sync.sync_errors = ""';
957 }
958 } elseif ( 'update' === $site_status ) {
959 $available_update_ids = MainWP_Common_Functions::instance()->get_available_update_siteids();
960 if ( empty( $available_update_ids ) ) {
961 $where = 'wp.id = -1'; // so get empty results.
962 if ( $is_not ) {
963 $where = 'wp.id != -1'; // so query with all sites.
964 }
965 } else {
966 $where = 'wp.id IN (' . implode( ',', $available_update_ids ) . ') ';
967 if ( $is_not ) {
968 $where = 'wp.id NOT IN (' . implode( ',', $available_update_ids ) . ') ';
969 }
970 }
971 } elseif ( 'sitehealthnotgood' === $site_status ) {
972 $where = ' wp_sync.health_status = 1 ';
973 if ( $is_not ) {
974 $where = 'wp_sync.health_status = 0';
975 }
976 } elseif ( 'phpver8' === $site_status ) {
977 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '<', '8.0.0.0' ); // NOSONAR - no IP.
978 if ( $is_not ) {
979 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '>=', '8.0.0.0' ); // NOSONAR - no IP.
980 }
981 } elseif ( 'phpver81' === $site_status ) {
982 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '<', '8.1.0.0' ); // NOSONAR - no IP.
983 if ( $is_not ) {
984 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '>=', '8.1.0.0' ); // NOSONAR - no IP.
985 }
986 } elseif ( 'phpver82' === $site_status ) {
987 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '<', '8.2.0.0' ); // NOSONAR - no IP.
988 if ( $is_not ) {
989 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '>=', '8.2.0.0' ); // NOSONAR - no IP.
990 }
991 } elseif ( 'phpver83' === $site_status ) {
992 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '<', '8.3.0.0' ); // NOSONAR - no IP.
993 if ( $is_not ) {
994 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '>=', '8.3.0.0' ); // NOSONAR - no IP.
995 }
996 } elseif ( 'phpver84' === $site_status ) {
997 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '<', '8.4.0.0' ); // NOSONAR - no IP.
998 if ( $is_not ) {
999 $where = MainWP_DB_Common::instance()->get_sql_where_wpopt_phpversion( 'phpversion', '>=', '8.4.0.0' ); // NOSONAR - no IP.
1000 }
1001 } elseif ( 'suspended' === $site_status ) {
1002 $where = 'wp.suspended = 1'; // query for suspended sites.
1003 if ( $is_not ) {
1004 $where = 'wp.suspended = 0'; // query for not suspended sites.
1005 }
1006 }
1007 }
1008
1009 $total_params = array( 'count_only' => true );
1010
1011 if ( $get_all ) {
1012 $total_params['search'] = $search;
1013 $params = array(
1014 'selectgroups' => true,
1015 'orderby' => $orderby,
1016 'offset' => $start,
1017 'rowcount' => $perPage,
1018 'search' => $search,
1019 );
1020 } else {
1021
1022 $total_params['search'] = $search;
1023
1024 $params = array(
1025 'selectgroups' => true,
1026 'orderby' => $orderby,
1027 'offset' => $start,
1028 'rowcount' => $perPage,
1029 'search' => $search,
1030 );
1031
1032 $total_params['isnot'] = $is_not;
1033 $params['isnot'] = $is_not;
1034
1035 $qry_group_ids = array();
1036 if ( ! empty( $group_ids ) ) {
1037 $group_ids = explode( ',', $group_ids ); // convert to array.
1038 // to fix query deleted groups.
1039 $groups = MainWP_DB_Common::instance()->get_groups_for_manage_sites();
1040 foreach ( $groups as $gr ) {
1041 if ( in_array( $gr->id, $group_ids ) ) {
1042 $qry_group_ids[] = $gr->id;
1043 }
1044 }
1045 // to fix.
1046 if ( in_array( 'nogroups', $group_ids ) ) {
1047 $qry_group_ids[] = 'nogroups';
1048 }
1049 }
1050
1051 if ( ! empty( $qry_group_ids ) ) {
1052 $total_params['group_id'] = $qry_group_ids;
1053 $params['group_id'] = $qry_group_ids;
1054 }
1055
1056 $qry_client_ids = array();
1057 if ( ! empty( $client_ids ) ) {
1058 $client_ids = explode( ',', $client_ids ); // convert to array.
1059 // to fix query deleted client.
1060 $clients = MainWP_DB_Client::instance()->get_wp_client_by( 'all' );
1061 foreach ( $clients as $cl ) {
1062 if ( in_array( $cl->client_id, $client_ids ) ) {
1063 $qry_client_ids[] = $cl->client_id;
1064 }
1065 }
1066 // to fix.
1067 if ( in_array( 'noclients', $client_ids ) ) {
1068 $qry_client_ids[] = 'noclients';
1069 }
1070 }
1071
1072 if ( ! empty( $qry_client_ids ) ) {
1073 $total_params['client_id'] = $qry_client_ids;
1074 $params['client_id'] = $qry_client_ids;
1075 }
1076
1077 if ( ! empty( $where ) ) {
1078 $total_params['extra_where'] = $where;
1079 $params['extra_where'] = $where;
1080 }
1081 }
1082
1083 $total_params['group_logic'] = $group_logic;
1084 $params['group_logic'] = $group_logic;
1085
1086 if ( empty( $selected_one_time_siteids ) ) {
1087 $selected_one_time_siteids = isset( $_REQUEST['selected_sites'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['selected_sites'] ) ) : ''; //phpcs:ignore WordPress.Security.NonceVerification.Recommended
1088 }
1089
1090 if ( ! empty( $selected_one_time_siteids ) ) {
1091 $selected_siteids = explode( ',', $selected_one_time_siteids );
1092 $selected_siteids = MainWP_Utility::array_numeric_filter( $selected_siteids );
1093 if ( ! empty( $selected_siteids ) ) {
1094 $params['selected_sites'] = $selected_siteids;
1095 }
1096 }
1097
1098 $totalRecords = $this->get_total_sites_by_pramas( $total_params );
1099
1100 if ( 'wpcore_version' === $req_orderby ) {
1101 $extra_view[] = 'wpversion_order_num';
1102 }
1103
1104 $params['extra_view'] = $extra_view;
1105 $params['view'] = 'manage_site';
1106 $params['dev_log_query'] = 0;
1107
1108 if ( ! empty( $_POST['reset_sites_filters'] ) ) { // phpcs:ignore -- NOSONAR - ok.
1109 self::invalidate_manage_sites_cache();
1110 }
1111
1112 $cache_group = MainWP_Cache_Helper::CGR_SITES;
1113
1114 $cache_key = MainWP_Cache_Helper::get_cache_key( 'sites_ids', $cache_group, $params );
1115
1116 $had_empty_cache = false;
1117 // IMPORTANT: Skip cache when searching to prevent cached site IDs from restricting results.
1118 // When $_included_cache_ids is set, the SQL query adds "WHERE wp.id IN (cached_ids)" which
1119 // limits results to previously cached sites. This breaks search functionality because we need
1120 // to search across ALL sites, not just the subset that was cached during the last non-search query.
1121 if ( empty( $search ) ) {
1122 $cache_ids = MainWP_Cache_Helper::instance()->get_cache(
1123 $cache_key,
1124 $cache_group
1125 );
1126
1127 if ( '_get_cache_false' !== $cache_ids ) {
1128 if ( empty( $cache_ids ) ) {
1129 $params['_included_cache_ids'] = array( 0 ); // not found if get cached success but empty.
1130 $had_empty_cache = true;
1131 } else {
1132 $params['_included_cache_ids'] = $cache_ids;
1133 }
1134 }
1135 }
1136
1137 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_search_websites_for_current_user( $params ) );
1138
1139 $site_ids = array();
1140 while ( $websites && ( $site = MainWP_DB::fetch_object( $websites ) ) ) {
1141 $site_ids[] = $site->id;
1142 }
1143
1144 // If cached IDs were used but the query returned nothing, the cache entry is corrupt
1145 // (e.g. written before a previous LIMIT-offset bug). Self-heal: delete stale cache
1146 // and re-run the full query so this request still returns correct results.
1147 $used_cache_ids = ! empty( $params['_included_cache_ids'] );
1148 if ( $used_cache_ids && empty( $site_ids ) && ! $had_empty_cache ) {
1149 MainWP_Cache_Helper::instance()->delete_cache( $cache_key, $cache_group );
1150 unset( $params['_included_cache_ids'] );
1151 $websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_search_websites_for_current_user( $params ) );
1152 $site_ids = array();
1153 while ( $websites && ( $site = MainWP_DB::fetch_object( $websites ) ) ) {
1154 $site_ids[] = $site->id;
1155 }
1156 MainWP_Cache_Helper::add_cache( $cache_key, $cache_group, $site_ids );
1157 } else {
1158 // Set manage sites ids cache.
1159 MainWP_Cache_Helper::add_cache( $cache_key, $cache_group, $site_ids );
1160 }
1161
1162 /**
1163 * Action is being replaced with mainwp_sitestable_prepared_items
1164 *
1165 * @deprecated
1166 */
1167 do_action_deprecated( 'mainwp-sitestable-prepared-items', array( $websites, $site_ids ), '4.0.7.2', 'mainwp_sitestable_prepared_items' ); // NOSONAR - not IP.
1168
1169 /**
1170 * Action: mainwp_sitestable_prepared_items
1171 *
1172 * Fires before the Sites table itemes are prepared.
1173 *
1174 * @param object $websites Object containing child sites data.
1175 * @param array $site_ids Array containing IDs of all child sites.
1176 *
1177 * @since Unknown
1178 */
1179 do_action( 'mainwp_sitestable_prepared_items', $websites, $site_ids );
1180
1181 $this->items = $websites;
1182 $this->total_items = $totalRecords;
1183 }
1184
1185
1186 /**
1187 * Get total sites by params.
1188 *
1189 * @param array $params Params.
1190 *
1191 * @return int Total
1192 */
1193 public function get_total_sites_by_pramas( $params ) {
1194 $cache_group = MainWP_Cache_Helper::CGR_SITES;
1195 $cache_key = MainWP_Cache_Helper::get_cache_key( 'total_sites', $cache_group, $params );
1196
1197 return MainWP_Cache_Helper::instance()->get_cache(
1198 $cache_key,
1199 $cache_group,
1200 function ( $filters ) {
1201 $total_websites = MainWP_DB::instance()->query( MainWP_DB::instance()->get_sql_search_websites_for_current_user( $filters ) );
1202 $totalRecords = $total_websites ? MainWP_DB::num_rows( $total_websites ) : 0;
1203
1204 if ( MainWP_DB::is_result( $total_websites ) ) {
1205 MainWP_DB::free_result( $total_websites );
1206 }
1207 return $totalRecords;
1208 },
1209 array( $params )
1210 );
1211 }
1212
1213 /**
1214 * Handle invalidate manage sites cache group.
1215 */
1216 public static function invalidate_manage_sites_cache() {
1217 $invalidates = array(
1218 MainWP_Cache_Helper::CGR_SITES,
1219 MainWP_Cache_Helper::CGR_UPDATES,
1220 );
1221 foreach ( $invalidates as $value ) {
1222 MainWP_Cache_Helper::invalidate_cache_group( $value );
1223 }
1224 }
1225
1226 /**
1227 * Display the table.
1228 *
1229 * @param bool $optimize true|false Whether or not to optimize.
1230 */
1231 public function display( $optimize = true ) { // phpcs:ignore Generic.Classes.OpeningBraceSameLine.ContentAfterBrace -- NOSONAR - complexity.
1232
1233 $count = MainWP_DB::instance()->get_websites_count( null, false );
1234
1235 if ( empty( $count ) ) {
1236 /**
1237 * Action: mainwp_before_empty_manage_sites_placeholder
1238 *
1239 * Fires before the placeholder on the empty Manage Sites page.
1240 *
1241 * @since 6.0
1242 */
1243 do_action( 'mainwp_before_empty_manage_sites_placeholder' );
1244 ?>
1245 <div id="mainwp-manage-sites-empty" class="ui padded center aligned segment">
1246 <?php MainWP_UI::render_empty_page_placeholder( __( 'No sites connected yet.', 'mainwp' ), __( 'Connect your first WordPress site and start managing updates, security, and backups from one command center.', 'mainwp' ), '<em data-emoji=":globe_with_meridians:" class="big"></em>' ); ?>
1247 <div class="ui hidden divider"></div>
1248 <a href="<?php echo esc_url( admin_url( 'admin.php?page=managesites&do=new' ) ); ?>" class="ui big green button"><i class="plus icon"></i> <?php esc_html_e( 'Connect Your First Site', 'mainwp' ); ?></a>
1249 <div class="ui hidden divider"></div>
1250 <a class="ui grey text" href="https://docs.mainwp.com/getting-started/get-started-with-mainwp#add-a-site-to-your-dashboard"><?php esc_html_e( 'or learn how it works →', 'mainwp' ); ?></a>
1251 </div>
1252 <?php
1253 /**
1254 * Action: mainwp_after_empty_manage_sites_placeholder
1255 *
1256 * Fires after the placeholder on the empty Manage Sites page.
1257 *
1258 * @since 6.0
1259 */
1260 do_action( 'mainwp_after_empty_manage_sites_placeholder' );
1261
1262 return;
1263 }
1264
1265 $sites_per_page = get_option( 'mainwp_default_sites_per_page', 25 );
1266
1267 $sites_per_page = intval( $sites_per_page );
1268
1269 $pages_length = array(
1270 25 => '25',
1271 10 => '10',
1272 50 => '50',
1273 100 => '100',
1274 300 => '300',
1275 );
1276
1277 $pages_length = $pages_length + array( $sites_per_page => $sites_per_page );
1278 ksort( $pages_length );
1279
1280 if ( isset( $pages_length[-1] ) ) {
1281 unset( $pages_length[-1] );
1282 }
1283
1284 $pagelength_val = implode( ',', array_keys( $pages_length ) );
1285 $pagelength_title = implode( ',', array_values( $pages_length ) );
1286
1287 /**
1288 * Action: mainwp_before_manage_sites_table
1289 *
1290 * Fires before the Manage Sites table.
1291 *
1292 * @since 4.1
1293 */
1294 do_action( 'mainwp_before_manage_sites_table' );
1295 ?>
1296 <?php if ( MainWP_Utility::show_mainwp_message( 'notice', 'mainwp-columns-notice' ) ) : ?>
1297 <div class="ui message">
1298 <i class="close icon mainwp-notice-dismiss" notice-id="mainwp-columns-notice"></i>
1299 <?php
1300 /* translators: 1: Lightbulb emoji icon, 2: Cog icon */
1301 printf( esc_html__( '%1$s Tip: To hide or show a column, click the Page Settings (%2$s) button and select options from "Show columns". You can also rearrange columns by dragging them, and the new order will be saved automatically.', 'mainwp' ), '<em data-emoji=":bulb:" class="small"></em>', '<i class="cog fitted icon"></i>' );
1302 ?>
1303
1304 </div>
1305 <?php endif; ?>
1306 <div id="mainwp-loading-sites">
1307 <div class="ui active page dimmer">
1308 <div class="ui double text loader"><?php esc_html_e( 'Loading...', 'mainwp' ); ?></div>
1309 </div>
1310 </div>
1311 <div id="mainwp-manage-sites-table-container" style="opacity:0;">
1312 <table id="mainwp-manage-sites-table" style="width:100%;" class="ui selectable unstackable table mainwp-with-preview-table mainwp-manage-wpsites-table">
1313 <thead>
1314 <tr><?php $this->print_column_headers( $optimize, true ); ?></tr>
1315 </thead>
1316 </table>
1317 </div>
1318 <?php
1319 /**
1320 * Action: mainwp_after_manage_sites_table
1321 *
1322 * Fires after the Manage Sites table.
1323 *
1324 * @since 4.1
1325 */
1326 do_action( 'mainwp_after_manage_sites_table' );
1327 ?>
1328
1329
1330 <?php
1331 $table_features = array(
1332 'searching' => 'true',
1333 'paging' => 'true',
1334 'pagingType' => 'full_numbers',
1335 'info' => 'true',
1336 'colReorder' => ' {columns:":not(.check-column):not(.manage-site_actions-column)"} ',
1337 'stateSave' => 'true',
1338 'stateDuration' => '60 * 60 * 24 * 30',
1339 'order' => '[]',
1340 'scrollX' => 'true',
1341 'responsive' => 'true',
1342 'fixedColumns' => '',
1343 'searchDelay' => 500,
1344 );
1345
1346 /**
1347 * Filter: mainwp_sites_table_features
1348 *
1349 * Filter the Monitoring table features.
1350 *
1351 * @since 4.1
1352 */
1353 $table_features = apply_filters( 'mainwp_sites_table_features', $table_features );
1354 ?>
1355
1356 <script type="text/javascript">
1357 mainwp_manage_sites_screen_options = function () {
1358 jQuery( '#mainwp-manage-sites-screen-options-modal' ).modal( {
1359 allowMultiple: true,
1360 onHide: function () {
1361 let val = jQuery( '#mainwp_default_sites_per_page' ).val();
1362 let saved = jQuery( '#mainwp_default_sites_per_page' ).attr( 'saved-value' );
1363 if ( saved != val ) {
1364 jQuery( '#mainwp-manage-sites-table' ).DataTable().page.len( val );
1365 jQuery( '#mainwp-manage-sites-table' ).DataTable().state.save();
1366 }
1367 }
1368 } ).modal( 'show' );
1369
1370 jQuery( '#manage-sites-screen-options-form' ).submit( function() {
1371 if ( jQuery('input[name=reset_managersites_columns_order]').attr('value') == 1 ) {
1372 $manage_sites_table.colReorder.reset();
1373 }
1374 jQuery( '#mainwp-manage-sites-screen-options-modal' ).modal( 'hide' );
1375 } );
1376 return false;
1377 };
1378
1379 let responsive = <?php echo esc_js( $table_features['responsive'] ); ?>;
1380 if( jQuery( window ).width() > 1140 ) {
1381 responsive = false;
1382 }
1383
1384 jQuery( document ).ready( function( $ ) {
1385
1386 <?php if ( ! $optimize ) { ?>
1387 try {
1388 //jQuery( '#mainwp-sites-table-loader' ).hide();
1389 $manage_sites_table = jQuery( '#mainwp-manage-sites-table' )
1390 .DataTable( {
1391 "responsive": responsive,
1392 "searching" : <?php echo esc_js( $table_features['searching'] ); ?>,
1393 "paging" : <?php echo esc_js( $table_features['paging'] ); ?>,
1394 "pagingType" : "<?php echo esc_js( $table_features['pagingType'] ); ?>",
1395 "info" : <?php echo esc_js( $table_features['info'] ); ?>,
1396 "scrollX" : <?php echo esc_js( $table_features['scrollX'] ); ?>,
1397 "colReorder" : <?php echo $table_features['colReorder']; // phpcs:ignore -- specical chars. ?>,
1398 "stateSave" : <?php echo esc_js( $table_features['stateSave'] ); ?>,
1399 "stateDuration" : <?php echo esc_js( $table_features['stateDuration'] ); ?>,
1400 "order" : <?php echo $table_features['order']; // phpcs:ignore -- specical chars. ?>,
1401 <?php if ( isset( $table_features['fixedColumns'] ) && '' !== $table_features['fixedColumns'] ) : ?>
1402 "fixedColumns" : <?php echo esc_js( $table_features['fixedColumns'] ); ?>,
1403 <?php endif; ?>
1404 "lengthMenu" : [ [<?php echo esc_js( $pagelength_val ); ?>, -1 ], [<?php echo esc_js( $pagelength_title ); ?>, "All" ] ],
1405 "columnDefs": [
1406 {
1407 "targets": 'no-sort',
1408 "orderable": false
1409 },
1410 {
1411 "targets": 'manage-site-column',
1412 "type": 'natural-nohtml'
1413 },
1414 <?php do_action( 'mainwp_manage_sites_table_columns_defs' ); ?>
1415 ],
1416 "pageLength": <?php echo intval( $sites_per_page ); ?>,
1417 "initComplete": function( settings, json ) {
1418 },
1419 "language": {
1420 "emptyTable": "<?php esc_html_e( 'No websites found.', 'mainwp' ); ?>"
1421 },
1422 "drawCallback": function( settings ) {
1423 },
1424 deferRender: true,
1425 stateSaveParams: function (settings, data) {
1426 data._mwpschema = 1; // bump only when state shape changes
1427 },
1428 stateLoadParams: function (settings, data) {
1429 const schema = Number(data?._mwpschema ?? 1); // treat legacy states as schema 1
1430 if (schema !== 1) return false;
1431
1432 if (
1433 data?.columns &&
1434 data.columns.length !== settings.aoColumns.length
1435 ) {
1436 console.log('Skip applying saved manage sites state.');
1437 // Reject stale/incompatible saved state
1438 return false;
1439 }
1440 return true;
1441 },
1442 search: { regex: false, smart: false },
1443 orderMulti: false,
1444 searchDelay: <?php echo intval( $table_features['searchDelay'] ); ?>
1445 } );
1446
1447 } catch(err) {
1448 // to fix js error.
1449 console.log(err);
1450 }
1451 setTimeout(() => {
1452 mainwp_datatable_fix_menu_overflow('#mainwp-manage-sites-table' );
1453 }, 800);
1454 <?php } else { ?>
1455 try {
1456 //jQuery( '#mainwp-sites-table-loader' ).hide();
1457 $manage_sites_table = jQuery( '#mainwp-manage-sites-table' ).on( 'processing.dt', function ( e, settings, processing ) {
1458 jQuery( '#mainwp-loading-sites' ).css( 'display', processing ? 'block' : 'none' );
1459 if (!processing) {
1460 let tb = jQuery( '#mainwp-manage-sites-table' );
1461 tb.find( 'th[cell-cls]' ).each( function(){
1462 let ceIdx = this.cellIndex;
1463 let cls = jQuery( this ).attr( 'cell-cls' );
1464 jQuery( '#mainwp-manage-sites-table tr' ).each(function(){
1465 jQuery(this).find( 'td:eq(' + ceIdx + ')' ).addClass(cls);
1466 } );
1467 } );
1468 $( '#mainwp-manage-sites-table .ui.dropdown' ).dropdown();
1469 $( '#mainwp-manage-sites-table .ui.checkbox' ).checkbox();
1470 }
1471 } ).DataTable( {
1472 "ajax": {
1473 "url": ajaxurl,
1474 "type": "POST",
1475 "data": function ( d ) {
1476 return $.extend( {}, d, mainwp_secure_data( {
1477 action: 'mainwp_manage_sites_display_rows',
1478 status: jQuery("#mainwp-filter-sites-status").dropdown("get value"),
1479 g: jQuery("#mainwp-filter-sites-group").dropdown("get value"),
1480 group_logic: jQuery("#mainwp-filter-sites-group-logic").dropdown("get value"),
1481 client: jQuery("#mainwp-filter-clients").length ? jQuery("#mainwp-filter-clients").dropdown("get value") : '',
1482 isnot: jQuery("#mainwp_is_not_site").dropdown("get value"),
1483 reset_sites_filters: jQuery("#mainwp_manage_sites_reset_filters").attr('reset-filters')
1484 } )
1485 );
1486 },
1487 "dataSrc": function ( json ) {
1488 managesites_reset_bulk_actions_params();
1489 for ( let i=0, ien=json.data.length ; i < ien ; i++ ) {
1490 json.data[i].syncError = json.rowsInfo[i].syncError ? json.rowsInfo[i].syncError : false;
1491 json.data[i].rowClass = json.rowsInfo[i].rowClass;
1492 json.data[i].siteID = json.rowsInfo[i].siteID;
1493 json.data[i].siteUrl = json.rowsInfo[i].siteUrl;
1494 }
1495 return json.data;
1496 }
1497 },
1498 "responsive": responsive,
1499 "searching" : <?php echo esc_js( $table_features['searching'] ); ?>,
1500 "paging" : <?php echo esc_js( $table_features['paging'] ); ?>,
1501 "pagingType" : "<?php echo esc_js( $table_features['pagingType'] ); ?>",
1502 "info" : <?php echo esc_js( $table_features['info'] ); ?>,
1503 "colReorder" : <?php echo $table_features['colReorder']; // phpcs:ignore -- specical chars. ?>,
1504 "scrollX" : <?php echo esc_js( $table_features['scrollX'] ); ?>,
1505 "stateSave" : <?php echo esc_js( $table_features['stateSave'] ); ?>,
1506 "stateDuration" : <?php echo esc_js( $table_features['stateDuration'] ); ?>,
1507 "order" : <?php echo $table_features['order']; // phpcs:ignore -- specical chars. ?>,
1508 "fixedColumns" : <?php echo ! empty( $table_features['fixedColumns'] ) ? esc_js( $table_features['fixedColumns'] ) : '""'; ?>,
1509 "lengthMenu" : [ [<?php echo esc_js( $pagelength_val ); ?>, -1 ], [<?php echo esc_js( $pagelength_title ); ?>, "All"] ],
1510 serverSide: true,
1511 "pageLength": <?php echo intval( $sites_per_page ); ?>,
1512 "columnDefs": <?php echo wp_json_encode( $this->get_columns_defines() ); ?>,
1513 "columns": <?php echo wp_json_encode( $this->get_columns_init() ); ?>,
1514 "language": {
1515 "emptyTable": "<?php esc_html_e( 'No websites found.', 'mainwp' ); ?>"
1516 },
1517 "drawCallback": function( settings ) {
1518 this.api().tables().body().to$().attr( 'id', 'mainwp-manage-sites-body-table' );
1519 if ( typeof mainwp_preview_init_event !== "undefined" ) {
1520 mainwp_preview_init_event();
1521 }
1522 jQuery( '#mainwp-manage-sites-table-container' ).css( 'opacity', '1' );
1523 setTimeout(() => {
1524 mainwp_datatable_fix_menu_overflow('#mainwp-manage-sites-table');
1525 }, 1000);
1526 },
1527 "initComplete": function( settings, json ) {
1528 },
1529 rowCallback: function (row, data) {
1530 jQuery( row ).addClass(data.rowClass);
1531 jQuery( row ).attr( 'site-url', data.siteUrl );
1532 jQuery( row ).attr( 'siteid', data.siteID );
1533 jQuery( row ).attr( 'id', "child-site-" + data.siteID );
1534 if ( data.syncError ) {
1535 jQuery( row ).find( 'td.column-site-bulk' ).addClass( 'site-sync-error' );
1536 };
1537 },
1538 'select': {
1539 items: 'row',
1540 style: 'multi+shift',
1541 selector: 'tr>td.check-column'
1542 },
1543 stateSaveParams: function (settings, data) {
1544 data._mwpschema = 1; // stable schema version, not plugin version
1545 },
1546 stateLoadParams: function (settings, data) {
1547 const schema = Number(data?._mwpschema ?? 1); // treat legacy states as schema 1
1548 if (schema !== 1) return false;
1549
1550 if (
1551 data?.columns &&
1552 data.columns.length !== settings.aoColumns.length
1553 ) {
1554 console.log('Skip applying saved manage sites state.');
1555 // Reject stale/incompatible saved state
1556 return false;
1557 }
1558 return true;
1559 },
1560 search: { regex: false, smart: false }, // Make search cheaper on the server.
1561 orderMulti: false,
1562 searchDelay: <?php echo intval( $table_features['searchDelay'] ); ?>
1563 }).on('select', function (e, dt, type, indexes) {
1564 if( 'row' == type ){
1565 dt.rows(indexes)
1566 .nodes()
1567 .to$().find('td.check-column .ui.checkbox' ).checkbox('set checked');
1568 }
1569 }).on('deselect', function (e, dt, type, indexes) {
1570 if( 'row' == type ){
1571 dt.rows(indexes)
1572 .nodes()
1573 .to$().find('td.check-column .ui.checkbox' ).checkbox('set unchecked');
1574 }
1575 }).on( 'columns-reordered', function ( e, settings, details ) {
1576 setTimeout(() => {
1577 jQuery( '#mainwp-manage-sites-table .ui.dropdown' ).dropdown();
1578 jQuery( '#mainwp-manage-sites-table .ui.checkbox' ).checkbox();
1579 mainwp_datatable_fix_menu_overflow('#mainwp-manage-sites-table' );
1580 }, 1000);
1581 } );
1582 } catch(err) {
1583 // to fix js error.
1584 }
1585 <?php } ?>
1586 _init_manage_sites_screen = function() {
1587 <?php
1588 if ( empty( $count ) ) {
1589 ?>
1590 jQuery( '#mainwp-manage-sites-screen-options-modal input[type=checkbox][id^="mainwp_show_column_"]' ).each( function() {
1591 let col_id = jQuery( this ).attr( 'id' );
1592 col_id = col_id.replace( "mainwp_show_column_", "" );
1593 try {
1594 $manage_sites_table.column( '#' + col_id ).visible( false );
1595 } catch(err) {
1596 // to fix js error.
1597 }
1598 } );
1599 let cols = ['favicon', 'site_combo','update','site_health','last_sync','site_actions'];
1600 jQuery.each( cols, function ( index, value ) {
1601 try {
1602 $manage_sites_table.column( '#' + value ).visible( true );
1603 } catch(err) {
1604 // to fix js error.
1605 }
1606 } );
1607 <?php
1608 } else {
1609 ?>
1610 jQuery( '#mainwp-manage-sites-screen-options-modal input[type=checkbox][id^="mainwp_show_column_"]' ).each( function() {
1611 let col_id = jQuery( this ).attr( 'id' );
1612 col_id = col_id.replace( "mainwp_show_column_", "" );
1613 try {
1614 $manage_sites_table.column( '#' + col_id ).visible( jQuery(this).is( ':checked' ) );
1615 } catch(err) {
1616 // to fix js error.
1617 }
1618 } );
1619 <?php } ?>
1620 };
1621 _init_manage_sites_screen();
1622 } );
1623
1624 mainwp_manage_sites_filter = function() {
1625 <?php if ( ! $optimize ) { ?>
1626 let group = jQuery( "#mainwp-filter-sites-group" ).dropdown( "get value" );
1627 let groupLogic = jQuery( "#mainwp-filter-sites-group-logic" ).dropdown( "get value" ) || 'or';
1628 let status = jQuery( "#mainwp-filter-sites-status" ).dropdown( "get value" );
1629 let isNot = jQuery("#mainwp_is_not_site").dropdown("get value");
1630 let client = jQuery("#mainwp-filter-clients").dropdown("get value");
1631 let params = '';
1632 params += '&g=' + group;
1633 params += '&group_logic=' + groupLogic;
1634 params += '&client=' + client;
1635 if ( status != '' ) {
1636 params += '&status=' + status;
1637 }
1638 if ( 'yes' == isNot ){
1639 params += '&isnot=yes';
1640 }
1641 window.location = 'admin.php?page=managesites' + params;
1642 return false;
1643 <?php } else { ?>
1644 try {
1645 let tagLogic = jQuery("#mainwp-filter-sites-group-logic").dropdown('get value') || 'or';
1646 let defaultFilter = (jQuery( "#mainwp-filter-sites-group" ).dropdown('get value') == ''
1647 && jQuery("#mainwp-filter-clients").dropdown('get value') == ''
1648 && jQuery("#mainwp-filter-sites-status").dropdown('get value') == 'all'
1649 && jQuery("#mainwp_is_not_site").dropdown('get value') == ''
1650 && tagLogic == 'or');
1651
1652 if(defaultFilter){
1653 jQuery('#mainwp_manage_sites_reset_filters').attr('disabled', 'disabled');
1654 } else {
1655 jQuery('#mainwp_manage_sites_reset_filters').attr('disabled', false);
1656 }
1657
1658 $manage_sites_table.ajax.reload();
1659 } catch(err) {
1660 // to fix js error.
1661 }
1662 <?php } ?>
1663 };
1664 mainwp_manage_sites_reset_filters = function(resetObj) {
1665 <?php if ( ! $optimize ) { ?>
1666 window.location = 'admin.php?page=managesites&isnot=no';
1667 return false;
1668 <?php } else { ?>
1669 try {
1670 jQuery( "#mainwp-filter-sites-group" ).dropdown('clear');
1671 jQuery("#mainwp-filter-sites-group-logic").dropdown('set selected', 'or');
1672 jQuery("#mainwp-filter-clients").dropdown('clear');
1673 jQuery( "#mainwp-filter-sites-status" ).dropdown('set selected', 'all');
1674 jQuery("#mainwp_is_not_site").dropdown('set selected', '');
1675 jQuery(resetObj).attr('disabled','disabled');
1676 jQuery(resetObj).attr('reset-filters',1);
1677 $manage_sites_table.ajax.reload();
1678 jQuery(resetObj).attr('reset-filters',0);
1679 } catch(err) {
1680 // to fix js error.
1681 }
1682 <?php } ?>
1683 }
1684 </script>
1685 <?php
1686 }
1687
1688 /**
1689 * Return empty table place holders.
1690 */
1691 public function display_rows_or_placeholder() {
1692 if ( $this->has_items() ) {
1693 $this->display_rows();
1694 }
1695 }
1696
1697 /**
1698 * Get the column count.
1699 *
1700 * @return int Column Count.
1701 */
1702 public function get_column_count() {
1703 list ( $columns ) = $this->get_column_info();
1704 return count( $columns );
1705 }
1706
1707 /**
1708 * Echo the column headers.
1709 *
1710 * @param bool $optimize true|false Whether or not to optimise.
1711 * @param bool $top true|false.
1712 */
1713 public function print_column_headers( $optimize, $top = true ) { // phpcs:ignore -- NOSONAR - complex.
1714 list( $columns, $sortable ) = $this->get_column_info();
1715
1716 if ( ! empty( $columns['cb'] ) ) {
1717 $columns['cb'] = '<div class="ui checkbox"><input id="' . ( $top ? 'cb-select-all-top' : 'cb-select-all-bottom' ) . '" type="checkbox" /></div>';
1718 }
1719
1720 $def_columns = $this->get_default_columns();
1721 $def_columns['site_actions'] = '';
1722
1723 foreach ( $columns as $column_key => $column_display_name ) {
1724
1725 $class = array( 'manage-' . $column_key . '-column' );
1726 $attr = '';
1727 if ( ! isset( $def_columns[ $column_key ] ) ) {
1728 $class[] = 'extra-column';
1729 if ( $optimize ) {
1730 $attr = 'cell-cls="' . esc_html( "collapsing $column_key column-$column_key" ) . '"';
1731 }
1732 }
1733
1734 if ( 'cb' === $column_key ) {
1735 $class[] = 'check-column';
1736 $class[] = 'collapsing';
1737 }
1738
1739 if ( ! isset( $sortable[ $column_key ] ) ) {
1740 $class[] = 'no-sort';
1741 }
1742
1743 $tag = 'th';
1744 $id = "id='$column_key'";
1745
1746 if ( ! empty( $class ) ) {
1747 $class = "class='" . join( ' ', $class ) . "'";
1748 }
1749
1750 echo "<$tag $id $class $attr>$column_display_name</$tag>"; // phpcs:ignore WordPress.Security.EscapeOutput
1751 }
1752 }
1753
1754 /**
1755 * Get column info.
1756 */
1757 protected function get_column_info() {
1758
1759 if ( isset( $this->column_headers ) && is_array( $this->column_headers ) ) {
1760 $column_headers = array( array(), array(), array(), $this->get_default_primary_column_name() );
1761 foreach ( $this->column_headers as $key => $value ) {
1762 $column_headers[ $key ] = $value;
1763 }
1764
1765 return $column_headers;
1766 }
1767
1768 $columns = $this->get_columns();
1769
1770 $sortable_columns = $this->get_sortable_columns();
1771
1772 $_sortable = $sortable_columns;
1773
1774 $sortable = array();
1775 foreach ( $_sortable as $id => $data ) {
1776 if ( empty( $data ) ) {
1777 continue;
1778 }
1779
1780 $data = (array) $data;
1781 if ( ! isset( $data[1] ) ) {
1782 $data[1] = false;
1783 }
1784
1785 $sortable[ $id ] = $data;
1786 }
1787
1788 $primary = $this->get_default_primary_column_name();
1789 $this->column_headers = array( $columns, $sortable, $primary );
1790
1791 return $this->column_headers;
1792 }
1793
1794
1795 /**
1796 * Clear Items.
1797 *
1798 * @uses \MainWP\Dashboard\MainWP_DB::is_result()
1799 * @uses \MainWP\Dashboard\MainWP_DB::free_result()
1800 */
1801 public function clear_items() {
1802 if ( MainWP_DB::is_result( $this->items ) ) {
1803 MainWP_DB::free_result( $this->items );
1804 }
1805 }
1806
1807 /**
1808 * Get table rows.
1809 *
1810 * Optimize for shared hosting or big networks.
1811 *
1812 * @return array Rows html.
1813 *
1814 * @uses \MainWP\Dashboard\MainWP_Connect::get_favico_url()
1815 * @uses \MainWP\Dashboard\MainWP_DB::instance()::get_website_options_array()
1816 * @uses \MainWP\Dashboard\MainWP_Utility::get_http_codes()
1817 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize_file_name()
1818 * @uses \MainWP\Dashboard\MainWP_Utility::get_site_health()
1819 * @uses \MainWP\Dashboard\MainWP_Utility::esc_content()
1820 * @uses \MainWP\Dashboard\MainWP_Utility::format_timestamp()
1821 * @uses \MainWP\Dashboard\MainWP_Utility::get_timestamp()
1822 */
1823 public function ajax_get_datatable_rows() { // phpcs:ignore -- NOSONAR - complex function. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
1824 $all_rows = array();
1825 $info_rows = array();
1826 $use_favi = get_option( 'mainwp_use_favicon', 1 );
1827
1828 $http_error_codes = MainWP_Utility::get_http_codes();
1829
1830 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
1831
1832 $decodedIgnoredCores = ! empty( $userExtension->ignored_wp_upgrades ) ? json_decode( $userExtension->ignored_wp_upgrades, true ) : array();
1833 if ( ! is_array( $decodedIgnoredCores ) ) {
1834 $decodedIgnoredCores = array();
1835 }
1836
1837 $last24_time = MainWP_Uptime_Monitoring_Handle::get_hourly_key_by_timestamp( time() - DAY_IN_SECONDS );
1838
1839 if ( $this->items ) {
1840 foreach ( $this->items as $website ) {
1841 $rw_classes = $this->get_groups_classes( $website );
1842 $hasSyncErrors = ( '' !== $website['sync_errors'] );
1843 $suspendedSite = ( '0' !== $website['suspended'] );
1844
1845 $rw_classes = trim( $rw_classes );
1846 $rw_classes = 'child-site mainwp-child-site-' . intval( $website['id'] ) . ' ' . ( $hasSyncErrors ? 'error' : '' ) . ' ' . ( $suspendedSite ? 'suspended' : '' ) . ' ' . $rw_classes;
1847
1848 $info_item = array(
1849 'rowClass' => esc_html( $rw_classes ),
1850 'siteID' => $website['id'],
1851 'siteUrl' => $website['url'],
1852 'syncError' => ( '' !== $website['sync_errors'] ? true : false ),
1853 );
1854
1855 $total_wp_upgrades = 0;
1856 $total_plugin_upgrades = 0;
1857 $total_theme_upgrades = 0;
1858
1859 $total_ignored_updates = 0;
1860
1861 $site_options = MainWP_DB::instance()->get_website_options_array( $website, array( 'wp_upgrades', 'ignored_wp_upgrades', 'premium_upgrades', 'primary_lasttime_backup' ) );
1862 $wp_upgrades = isset( $site_options['wp_upgrades'] ) ? json_decode( $site_options['wp_upgrades'], true ) : array();
1863 $ignored_core_upgrades = isset( $site_options['ignored_wp_upgrades'] ) ? json_decode( $site_options['ignored_wp_upgrades'], true ) : array();
1864
1865 if ( $website['is_ignoreCoreUpdates'] || MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $ignored_core_upgrades, 'core', $total_ignored_updates ) || MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $decodedIgnoredCores, 'core', $total_ignored_updates ) ) {
1866 $wp_upgrades = array();
1867 }
1868
1869 if ( is_array( $wp_upgrades ) && ! empty( $wp_upgrades ) ) {
1870 ++$total_wp_upgrades;
1871 }
1872
1873 $plugin_upgrades = json_decode( $website['plugin_upgrades'], true );
1874
1875 if ( $website['is_ignorePluginUpdates'] ) {
1876 $plugin_upgrades = array();
1877 }
1878
1879 $theme_upgrades = json_decode( $website['theme_upgrades'], true );
1880
1881 if ( $website['is_ignoreThemeUpdates'] ) {
1882 $theme_upgrades = array();
1883 }
1884
1885 $decodedPremiumUpgrades = isset( $site_options['premium_upgrades'] ) ? json_decode( $site_options['premium_upgrades'], true ) : array();
1886
1887 if ( is_array( $decodedPremiumUpgrades ) ) {
1888 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
1889 $premiumUpgrade['premium'] = true;
1890 if ( 'plugin' === $premiumUpgrade['type'] ) {
1891 if ( ! is_array( $plugin_upgrades ) ) {
1892 $plugin_upgrades = array();
1893 }
1894 if ( ! $website['is_ignorePluginUpdates'] ) {
1895 $plugin_upgrades[ $crrSlug ] = $premiumUpgrade;
1896 }
1897 } elseif ( 'theme' === $premiumUpgrade['type'] ) {
1898 if ( ! is_array( $theme_upgrades ) ) {
1899 $theme_upgrades = array();
1900 }
1901 if ( ! $website['is_ignoreThemeUpdates'] ) {
1902 $theme_upgrades[ $crrSlug ] = $premiumUpgrade;
1903 }
1904 }
1905 }
1906 }
1907
1908 if ( is_array( $plugin_upgrades ) ) {
1909 $ignored_plugins = json_decode( $website['ignored_plugins'], true );
1910 if ( is_array( $ignored_plugins ) ) {
1911 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins, $total_ignored_updates );
1912 }
1913
1914 $ignored_plugins = json_decode( $this->userExtension->ignored_plugins, true );
1915 if ( is_array( $ignored_plugins ) ) {
1916 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins, $total_ignored_updates );
1917 }
1918 $total_plugin_upgrades += count( $plugin_upgrades );
1919 }
1920
1921 if ( is_array( $theme_upgrades ) ) {
1922 $ignored_themes = json_decode( $website['ignored_themes'], true );
1923 if ( is_array( $ignored_themes ) ) {
1924 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes, $total_ignored_updates );
1925 }
1926 $ignored_themes = json_decode( $this->userExtension->ignored_themes, true );
1927 if ( is_array( $ignored_themes ) ) {
1928 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes, $total_ignored_updates );
1929 }
1930 $total_theme_upgrades += count( $theme_upgrades );
1931 }
1932
1933 $total_updates = $total_wp_upgrades + $total_plugin_upgrades + $total_theme_upgrades;
1934
1935 $health_status = isset( $website['health_site_status'] ) ? json_decode( $website['health_site_status'], true ) : array();
1936 $hstatus = MainWP_Utility::get_site_health( $health_status );
1937
1938 $hval = $hstatus['val'];
1939 $critical = $hstatus['critical'];
1940
1941 if ( 80 <= $hval && empty( $critical ) ) {
1942 $site_health = '<a href="' . MainWP_Site_Open::get_open_site_admin_link( $website['id'] ) . '&location=' . esc_attr( base64_encode( 'site-health.php' ) ) . '" target="_blank" class="open_newwindow_wpadmin ui mini grey icon basic button" data-tooltip="' . esc_attr__( 'Health Score: ', 'mainwp' ) . $hval . '" data-position="left center" data-inverted=""><i class="heartbeat green icon"></i></a>'; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1943 } else {
1944 $site_health = '<a href="' . MainWP_Site_Open::get_open_site_admin_link( $website['id'] ) . '&location=' . esc_attr( base64_encode( 'site-health.php' ) ) . '" target="_blank" class="open_newwindow_wpadmin ui mini grey icon basic button" data-tooltip="' . esc_attr__( 'Health Score: ', 'mainwp' ) . $hval . esc_attr__( ' | Critical Issues: ', 'mainwp' ) . $critical . '" data-position="left center" data-inverted=""><i class="heartbeat yellow icon"></i></a>'; // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions -- base64_encode used for http encoding compatible.
1945 }
1946
1947 $note = html_entity_decode( $website['note'] );
1948 $esc_note = MainWP_Utility::esc_content( $note );
1949 $strip_note = wp_strip_all_tags( $esc_note );
1950
1951 $columns = $this->get_columns();
1952
1953 $cols_data = array();
1954
1955 $website = apply_filters( 'mainwp_sitestable_website', $website, $this->userExtension );
1956
1957 $site_icon = '';
1958 if ( $use_favi ) {
1959 $siteObj = (object) $website;
1960 $favi_url = MainWP_Connect::get_favico_url( $siteObj );
1961 $site_icon = MainWP_Manage_Sites::get_instance()->get_site_icon_display( $website['cust_site_icon_info'], $favi_url );
1962 }
1963
1964 $client_image = '';
1965 if ( $website['client_id'] > 0 ) {
1966 $client = MainWP_DB_Client::instance()->get_wp_client_by( 'client_id', $website['client_id'], true );
1967 $client_image = MainWP_Client_Handler::get_client_avatar( $client );
1968 } else {
1969 $client_image = '<i class="user circle grey big icon"></i>';
1970 }
1971
1972 $website_info = MainWP_DB::instance()->get_website_option( $website, 'site_info' );
1973 $website_info = ! empty( $website_info ) ? json_decode( $website_info, true ) : array();
1974
1975 foreach ( $columns as $column_name => $column_display_name ) {
1976
1977 $column_content = apply_filters( 'mainwp_sitestable_display_row_columns', false, $column_name, $website );
1978
1979 if ( false !== $column_content ) {
1980 $cols_data[ $column_name ] = $column_content;
1981 continue;
1982 }
1983
1984 ob_start();
1985 ?>
1986 <?php if ( 'cb' === $column_name ) { ?>
1987 <div class="ui checkbox"><input type="checkbox" value="<?php echo intval( $website['id'] ); ?>" /></div>
1988 <?php } elseif ( 'status' === $column_name ) { ?>
1989 <?php if ( $hasSyncErrors ) : ?>
1990 <span data-tooltip="<?php esc_attr_e( 'Disconnected', 'mainwp' ); ?>" data-position="right center" data-inverted=""><a class="mainwp_site_reconnect" href="#"><i class="red times large icon"></i></a></span>
1991 <?php else : ?>
1992 <?php if ( $suspendedSite ) : ?>
1993 <span data-tooltip="<?php esc_attr_e( 'Suspended', 'mainwp' ); ?>" data-position="right center" data-inverted=""><a class="managesites_syncdata" href="#"><i class="pause yellow large icon"></i></a></span>
1994 <?php else : ?>
1995 <span data-tooltip="<?php esc_attr_e( 'Connected', 'mainwp' ); ?>" data-position="right center" data-inverted=""><a class="managesites_syncdata" href="#"><i class="green large check icon"></i></a></span>
1996 <?php endif; ?>
1997 <?php endif; ?>
1998 <?php } elseif ( 'favicon' === $column_name ) { ?>
1999 <?php echo $site_icon; // phpcs:ignore WordPress.Security.EscapeOutput ?>
2000 <?php
2001 } elseif ( 'site_combo' === $column_name ) {
2002 $scb_id = $website['id'];
2003 ?>
2004 <i class="ui active inline loader tiny" style="display:none"></i>
2005 <span id="site-status-<?php echo esc_attr( $scb_id ); ?>" class="status hidden"></span>
2006 <?php if ( \mainwp_current_user_can( 'dashboard', 'access_wpadmin_on_child_sites' ) ) : ?>
2007 <a href="<?php MainWP_Site_Open::get_open_site_url( $website['id'] ); ?>" class="open_newwindow_wpadmin" target="_blank"><i class="sign in icon"></i></a>
2008 <?php endif; ?>
2009 <a href="<?php echo 'admin.php?page=managesites&dashboard=' . intval( $website['id'] ); ?>">
2010 <?php echo esc_attr( stripslashes( $website['name'] ) ); ?>
2011 </a>
2012 <div>
2013 <span class="ui small text">
2014 <a href="<?php echo esc_url( $website['url'] ); ?>" class="mainwp-may-hide-referrer open_site_url ui grey text" target="_blank">
2015 <?php echo esc_html( MainWP_Utility::get_nice_url( $website['url'] ) ); ?>
2016 </a>
2017 </span>
2018 </div>
2019 <?php
2020 } elseif ( 'site' === $column_name ) {
2021 $s_id = $website['id'];
2022 ?>
2023 <a href="<?php echo 'admin.php?page=managesites&dashboard=' . intval( $website['id'] ); ?>"><?php echo esc_attr( stripslashes( $website['name'] ) ); ?></a><i class="ui active inline loader tiny" style="display:none"></i>
2024 <span id="site-status-<?php echo esc_attr( $s_id ); ?>" class="status hidden"></span>
2025 <?php } elseif ( 'login' === $column_name ) { ?>
2026 <?php if ( ! \mainwp_current_user_can( 'dashboard', 'access_wpadmin_on_child_sites' ) ) : ?>
2027 <i class="sign in icon"></i>
2028 <?php else : ?>
2029 <a href="<?php MainWP_Site_Open::get_open_site_url( $website['id'] ); ?>" class="open_newwindow_wpadmin" target="_blank"><i class="sign in icon"></i></a>
2030 <?php endif; ?>
2031 <?php } elseif ( 'url' === $column_name ) { ?>
2032 <a href="<?php echo esc_url( $website['url'] ); ?>" class="mainwp-may-hide-referrer open_site_url" target="_blank"><?php echo esc_html( MainWP_Utility::get_nice_url( $website['url'] ) ); ?></a>
2033 <?php } elseif ( 'tags' === $column_name ) { ?>
2034 <?php echo MainWP_System_Utility::get_site_tags_belong( $website ); // phpcs:ignore WordPress.Security.EscapeOutput ?>
2035 <?php
2036 } elseif ( 'client_name' === $column_name ) {
2037 ?>
2038 <?php if ( ! empty( $website['client_name'] ) ) : ?>
2039 <a href="<?php echo 'admin.php?page=ManageClients&client_id=' . intval( $website['client_id'] ); ?>">
2040 <?php echo $client_image; //phpcs:ignore -- NOSONAR - ok.?> <?php echo esc_html( $website['client_name'] ); ?>
2041 </a>
2042 <?php else : ?>
2043 <?php echo $client_image; //phpcs:ignore -- NOSONAR - ok.?> <span><?php echo esc_html( 'Unassigned' ); ?></span>
2044 <?php endif; ?>
2045 <?php
2046 } elseif ( 'update' === $column_name ) {
2047 $ignored_info = ! empty( $total_ignored_updates ) ? ' (' . (int) $total_ignored_updates . ' updates ignored)' : '';
2048 ?>
2049 <a data-tooltip="<?php echo ! empty( $website['dtsSync'] ) ? esc_attr__( 'Last sync: ', 'mainwp' ) . MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $website['dtsSync'] ) ) : ''; echo $ignored_info; //phpcs:ignore -- ok. ?> " data-position="left center" data-inverted="" class="ui mini <?php echo esc_attr( MainWP_Utility::mainwp_get_update_count_class( $total_updates ) ); ?> button" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>">
2050 <i class="sync alternate icon"></i> <?php echo intval( $total_updates ); ?>
2051 </a>
2052 <?php } elseif ( 'wpcore_update' === $column_name ) { ?>
2053 <a class="ui mini <?php echo esc_attr( MainWP_Utility::mainwp_get_update_count_class( $total_wp_upgrades ) ); ?> button" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>&tab=wordpress-updates">
2054 <i class="sync alternate icon"></i> <?php echo intval( $total_wp_upgrades ); ?>
2055 </a>
2056 <?php } elseif ( 'plugin_update' === $column_name ) { ?>
2057 <a class="ui mini <?php echo esc_attr( MainWP_Utility::mainwp_get_update_count_class( $total_plugin_upgrades ) ); ?> button" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>">
2058 <i class="sync alternate icon"></i> <?php echo intval( $total_plugin_upgrades ); ?>
2059 </a>
2060 <?php } elseif ( 'theme_update' === $column_name ) { ?>
2061 <a class="ui mini <?php echo esc_attr( MainWP_Utility::mainwp_get_update_count_class( $total_theme_upgrades ) ); ?> button" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>&tab=themes-updates">
2062 <i class="sync alternate icon"></i> <?php echo intval( $total_theme_upgrades ); ?>
2063 </a>
2064 <?php } elseif ( 'wpcore_version' === $column_name ) { ?>
2065 <?php if ( ! empty( $website_info['wpversion'] ) ) : ?>
2066 <?php if ( $total_wp_upgrades > 0 && is_array( $wp_upgrades ) && ! empty( $wp_upgrades['new'] ) ) : ?>
2067 <a class="ui grey text" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>&tab=wordpress-updates"><i class="small red sync alternate icon"></i> <?php echo esc_html( $website_info['wpversion'] ); ?> <i class="tiny grey chevron right icon"></i> <?php echo esc_html( $wp_upgrades['new'] ); ?></a>
2068 <?php else : ?>
2069 <span class="ui grey text"><?php echo esc_html( $website_info['wpversion'] ); ?></span>
2070 <?php endif; ?>
2071 <?php endif; ?>
2072 <?php } elseif ( 'security' === $column_name ) { ?>
2073 <?php if ( ! empty( $website['securityIssues'] ) && '[]' !== $website['securityIssues'] ) : ?>
2074 <?php if ( 0 < $website['securityIssues'] ) : ?>
2075 <a href="admin.php?page=managesites&scanid=<?php echo intval( $website['id'] ); ?>" class="ui mini button" data-tooltip="<?php esc_attr_e( 'Click to review site hardening options.', 'mainwp' ); ?>" data-position="left center" data-inverted=""><i class="shield red icon"></i> <?php echo intval( $website['securityIssues'] ); ?></a>
2076 <?php else : ?>
2077 <a href="admin.php?page=managesites&scanid=<?php echo intval( $website['id'] ); ?>" class="ui mini button" data-tooltip="<?php esc_attr_e( 'Click to review site hardening options.', 'mainwp' ); ?>" data-position="left center" data-inverted=""><i class="shield green icon"></i> <?php esc_html_e( '0', 'mainwp' ); ?></a>
2078 <?php endif; ?>
2079 <?php else : ?>
2080 <a href="admin.php?page=managesites&scanid=<?php echo intval( $website['id'] ); ?>" class="ui mini button" data-tooltip="<?php esc_attr_e( 'Data not available. Site might be disconnected.', 'mainwp' ); ?>" data-position="left center" data-inverted=""><i class="shield grey icon"></i> <?php esc_html_e( '0', 'mainwp' ); ?></a>
2081 <?php endif; ?>
2082 <?php } elseif ( 'uptime' === $column_name ) { ?>
2083 <?php
2084 $uptime_status = MainWP_DB_Uptime_Monitoring::instance()->get_uptime_monitor_stat_hourly_by( $website['monitor_id'], 'last24', $last24_time );
2085 MainWP_Monitoring_Sites_List_Table::instance()->render_last24_uptime_status( $uptime_status, $last24_time );
2086 ?>
2087
2088 <?php } elseif ( 'last_sync' === $column_name ) { ?>
2089 <?php echo ! empty( $website['dtsSync'] ) ? '<span data-tooltip="' . MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $website['dtsSync'] ) ) . '" data-position="left center" data-inverted=""><i class="calendar outline icon"></i> ' . MainWP_Utility::time_elapsed_string( $website['dtsSync'] ) . '</span>' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?>
2090 <?php } elseif ( 'last_post' === $column_name ) { ?>
2091 <?php echo ! empty( $website['last_post_gmt'] ) ? '<span data-tooltip="' . MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $website['last_post_gmt'] ) ) . '" data-position="left center" data-inverted=""><i class="calendar outline icon"></i> ' . MainWP_Utility::time_elapsed_string( $website['last_post_gmt'] ) . '</span>' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?>
2092 <?php } elseif ( ! $this->site_health_disabled && 'site_health' === $column_name ) { ?>
2093 <?php if ( ! $hasSyncErrors ) : ?>
2094 <?php echo $site_health; //phpcs:ignore -- NOSONAR - ok.?>
2095 <?php else : ?>
2096 <span class="ui mini grey icon basic button" data-tooltip="<?php esc_attr_e( 'Data not available. Site might be disconnected.', 'mainwp' ); ?>" data-position="left center" data-inverted=""><i class="heartbeat grey icon"></i></span>
2097 <?php endif; ?>
2098 <?php } elseif ( 'status_code' === $column_name ) { ?>
2099 <?php
2100 if ( $website['http_response_code'] ) {
2101 $code = $website['http_response_code'];
2102 ?>
2103 <div class="ui small label">
2104 <?php echo esc_html( $code ); ?>
2105 <?php
2106 if ( isset( $http_error_codes[ $code ] ) ) {
2107 echo '<div class="detail">' . esc_html( $http_error_codes[ $code ] ) . '</div>';
2108 }
2109 ?>
2110 </div>
2111 <?php
2112 }
2113 ?>
2114 <?php
2115 } elseif ( 'notes' === $column_name ) {
2116 $st_id1 = $website['id'];
2117 ?>
2118 <?php if ( empty( $website['note'] ) ) : ?>
2119 <a href="javascript:void(0)" class="mainwp-edit-site-note ui mini grey icon basic button" id="mainwp-notes-<?php echo intval( $st_id1 ); ?>"><i class="sticky note outline grey icon"></i></a>
2120 <?php
2121 else :
2122 $st_id2 = $website['id'];
2123 ?>
2124 <a href="javascript:void(0)" class="mainwp-edit-site-note ui mini icon basic button" id="mainwp-notes-<?php echo intval( $st_id2 ); ?>" data-tooltip="<?php echo substr( wp_unslash( $strip_note ), 0, 100 ); // phpcs:ignore WordPress.Security.EscapeOutput ?>" data-position="left center" data-inverted=""><i class="sticky green note icon"></i></a>
2125 <?php
2126 endif;
2127 $nst_id1 = $website['id'];
2128 ?>
2129 <span style="display: none" id="mainwp-notes-<?php echo intval( $nst_id1 ); ?>-note"><?php echo wp_unslash( $esc_note ); // phpcs:ignore WordPress.Security.EscapeOutput ?></span>
2130 <?php } elseif ( 'phpversion' === $column_name ) { ?>
2131 <?php echo ! empty( $website['phpversion'] ) ? '<i class="php icon"></i> ' . esc_html( substr( $website['phpversion'], 0, 6 ) ) : ''; ?>
2132 <?php } elseif ( 'ip' === $column_name ) { ?>
2133 <?php echo ! empty( $website['ip'] ) ? esc_html( $website['ip'] ) : ''; ?>
2134 <?php } elseif ( 'language' === $column_name ) { ?>
2135 <?php MainWP_Utility::get_language_code_as_flag( ! empty( $website_info['site_lang'] ) ? $website_info['site_lang'] : '' ); ?>
2136 <?php } elseif ( 'index' === $column_name ) { ?>
2137 <?php MainWP_Utility::get_site_index_option_icon( isset( $website_info['site_public'] ) ? $website_info['site_public'] : '' ); ?>
2138 <?php } elseif ( 'added_datetime' === $column_name ) { ?>
2139 <?php echo ! empty( $website['added_timestamp'] ) ? '<span data-tooltip="' . MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $website['added_timestamp'] ) ) . '" data-position="left center" data-inverted=""><i class="calendar outline icon"></i> ' . MainWP_Utility::time_elapsed_string( $website['added_timestamp'] ) . '</span>' : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?>
2140 <?php } elseif ( 'site_actions' === $column_name ) { ?>
2141 <div class="ui right pointing dropdown" style="z-index: 99;">
2142 <a href="javascript:void(0)"><i class="ellipsis vertical icon"></i></a>
2143 <div class="menu" siteid="<?php echo intval( $website['id'] ); ?>">
2144 <?php if ( '' !== $website['sync_errors'] ) : ?>
2145 <a class="mainwp_site_reconnect item" href="#"><?php esc_html_e( 'Reconnect', 'mainwp' ); ?></a>
2146 <?php else : ?>
2147 <?php if ( \mainwp_current_user_can( 'dashboard', 'access_wpadmin_on_child_sites' ) ) : ?>
2148 <a href="<?php MainWP_Site_Open::get_open_site_url( $website['id'] ); ?>" class="open_newwindow_wpadmin item" target="_blank"><?php esc_html_e( 'Go To WP Admin', 'mainwp' ); ?></a>
2149 <?php endif; ?>
2150 <a class="managesites_syncdata item" href="#"><?php esc_html_e( 'Sync Data', 'mainwp' ); ?></a>
2151 <?php endif; ?>
2152 <?php if ( \mainwp_current_user_can( 'dashboard', 'access_individual_dashboard' ) ) : ?>
2153 <a class="item" href="admin.php?page=managesites&dashboard=<?php echo intval( $website['id'] ); ?>"><?php esc_html_e( 'Overview', 'mainwp' ); ?></a>
2154 <?php endif; ?>
2155 <?php if ( \mainwp_current_user_can( 'dashboard', 'edit_sites' ) ) : ?>
2156 <a class="item" href="admin.php?page=managesites&id=<?php echo intval( $website['id'] ); ?>"><?php esc_html_e( 'Settings', 'mainwp' ); ?></a>
2157 <?php endif; ?>
2158 <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_security_issues' ) ) : ?>
2159 <a class="item" href="admin.php?page=managesites&scanid=<?php echo intval( $website['id'] ); ?>"><?php esc_html_e( 'Site Hardening', 'mainwp' ); ?></a>
2160 <?php endif; ?>
2161 <a class="item" site-name="<?php echo esc_html( $website['name'] ); ?>" site-id="<?php echo esc_html( $website['id'] ); ?>" onclick="return managesites_remove( this )"><?php esc_html_e( 'Remove Site', 'mainwp' ); ?></a>
2162 <?php
2163 /**
2164 * Action: mainwp_manage_sites_action
2165 *
2166 * Adds custom manage sites action item.
2167 *
2168 * @param array $website Array containing website data.
2169 *
2170 * @since 4.1
2171 */
2172 do_action( 'mainwp_manage_sites_action', $website );
2173 ?>
2174 </div>
2175 </div>
2176 <?php
2177 } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
2178 echo call_user_func( array( $this, 'column_' . $column_name ), $website ); // phpcs:ignore WordPress.Security.EscapeOutput
2179 } else {
2180 echo $this->column_default( $website, $column_name ); // phpcs:ignore WordPress.Security.EscapeOutput
2181 }
2182 $cols_data[ $column_name ] = ob_get_clean();
2183 }
2184 $all_rows[] = $cols_data;
2185 $info_rows[] = $info_item;
2186 }
2187 }
2188 return array(
2189 'data' => $all_rows,
2190 'recordsTotal' => $this->total_items,
2191 'recordsFiltered' => $this->total_items,
2192 'rowsInfo' => $info_rows,
2193 );
2194 }
2195
2196 /**
2197 * Get groups classes row.
2198 *
2199 * @param array $item Array containing child site data.
2200 * @return mixed Single Row Classes Item.
2201 */
2202 public function get_groups_classes( $item ) {
2203 $rw_classes = '';
2204 if ( isset( $item['wpgroupids'] ) && ! empty( $item['wpgroupids'] ) ) {
2205 $group_class = $item['wpgroupids'];
2206 $group_class = explode( ',', $group_class );
2207 if ( is_array( $group_class ) ) {
2208 foreach ( $group_class as $_class ) {
2209 $_class = trim( $_class );
2210 $_class = 'group-' . MainWP_Utility::sanitize_file_name( $_class );
2211 $rw_classes .= ' ' . strtolower( $_class );
2212 }
2213 } else {
2214 $_class = MainWP_Utility::sanitize_file_name( $group_class );
2215 $rw_classes .= ' group-' . strtolower( $_class );
2216 }
2217 }
2218 return $rw_classes;
2219 }
2220
2221 /**
2222 * Fetch single row item.
2223 *
2224 * @return mixed Single Row Item.
2225 *
2226 * @uses \MainWP\Dashboard\MainWP_DB::is_result()
2227 * @uses \MainWP\Dashboard\MainWP_DB::fetch_array()
2228 */
2229 public function display_rows() {
2230 if ( MainWP_DB::is_result( $this->items ) ) {
2231 while ( $this->items && ( $item = MainWP_DB::fetch_array( $this->items ) ) ) {
2232 $this->single_row( $item );
2233 }
2234 }
2235 }
2236
2237 /**
2238 * Single Row.
2239 *
2240 * @param mixed $website Child Site.
2241 *
2242 * @uses \MainWP\Dashboard\MainWP_Utility::sanitize_file_name()
2243 */
2244 public function single_row( $website ) {
2245 $classes = $this->get_groups_classes( $website );
2246
2247 $hasSyncErrors = ( '' !== $website['sync_errors'] );
2248 $suspendedSite = ( '0' !== $website['suspended'] );
2249
2250 $classes = trim( $classes );
2251 $classes = ' class="child-site mainwp-child-site-' . intval( $website['id'] ) . ' ' . ( $hasSyncErrors ? 'error' : '' ) . ' ' . ( $suspendedSite ? 'suspended' : '' ) . ' ' . $classes . '"';
2252 echo '<tr id="child-site-' . intval( $website['id'] ) . '"' . esc_html( $classes ) . ' siteid="' . intval( $website['id'] ) . '" site-url="' . esc_url( $website['url'] ) . '">';
2253 $this->single_row_columns( $website );
2254 echo '</tr>';
2255 }
2256
2257
2258 /**
2259 * Columns for a single row.
2260 *
2261 * @param mixed $website Child Site.
2262 * @param bool $good_health Good site health info.
2263 *
2264 * @uses \MainWP\Dashboard\MainWP_Connect::get_favico_url()
2265 * @uses \MainWP\Dashboard\MainWP_DB::instance()::get_website_options_array()
2266 * @uses \MainWP\Dashboard\MainWP_Utility::get_site_health()
2267 * @uses \MainWP\Dashboard\MainWP_Utility::esc_content()
2268 * @uses \MainWP\Dashboard\MainWP_Utility::get_http_codes()
2269 * @uses \MainWP\Dashboard\MainWP_Utility::format_timestamp()
2270 * @uses \MainWP\Dashboard\MainWP_Utility::get_timestamp()
2271 */
2272 protected function single_row_columns( $website, $good_health = false ) { // phpcs:ignore -- NOSONAR - complex function. Current complexity is the only way to achieve desired results, pull request solutions appreciated.
2273
2274 $total_wp_upgrades = 0;
2275 $total_plugin_upgrades = 0;
2276 $total_theme_upgrades = 0;
2277
2278 $total_ignored_updates = 0;
2279
2280 $userExtension = MainWP_DB_Common::instance()->get_user_extension();
2281
2282 $decodedIgnoredCores = ! empty( $userExtension->ignored_wp_upgrades ) ? json_decode( $userExtension->ignored_wp_upgrades, true ) : array();
2283 if ( ! is_array( $decodedIgnoredCores ) ) {
2284 $decodedIgnoredCores = array();
2285 }
2286
2287 $site_options = MainWP_DB::instance()->get_website_options_array( $website, array( 'wp_upgrades', 'ignored_wp_upgrades', 'premium_upgrades', 'primary_lasttime_backup' ) );
2288 $wp_upgrades = isset( $site_options['wp_upgrades'] ) ? json_decode( $site_options['wp_upgrades'], true ) : array();
2289 $ignored_core_upgrades = isset( $site_options['ignored_wp_upgrades'] ) ? json_decode( $site_options['ignored_wp_upgrades'], true ) : array();
2290
2291 if ( $website['is_ignoreCoreUpdates'] || MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $ignored_core_upgrades, 'core', $total_ignored_updates ) || MainWP_Common_Functions::instance()->is_ignored_updates( $wp_upgrades, $decodedIgnoredCores, 'core', $total_ignored_updates ) ) {
2292 $wp_upgrades = array();
2293 }
2294
2295 if ( is_array( $wp_upgrades ) && ! empty( $wp_upgrades ) ) {
2296 ++$total_wp_upgrades;
2297 }
2298
2299 $plugin_upgrades = json_decode( $website['plugin_upgrades'], true );
2300
2301 if ( $website['is_ignorePluginUpdates'] ) {
2302 $plugin_upgrades = array();
2303 }
2304
2305 $theme_upgrades = json_decode( $website['theme_upgrades'], true );
2306
2307 if ( $website['is_ignoreThemeUpdates'] ) {
2308 $theme_upgrades = array();
2309 }
2310
2311 $decodedPremiumUpgrades = isset( $site_options['premium_upgrades'] ) ? json_decode( $site_options['premium_upgrades'], true ) : array();
2312 if ( is_array( $decodedPremiumUpgrades ) ) {
2313 foreach ( $decodedPremiumUpgrades as $crrSlug => $premiumUpgrade ) {
2314 $premiumUpgrade['premium'] = true;
2315
2316 if ( 'plugin' === $premiumUpgrade['type'] ) {
2317 if ( ! is_array( $plugin_upgrades ) ) {
2318 $plugin_upgrades = array();
2319 }
2320 if ( ! $website['is_ignorePluginUpdates'] ) {
2321 $plugin_upgrades[ $crrSlug ] = $premiumUpgrade;
2322 }
2323 } elseif ( 'theme' === $premiumUpgrade['type'] ) {
2324 if ( ! is_array( $theme_upgrades ) ) {
2325 $theme_upgrades = array();
2326 }
2327 if ( ! $website['is_ignoreThemeUpdates'] ) {
2328 $theme_upgrades[ $crrSlug ] = $premiumUpgrade;
2329 }
2330 }
2331 }
2332 }
2333
2334 if ( is_array( $plugin_upgrades ) ) {
2335
2336 $ignored_plugins = json_decode( $website['ignored_plugins'], true );
2337 if ( is_array( $ignored_plugins ) ) {
2338 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins, $total_ignored_updates );
2339
2340 }
2341
2342 $ignored_plugins = json_decode( $this->userExtension->ignored_plugins, true );
2343 if ( is_array( $ignored_plugins ) ) {
2344 $plugin_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $plugin_upgrades, $ignored_plugins, $total_ignored_updates );
2345 }
2346
2347 $total_plugin_upgrades += count( $plugin_upgrades );
2348 }
2349
2350 if ( is_array( $theme_upgrades ) ) {
2351
2352 $ignored_themes = json_decode( $website['ignored_themes'], true );
2353 if ( is_array( $ignored_themes ) ) {
2354 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes, $total_ignored_updates );
2355 }
2356
2357 $ignored_themes = json_decode( $this->userExtension->ignored_themes, true );
2358 if ( is_array( $ignored_themes ) ) {
2359 $theme_upgrades = MainWP_Common_Functions::instance()->get_not_ignored_updates_themesplugins( $theme_upgrades, $ignored_themes, $total_ignored_updates );
2360 }
2361
2362 $total_theme_upgrades += count( $theme_upgrades );
2363 }
2364
2365 $total_updates = $total_wp_upgrades + $total_plugin_upgrades + $total_theme_upgrades;
2366
2367 if ( 5 < $total_updates ) {
2368 $a_color = 'red';
2369 } elseif ( 0 < $total_updates && 5 >= $total_updates ) {
2370 $a_color = 'yellow';
2371 } else {
2372 $a_color = 'green';
2373 }
2374
2375 if ( 5 < $total_wp_upgrades ) {
2376 $w_color = 'red';
2377 } elseif ( 0 < $total_wp_upgrades && 5 >= $total_wp_upgrades ) {
2378 $w_color = 'yellow';
2379 } else {
2380 $w_color = 'green';
2381 }
2382
2383 if ( 5 < $total_plugin_upgrades ) {
2384 $p_color = 'red';
2385 } elseif ( 0 < $total_plugin_upgrades && 5 >= $total_plugin_upgrades ) {
2386 $p_color = 'yellow';
2387 } else {
2388 $p_color = 'green';
2389 }
2390
2391 if ( 5 < $total_theme_upgrades ) {
2392 $t_color = 'red';
2393 } elseif ( 0 < $total_theme_upgrades && 5 >= $total_theme_upgrades ) {
2394 $t_color = 'yellow';
2395 } else {
2396 $t_color = 'green';
2397 }
2398
2399 $hasSyncErrors = ( '' !== $website['sync_errors'] );
2400 $suspendedSite = ( '0' !== $website['suspended'] );
2401
2402 if ( $hasSyncErrors ) {
2403 $a_color = '';
2404 $w_color = '';
2405 $p_color = '';
2406 $t_color = '';
2407 }
2408
2409 $health_status = isset( $website['health_site_status'] ) ? json_decode( $website['health_site_status'], true ) : array();
2410 $hstatus = MainWP_Utility::get_site_health( $health_status );
2411 $hval = $hstatus['val'];
2412 $critical = $hstatus['critical'];
2413
2414 if ( 80 <= $hval && empty( $critical ) ) {
2415 $h_color = 'green';
2416 $h_text = esc_html__( 'Good', 'mainwp' );
2417 } else {
2418 $h_color = 'orange';
2419 $h_text = esc_html__( 'Should be improved', 'mainwp' );
2420 }
2421
2422 if ( $hasSyncErrors ) {
2423 $h_color = '';
2424 $h_color = '';
2425 }
2426
2427 $note = html_entity_decode( $website['note'] );
2428 $esc_note = MainWP_Utility::esc_content( $note );
2429 $strip_note = wp_strip_all_tags( $esc_note );
2430
2431 list( $columns ) = $this->get_column_info();
2432
2433 $use_favi = get_option( 'mainwp_use_favicon', 1 );
2434
2435 $http_error_codes = MainWP_Utility::get_http_codes();
2436
2437 $website = apply_filters( 'mainwp_sitestable_website', $website, $this->userExtension );
2438
2439 $imgfavi = '';
2440 if ( $use_favi ) {
2441 $siteObj = (object) $website;
2442 $favi_url = MainWP_Connect::get_favico_url( $siteObj );
2443 if ( ! empty( $favi_url ) ) {
2444 $imgfavi = '<img src="' . esc_attr( $favi_url ) . '" style="width:28px;height:28px;" class="ui circular image" />';
2445 } else {
2446 $imgfavi = '<i class="icon big wordpress"></i> '; // phpcs:ignore -- Prevent modify WP icon.
2447 }
2448 }
2449
2450 foreach ( $columns as $column_name => $column_display_name ) {
2451
2452 $classes = "collapsing center aligned $column_name column-$column_name";
2453 $attributes = "class='$classes'";
2454
2455 $rendered_custom_column = apply_filters( 'mainwp_sitestable_render_column', false, $column_name, $website, $classes );
2456 if ( $rendered_custom_column ) {
2457 continue;
2458 }
2459
2460 ?>
2461 <?php if ( 'cb' === $column_name ) { ?>
2462 <td class="check-column">
2463 <div class="ui checkbox">
2464 <input type="checkbox" value="<?php echo intval( $website['id'] ); ?>" name=""/>
2465 </div>
2466 </td>
2467 <?php } elseif ( 'status' === $column_name ) { ?>
2468 <td class="center aligned collapsing mainwp-status-cell">
2469 <?php if ( $hasSyncErrors ) : ?>
2470 <span><a class="mainwp_site_reconnect" href="#"><i class="circular inverted red unlink icon"></i></a></span>
2471 <?php else : ?>
2472 <span><a class="managesites_syncdata" href="#"><?php echo $suspendedSite ? '<i class="pause circular yellow inverted icon"></i>' : '<i class="circular inverted green check icon"></i>'; ?></a></span>
2473 <?php endif; ?>
2474 </td>
2475 <?php
2476 } elseif ( 'favicon' === $column_name ) {
2477 ?>
2478 <td class="collapsing no-sort mainwp-favicon-cell">
2479 <?php echo $imgfavi; // phpcs:ignore WordPress.Security.EscapeOutput ?>
2480 </td>
2481 <?php
2482 } elseif ( 'site' === $column_name ) {
2483 $cls_site = '';
2484 if ( '' !== $website['sync_errors'] ) {
2485 $cls_site = 'site-sync-error';
2486 }
2487 $sta_id = $website['id'];
2488 ?>
2489 <td class="column-site-bulk mainwp-site-cell collapsing all <?php echo esc_attr( $cls_site ); ?>"><a href="<?php echo 'admin.php?page=managesites&dashboard=' . intval( $website['id'] ); ?>"><?php echo esc_html( stripslashes( $website['name'] ) ); ?></a><i class="ui active inline loader tiny" style="display:none"></i>
2490 <span id="site-status-<?php echo esc_attr( $sta_id ); ?>" class="status hidden"></span></td>
2491 <?php } elseif ( 'login' === $column_name ) { ?>
2492 <td class="collapsing mainwp-wp-admin-cell">
2493 <?php if ( ! \mainwp_current_user_can( 'dashboard', 'access_wpadmin_on_child_sites' ) ) : ?>
2494 <i class="sign in icon"></i>
2495 <?php else : ?>
2496 <a href="<?php MainWP_Site_Open::get_open_site_url( $website['id'] ); ?>" class="open_newwindow_wpadmin" target="_blank"><i class="sign in icon"></i></a>
2497 <?php endif; ?>
2498 </td>
2499 <?php
2500 } elseif ( 'client_name' === $column_name ) {
2501 ?>
2502 <td class="collapsing mainwp-client-cell">
2503 <a href="<?php echo 'admin.php?page=ManageClients&client_id=' . intval( $website['client_id'] ); ?>"><?php echo esc_html( $website['client_name'] ); ?></a>
2504 </td>
2505 <?php
2506 } elseif ( 'url' === $column_name ) {
2507 ?>
2508 <td class="mainwp-url-cell collapsing"><a href="<?php echo esc_url( $website['url'] ); ?>" class="mainwp-may-hide-referrer open_site_url" target="_blank"><?php echo esc_html( MainWP_Utility::get_nice_url( $website['url'] ) ); ?></a></td>
2509 <?php
2510 } elseif ( 'tags' === $column_name ) {
2511 ?>
2512 <td class="collapsing mainwp-tags-cell"><?php echo MainWP_System_Utility::get_site_tags_belong( $website ); // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
2513 <?php
2514 } elseif ( 'update' === $column_name ) {
2515 ?>
2516 <td class="collapsing center aligned mainwp-update-cell"><a class="ui mini compact button <?php echo esc_attr( $a_color ); ?>" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>"><?php echo intval( $total_updates ); ?></a></td>
2517 <?php } elseif ( 'wpcore_update' === $column_name ) { ?>
2518 <td class="collapsing mainwp-wp-core-update-cell center aligned"><a class="ui basic mini compact button <?php echo esc_attr( $w_color ); ?>" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>&tab=wordpress-updates"><?php echo intval( $total_wp_upgrades ); ?></a></td>
2519 <?php } elseif ( 'plugin_update' === $column_name ) { ?>
2520 <td class="collapsing mainwp-plugin-update-cell center aligned"><a class="ui basic mini compact button <?php echo esc_attr( $p_color ); ?>" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>"><?php echo intval( $total_plugin_upgrades ); ?></a></td>
2521 <?php } elseif ( 'theme_update' === $column_name ) { ?>
2522 <td class="collapsing mainwp-theme-update-cell center aligned"><a class="ui basic mini compact button <?php echo esc_attr( $t_color ); ?>" href="admin.php?page=managesites&updateid=<?php echo intval( $website['id'] ); ?>&tab=themes-updates"><?php echo intval( $total_theme_upgrades ); ?></a></td>
2523 <?php } elseif ( 'last_sync' === $column_name ) { ?>
2524 <td class="collapsing mainwp-last-sync-cell"><?php echo ! empty( $website['dtsSync'] ) ? MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $website['dtsSync'] ) ) : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
2525 <?php } elseif ( 'last_post' === $column_name ) { ?>
2526 <td class="collapsing mainwp-last-post-cell"><?php echo ! empty( $website['last_post_gmt'] ) ? MainWP_Utility::format_timestamp( MainWP_Utility::get_timestamp( $website['last_post_gmt'] ) ) : ''; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
2527 <?php } elseif ( 'site_health' === $column_name ) { ?>
2528 <td class="collapsing mainwp-site-health-cell"><a class="open_newwindow_wpadmin" href="<?php MainWP_Site_Open::get_open_site_admin_link( $website['id'], true ); ?>&location=<?php echo esc_attr( base64_encode( 'site-health.php' ) ); // phpcs:ignore -- base64_encode used for http encoding compatible. ?>" target="_blank"><span class="ui <?php echo esc_attr( $h_color ); ?> empty circular label"></span></a> <?php echo esc_html( $h_text ); ?></td>
2529 <?php } elseif ( 'status_code' === $column_name ) { ?>
2530 <td class="collapsing mainwp-status-code-cell" data-order="<?php echo esc_html( $website['http_response_code'] ); ?>">
2531 <?php
2532 if ( $website['http_response_code'] ) {
2533 $code = $website['http_response_code'];
2534 echo esc_html( $code );
2535 if ( isset( $http_error_codes[ $code ] ) ) {
2536 echo ' - ' . esc_html( $http_error_codes[ $code ] );
2537 }
2538 }
2539 ?>
2540 </td>
2541 <?php } elseif ( 'notes' === $column_name ) { ?>
2542 <td class="collapsing center aligned mainwp-notes-cell">
2543 <?php
2544 if ( '' === $website['note'] ) :
2545 $not_id1 = $website['id'];
2546 ?>
2547 <a href="javascript:void(0)" class="mainwp-edit-site-note" id="mainwp-notes-<?php echo intval( $not_id1 ); ?>"><i class="sticky note outline icon"></i></a>
2548 <?php
2549 else :
2550 $not_id2 = $website['id'];
2551 ?>
2552 <a href="javascript:void(0)" class="mainwp-edit-site-note" id="mainwp-notes-<?php echo intval( $not_id2 ); ?>" data-tooltip="<?php echo substr( wp_unslash( $strip_note ), 0, 100 ); // phpcs:ignore WordPress.Security.EscapeOutput ?>" data-position="left center" data-inverted=""><i class="sticky green note icon"></i></a>
2553 <?php endif; ?>
2554 <span style="display: none" id="mainwp-notes-<?php echo intval( $website['id'] ); ?>-note"><?php echo wp_unslash( $esc_note ); // phpcs:ignore WordPress.Security.EscapeOutput ?></span>
2555 </td>
2556 <?php } elseif ( 'phpversion' === $column_name ) { ?>
2557 <td class="collapsing center aligned mainwp-php-cell"><?php echo esc_html( substr( $website['phpversion'], 0, 6 ) ); ?></td>
2558 <?php
2559 } elseif ( 'ip' === $column_name ) {
2560 ?>
2561 <td class="collapsing center aligned mainwp-ip-cell"><?php echo ! empty( $website['ip'] ) ? esc_html( $website['ip'] ) : ''; ?></td>
2562 <?php
2563 } elseif ( 'added_datetime' === $column_name ) {
2564 ?>
2565 <td class="collapsing center aligned mainwp-connected-cell" data-order="<?php echo intval( $website['added_timestamp'] ); ?>"><?php echo ! empty( $website['added_timestamp'] ) ? MainWP_Utility::format_date( MainWP_Utility::get_timestamp( $website['added_timestamp'] ) ) : 'N/A'; // phpcs:ignore WordPress.Security.EscapeOutput ?></td>
2566 <?php
2567 } elseif ( 'site_actions' === $column_name ) {
2568 ?>
2569 <td class="collapsing mainwp-site-actions-cell">
2570 <div class="ui right pointing dropdown" style="z-index: 99;">
2571 <a href="javascript:void(0)"><i class="ellipsis vertical icon"></i></a>
2572 <div class="menu" siteid="<?php echo intval( $website['id'] ); ?>">
2573 <?php if ( '' !== $website['sync_errors'] ) : ?>
2574 <a class="mainwp_site_reconnect item" href="#"><?php esc_html_e( 'Reconnect', 'mainwp' ); ?></a>
2575 <?php else : ?>
2576 <a class="managesites_syncdata item" href="#"><?php esc_html_e( 'Sync Data', 'mainwp' ); ?></a>
2577 <?php endif; ?>
2578 <?php if ( \mainwp_current_user_can( 'dashboard', 'access_individual_dashboard' ) ) : ?>
2579 <a class="item" href="admin.php?page=managesites&dashboard=<?php echo intval( $website['id'] ); ?>"><?php esc_html_e( 'Overview', 'mainwp' ); ?></a>
2580 <?php endif; ?>
2581 <?php if ( \mainwp_current_user_can( 'dashboard', 'edit_sites' ) ) : ?>
2582 <a class="item" href="admin.php?page=managesites&id=<?php echo intval( $website['id'] ); ?>"><?php esc_html_e( 'Settings', 'mainwp' ); ?></a>
2583 <?php endif; ?>
2584 <?php if ( \mainwp_current_user_can( 'dashboard', 'manage_security_issues' ) ) : ?>
2585 <a class="item" href="admin.php?page=managesites&scanid=<?php echo intval( $website['id'] ); ?>"><?php esc_html_e( 'Site Hardening', 'mainwp' ); ?></a>
2586 <?php endif; ?>
2587 <a class="item" site-name="<?php echo esc_html( $website['name'] ); ?>" site-id="<?php echo esc_html( $website['id'] ); ?>" onclick="return managesites_remove( this )"><?php esc_html_e( 'Remove Site', 'mainwp' ); ?></a>
2588 <?php
2589 /**
2590 * Action: mainwp_manage_sites_action
2591 *
2592 * Adds custom manage sites action item.
2593 *
2594 * @param array $website Array containing website data.
2595 *
2596 * @since 4.1
2597 */
2598 do_action( 'mainwp_manage_sites_action', $website );
2599 ?>
2600 </div>
2601 </div>
2602 </td>
2603 <?php
2604 } elseif ( method_exists( $this, 'column_' . $column_name ) ) {
2605 echo "<td $attributes>"; // phpcs:ignore WordPress.Security.EscapeOutput
2606 echo call_user_func( array( $this, 'column_' . $column_name ), $website ); // phpcs:ignore WordPress.Security.EscapeOutput
2607 echo '</td>';
2608 } else {
2609 echo "<td $attributes>"; // phpcs:ignore WordPress.Security.EscapeOutput
2610 echo $this->column_default( $website, $column_name ); // phpcs:ignore WordPress.Security.EscapeOutput
2611 echo '</td>';
2612 }
2613 }
2614 }
2615 }
2616