PluginProbe
MainWP Dashboard: Self-hosted WordPress Management for Agencies / 6.2.1
MainWP Dashboard: Self-hosted WordPress Management for Agencies v6.2.1
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
← All changes | modules/logs/classes/class-log-admin.php +139 -112 5.2 → 6.2.1 View file →
@@ -9,10 +9,12 @@
9 9 namespace MainWP\Dashboard\Module\Log;
10 10
11 11 use MainWP\Dashboard\MainWP_Logger;
12 12 use MainWP\Dashboard\MainWP_Post_Handler;
13 +use MainWP\Dashboard\MainWP_Utility;
14 +use MainWP\Dashboard\MainWP_DB;
15 +use MainWP\Dashboard\MainWP_Connect;
13 16
14 -
15 17 defined( 'ABSPATH' ) || exit;
16 18
17 19 use DateTime;
18 20 use DateTimeZone;
@@ -60,9 +62,8 @@
60 62 */
61 63 public function __construct( $manager ) {
62 64 $this->manager = $manager;
63 65 add_action( 'init', array( &$this, 'init' ) );
64 - add_filter( 'mainwp_getsubpages_settings', array( $this, 'add_subpage_menu_logs' ) );
65 66 // Load admin scripts and styles.
66 67 add_action(
67 68 'admin_enqueue_scripts',
68 69 array(
@@ -72,10 +73,18 @@
72 73 9
73 74 );
74 75
75 76 // Auto purge setup.
76 - add_action( 'wp_loaded', array( $this, 'hook_purge_scheduled_action' ) );
77 77 add_action( 'admin_init', array( $this, 'admin_init' ) );
78 + $log_page = Log_Insights_Page::instance();
79 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_delete_records', array( $this, 'ajax_delete_records' ) );
80 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_compact_records', array( $this, 'ajax_compact_records' ) );
81 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_clean_up_child_logs', array( $this, 'ajax_clean_up_child_logs' ) );
82 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_manage_events_display_rows', array( Log_Manage_Insights_Events_Page::instance(), 'ajax_manage_events_display_rows' ) );
83 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_widget_insights_display_rows', array( $log_page, 'ajax_events_display_rows' ) );
84 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_widget_events_overview_display_rows', array( $log_page, 'ajax_events_overview_display_rows' ) );
85 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_update_dismissed_db', array( $log_page, 'ajax_archive_dismissed_db' ) );
86 + MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_cancel_update_dismissed_db', array( $log_page, 'ajax_cancel_update_dismissed_db' ) );
78 87 }
79 88
80 89 /**
81 90 * Initiate Hooks
@@ -89,60 +98,24 @@
89 98 /**
90 99 * Handle admin_init action.
91 100 */
92 101 public function admin_init() {
93 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_display_rows', array( $this, 'ajax_display_rows' ) );
94 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_delete_records', array( $this, 'ajax_delete_records' ) );
95 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_compact_records', array( $this, 'ajax_compact_records' ) );
96 - MainWP_Post_Handler::instance()->add_action( 'mainwp_module_log_events_display_rows', array( Log_Insights_Page::instance(), 'ajax_events_display_rows' ) );
97 102 Log_Events_Filter_Segment::get_instance()->admin_init();
103 + $this->handle_post_archive_data();
98 104 }
99 105
100 -
101 106 /**
102 - * Init sub menu logs.
103 - *
104 - * @param array $subpages sub pages.
105 - *
106 - * @action init
107 + * Handle archive data action.
107 108 */
108 - public function add_subpage_menu_logs( $subpages = array() ) {
109 - $subpages[] = array(
110 - 'title' => esc_html__( 'Dashboard Insights', 'mainwp' ),
111 - 'slug' => 'DashboardInsights',
112 - 'callback' => array( $this, 'render_list_table' ),
113 - 'class' => 'mainwp-logs-menu',
114 - );
115 - return $subpages;
109 + public function handle_post_archive_data() {
110 + if ( isset( $_GET['clearArchivedSitesChangesData'] ) && isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'clear_archived_sites_changes' ) ) { // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
111 + Log_DB_Archive::instance()->truncate_archive_tables();
112 + wp_safe_redirect( esc_url( admin_url( 'admin.php?page=MainWPTools' ) ) );
113 + die();
114 + }
116 115 }
117 116
118 117 /**
119 - * Render main page
120 - */
121 - public function render_list_table() {
122 - $this->list_table = new Log_List_Table( $this->manager );
123 - /** This action is documented in ../pages/page-mainwp-manage-sites.php */
124 - do_action( 'mainwp_pageheader_settings', 'DashboardInsights' );
125 - ?>
126 - <div id="mainwp-manage-sites-content" class="ui segment">
127 - <div class="ui form">
128 - <h3 class="ui dividing header"><?php esc_html_e( 'Dashboard Insights', 'mainwp' ); ?></h3>
129 - <h4 class="ui header"><?php printf( esc_html__( 'Total logs size: %1$s (MB)', 'mainwp' ), esc_html( $this->get_db_size() ) ); ?></h4>
130 - <div id="mainwp-message-zone" style="display:none;" class="ui message"></div>
131 - <form method="post" class="mainwp-table-container">
132 - <?php
133 - wp_nonce_field( 'mainwp-admin-nonce' );
134 - $this->list_table->display();
135 - ?>
136 - </form>
137 - </div>
138 - </div>
139 - <?php
140 - /** This action is documented in ../pages/page-mainwp-manage-sites.php */
141 - do_action( 'mainwp_pagefooter_settings', 'DashboardInsights' );
142 - }
143 -
144 - /**
145 118 * Enqueue scripts/styles for admin screen
146 119 *
147 120 * @action admin_enqueue_scripts
148 121 *
@@ -150,9 +123,9 @@
150 123 *
151 124 * @return void
152 125 */
153 126 public function admin_enqueue_scripts( $hook ) {
154 - $script_screens = array( 'mainwp_page_InsightsOverview', 'mainwp_page_SettingsDashboardInsights', 'mainwp_page_SettingsInsights' );
127 + $script_screens = array( 'mainwp_page_InsightsOverview', 'mainwp_page_SettingsDashboardInsights', 'mainwp_page_SettingsInsights', 'mainwp_page_InsightsManage' );
155 128 wp_enqueue_style( 'mainwp-module-log-admin', $this->manager->locations['url'] . 'ui/css/admin.css', array(), $this->manager->get_version() );
156 129
157 130 if ( in_array( $hook, $script_screens, true ) ) {
158 131 wp_enqueue_script(
@@ -188,21 +161,33 @@
188 161 );
189 162 }
190 163 }
191 164
192 -
193 165 /**
194 - * Method ajax_display_rows()
166 + * Method hook_schedules_cron_listing().
195 167 *
196 - * Display table rows, optimize for shared hosting or big networks.
168 + * @param array $cron_list Cron info.
169 + * @return array Cron info.
197 170 */
198 - public function ajax_display_rows() {
199 - MainWP_Post_Handler::instance()->check_security( 'mainwp_module_log_display_rows' );
200 - $this->load_list_table();
201 - $this->list_table->prepare_items();
202 - $output = $this->list_table->ajax_get_datatable_rows();
203 - MainWP_Logger::instance()->log_execution_time( 'ajax_display_rows()' );
204 - wp_send_json( $output );
171 + public function hook_schedules_cron_listing( $cron_list = array() ) {
172 +
173 + if ( ! $this->manager->is_enabled_auto_archive_logs() ) {
174 + return $cron_list;
175 + }
176 +
177 + if ( ! is_array( $cron_list ) ) {
178 + $cron_list = array();
179 + }
180 + $start_lasttime = get_option( 'mainwp_module_log_last_time_auto_archive_logs', 0 );
181 + $start_nexttime = wp_next_scheduled( 'mainwp_module_log_cron_job_auto_archive' );
182 + $cron_list['mainwp_module_log_cron_job_auto_archive'] = array(
183 + 'title' => __( 'Auto archive Network Activity logs', 'mainwp' ),
184 + 'action' => 'mainwp_module_log_cron_job_auto_archive',
185 + 'frequency' => __( 'Once daily', 'mainwp' ),
186 + 'last_run' => empty( $start_lasttime ) ? 'N/A' : MainWP_Utility::format_timestamp( $start_lasttime ),
187 + 'next_run' => empty( $start_nexttime ) ? 'N/A' : MainWP_Utility::format_timestamp( $start_nexttime ),
188 + );
189 + return $cron_list;
205 190 }
206 191
207 192 /**
208 193 * Handle ajax delete logs records.
@@ -216,9 +201,9 @@
216 201 $start_time = ! empty( $start_date ) ? strtotime( $start_date . ' 00:00:00' ) : '';
217 202 $end_time = ! empty( $end_date ) ? strtotime( $end_date . ' 23:59:59' ) : '';
218 203
219 204 if ( ! is_numeric( $start_time ) || ! is_numeric( $end_time ) || $start_time > $end_time ) {
220 - die( wp_json_encode( array( 'error' => esc_html__( 'Invalid Start date or end date. Please try again.' ) ) ) );
205 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid Start date or end date. Please try again.', 'mainwp' ) ) ) );
221 206 }
222 207
223 208 $this->manager->db->create_compact_and_erase_records( $start_time, $end_time );
224 209
@@ -234,9 +219,9 @@
234 219
235 220 $year = isset( $_POST['year'] ) ? intval( $_POST['year'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
236 221
237 222 if ( $year < 2022 ) {
238 - die( wp_json_encode( array( 'error' => esc_html__( 'Invalid selected year. Please try again.' ) ) ) );
223 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid selected year. Please try again.', 'mainwp' ) ) ) );
239 224 }
240 225
241 226 $aday = $year . '-12-15'; // a day in last month.
242 227
@@ -248,20 +233,49 @@
248 233 wp_send_json( array( 'result' => 'SUCCESS' ) );
249 234 }
250 235
251 236 /**
252 - * Method load_sites_table()
253 - *
254 - * Load sites table.
237 + * Handle ajax clean up child logs.
255 238 */
256 - public function load_list_table() {
257 - $this->list_table = new Log_List_Table( $this->manager );
239 + public function ajax_clean_up_child_logs() {
240 + MainWP_Post_Handler::instance()->check_security( 'mainwp_module_log_clean_up_child_logs' );
241 +
242 + $siteid = isset( $_POST['siteid'] ) ? intval( $_POST['siteid'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification,WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
243 + $website = false;
244 +
245 + if ( $siteid > 0 ) {
246 + $website = MainWP_DB::instance()->get_website_by_id( $siteid );
247 + }
248 +
249 + if ( empty( $siteid ) || empty( $website ) ) {
250 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid site id or website not found. Please try again.', 'mainwp' ) ) ) );
251 + }
252 +
253 + $information = MainWP_Connect::fetch_url_authed( $website, 'clean_up_child_logs' );
254 +
255 + if ( ! is_array( $information ) ) {
256 + die( wp_json_encode( array( 'error' => esc_html__( 'Invalid response from child site. Please try again.', 'mainwp' ) ) ) );
257 + }
258 +
259 + $rsult = array();
260 + if ( isset( $information['success'] ) && 1 === intval( $information['success'] ) ) {
261 + $rsult['success'] = 1;
262 +
263 + if ( isset( $information['dbsize_activitylogs'] ) ) {
264 + MainWP_DB::instance()->update_website_option( $website, 'dbsize_activitylogs', $information['dbsize_activitylogs'] );
265 + }
266 + } elseif ( isset( $information['error'] ) ) {
267 + $rsult['error'] = $information['error'];
268 + }
269 +
270 + wp_send_json( $rsult );
258 271 }
259 272
260 -
261 273 /**
262 274 * Schedules a purge of records.
263 275 *
276 + * @compatible
277 + *
264 278 * @return void
265 279 */
266 280 public function hook_purge_scheduled_action() { //phpcs:ignore -- NOSONAR - complex.
267 281 $enable_schedule = is_array( $this->manager->settings->options ) && ! empty( $this->manager->settings->options['enabled'] ) && ! empty( $this->manager->settings->options['auto_purge'] ) ? true : false;
@@ -267,13 +281,11 @@
267 281 $enable_schedule = is_array( $this->manager->settings->options ) && ! empty( $this->manager->settings->options['enabled'] ) && ! empty( $this->manager->settings->options['auto_purge'] ) ? true : false;
268 282 if ( $enable_schedule ) {
269 283 $last_purge = get_option( 'mainwp_module_log_last_time_auto_purge_logs' );
270 284 $next_purge = get_option( 'mainwp_module_log_next_time_auto_purge_logs' );
271 - $days = false;
285 + $days = 100;
272 286 if ( is_array( $this->manager->settings->options ) && isset( $this->manager->settings->options['records_ttl'] ) ) {
273 287 $days = intval( $this->manager->settings->options['records_ttl'] );
274 - } else {
275 - $days = 100;
276 288 }
277 289
278 290 if ( defined( 'MAINWP_MODULE_LOG_KEEP_RECORDS_TTL' ) && is_numeric( MAINWP_MODULE_LOG_KEEP_RECORDS_TTL ) && MAINWP_MODULE_LOG_KEEP_RECORDS_TTL > 0 ) {
279 291 $days = MAINWP_MODULE_LOG_KEEP_RECORDS_TTL;
@@ -300,37 +312,65 @@
300 312 }
301 313
302 314
303 315 /**
304 - * Get db size.
316 + * Render logs db large size notice.
305 317 *
306 - * @return string Return current db size.
318 + * @param int $limit DB size limit in MByte, default 300 MB.
319 + * @param string $which The page slug where the notice is displayed.
307 320 */
308 - public function get_db_size() {
309 - $size = get_transient( 'mainwp_module_log_transient_db_logs_size' );
310 - if ( false !== $size ) {
311 - return $size;
321 + public function render_logs_db_notice( $limit = 300, $which = '' ) {
322 + if ( empty( $limit ) ) {
323 + $limit = 300; // MB.
312 324 }
325 + if ( MainWP_Utility::show_mainwp_message( 'notice', 'logs-db-size-large' ) ) {
326 + $size = Log_DB_Helper::instance()->get_db_size();
327 + if ( $size >= $limit ) {
328 + ?>
329 + <div class="ui yellow message" <?php echo 'overview' === $which || 'client_overview' === $which ? 'style="margin: 1em;"' : ''; ?>>
330 + <i class="close icon mainwp-notice-dismiss" notice-id="logs-db-size-large"></i>
331 + <?php
332 + /* translators: 1: Database size in MB, 2: Opening anchor tag, 3: Closing anchor tag */
333 + printf( esc_html__( 'Your Network Activity logs are using a lot of database space (%1$s MB). Go to %2$sMainWP > Settings > Network Activity Settings%3$s and enable Automatically archive logs, then set a Data retention period to keep the table size under control.', 'mainwp' ), esc_html( $size ), '<a href="admin.php?page=SettingsInsights#field-log-enable-auto-archive">', '</a>' ); // NOSONAR - noopener - open safe.
334 + ?>
335 + </div>
336 + <?php
337 + }
338 + }
339 + }
313 340
314 - global $wpdb;
315 - $sql = $wpdb->prepare(
316 - 'SELECT
317 - ROUND(SUM(DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2)
318 - FROM INFORMATION_SCHEMA.TABLES
319 - WHERE
320 - TABLE_SCHEMA = %s
321 - AND table_name = %s
322 - OR table_name = %s',
323 - $wpdb->dbname,
324 - $wpdb->mainwp_tbl_logs,
325 - $wpdb->mainwp_tbl_logs_meta
326 - );
327 -
328 - $dbsize_mb = $wpdb->get_var( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery -- prepared SQL.
329 -
330 - set_transient( 'mainwp_module_log_transient_db_logs_size', $dbsize_mb, 15 * MINUTE_IN_SECONDS );
331 -
332 - return $dbsize_mb;
341 + /**
342 + * Render logs db update notice.
343 + */
344 + public function render_update_db_notice() {
345 + $status = '';
346 + $dbver = Log_Install::instance()->get_current_logs_db_ver();
347 + if ( version_compare( $dbver, '1.0.1.26', '=' ) && ! get_option( 'mainwp_module_logs_updates_dismissed_db_cancelled' ) ) { // NOSONAR - no ip,checks ver <= 22 only.
348 + $status = get_option( 'mainwp_module_logs_updates_dismissed_db_process_status', '' );
349 + }
350 + ?>
351 + <div class="ui green message" id="module-log-update-dissmised-logs-running" style="display:none;"></div>
352 + <?php
353 + if ( 'require_update' === $status && MainWP_Utility::show_mainwp_message( 'notice', 'logs-db-update-required' ) ) {
354 + delete_option( 'mainwp_module_logs_updates_dismissed_db_cancelled' ); // To ensure it does not retrieve old saved values.
355 + ?>
356 + <div class="ui yellow message">
357 + <i class="close icon mainwp-notice-dismiss" notice-id="logs-db-update-required"></i>
358 + <?php
359 + /* translators: 1: Opening anchor tag, 2: Closing anchor tag */
360 + printf( esc_html__( 'Your \'Network Activity\' database needs to be updated. Click %1$shere%2$s to start the update.', 'mainwp' ), '<a href="javascript:void(0);" id="module-update-logs-db-requirement">', '</a>' );
361 + ?>
362 + </div>
363 + <?php
364 + } elseif ( 'running' === $status ) {
365 + ?>
366 + <script type="text/javascript">
367 + jQuery(function ($) {
368 + mainwp_module_logs_start_update_dismissed_db();
369 + });
370 + </script>
371 + <?php
372 + }
333 373 }
334 374
335 375 /**
336 376 * Get WP users.
@@ -337,23 +377,10 @@
337 377 *
338 378 * @return array Array of users.
339 379 */
340 380 public function get_all_users() {
341 - $list_users = array();
342 - $all_users = get_users();
343 - if ( is_array( $all_users ) ) {
344 - foreach ( $all_users as $user ) {
345 - if ( empty( $user->ID ) ) {
346 - continue;
347 - }
348 - $fields = array();
349 - $fields['id'] = $user->ID;
350 - $fields['login'] = $user->user_login;
351 - $fields['nicename'] = $user->user_nicename;
352 - $list_users[] = $fields;
353 - }
354 - }
355 - return $list_users;
381 + $users_sites = Log_DB_Helper::instance()->get_logs_users();
382 + return ! empty( $users_sites ) ? $users_sites : array();
356 383 }
357 384
358 385 /**
359 386 * Method mainwp_help_content()
@@ -365,11 +392,11 @@
365 392 if ( isset( $_GET['page'] ) && in_array( $_GET['page'], $allow_pages, true ) ) { //phpcs:ignore WordPress.Security.NonceVerification.Recommended
366 393 ?>
367 394 <p><?php esc_html_e( 'If you need help with the Dashboard Insights module, please review following help documents', 'mainwp' ); ?></p>
368 395 <div class="ui list">
369 - <div class="item"><i class="external alternate icon"></i> <a href="https://kb.mainwp.com/docs/dashboard-insights/" target="_blank">Dashboard Insights</a></div> <?php // NOSONAR -- compatible with help. ?>
370 - <div class="item"><i class="external alternate icon"></i> <a href="https://kb.mainwp.com/docs/dashboard-insights/#comprehensive-filtering-options" target="_blank">Filtering Options</a></div> <?php // NOSONAR -- compatible with help. ?>
371 - <div class="item"><i class="external alternate icon"></i> <a href="https://kb.mainwp.com/docs/dashboard-insights/#export-the-data-and-charts-from-an-individual-widget" target="_blank">Export Insights Data</a></div> <?php // NOSONAR -- compatible with help. ?>
396 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/add-ons/security/dashboard-insights-extension#dashboard-insights" target="_blank">Dashboard Insights</a></div> <?php // NOSONAR -- compatible with help. ?>
397 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/add-ons/security/dashboard-insights-extension#comprehensive-filtering-options" target="_blank">Filtering Options</a></div> <?php // NOSONAR -- compatible with help. ?>
398 + <div class="item"><i class="external alternate icon"></i> <a href="https://docs.mainwp.com/add-ons/security/dashboard-insights-extension#export-the-data-and-charts-from-an-individual-widget" target="_blank">Export Insights Data</a></div> <?php // NOSONAR -- compatible with help. ?>
372 399 <?php
373 400 /**
374 401 * Action: mainwp_module_dashboard_insights_help_item
375 402 *